Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 1 | // Copyright 2006 Google Inc. All Rights Reserved. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | package com.google.devtools.build.lib.syntax; |
| 16 | |
Han-Wen Nienhuys | 6682a31 | 2015-02-26 14:51:57 +0000 | [diff] [blame^] | 17 | import static org.junit.Assert.assertEquals; |
| 18 | import static org.junit.Assert.assertFalse; |
| 19 | import static org.junit.Assert.assertTrue; |
| 20 | import static org.junit.Assert.fail; |
| 21 | |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 22 | import com.google.common.collect.Lists; |
| 23 | |
Han-Wen Nienhuys | 6682a31 | 2015-02-26 14:51:57 +0000 | [diff] [blame^] | 24 | import org.junit.Test; |
| 25 | import org.junit.runner.RunWith; |
| 26 | import org.junit.runners.JUnit4; |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 27 | |
| 28 | import java.util.Arrays; |
| 29 | import java.util.IllegalFormatException; |
| 30 | import java.util.LinkedHashMap; |
| 31 | import java.util.List; |
| 32 | import java.util.Map; |
| 33 | |
| 34 | /** |
| 35 | * Test properties of the evaluator's datatypes and utility functions |
| 36 | * without actually creating any parse trees. |
| 37 | */ |
Han-Wen Nienhuys | 6682a31 | 2015-02-26 14:51:57 +0000 | [diff] [blame^] | 38 | @RunWith(JUnit4.class) |
| 39 | public class EvalUtilsTest { |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 40 | |
| 41 | private static List<?> makeList(Object ...args) { |
| 42 | return EvalUtils.makeSequence(Arrays.<Object>asList(args), false); |
| 43 | } |
| 44 | private static List<?> makeTuple(Object ...args) { |
| 45 | return EvalUtils.makeSequence(Arrays.<Object>asList(args), true); |
| 46 | } |
| 47 | private static Map<Object, Object> makeDict() { |
| 48 | return new LinkedHashMap<>(); |
| 49 | } |
| 50 | private static FilesetEntry makeFilesetEntry() { |
| 51 | try { |
| 52 | return new FilesetEntry(Label.parseAbsolute("//foo:bar"), |
| 53 | Lists.<Label>newArrayList(), Lists.newArrayList("xyz"), "", |
| 54 | FilesetEntry.SymlinkBehavior.COPY, "."); |
| 55 | } catch (Label.SyntaxException e) { |
| 56 | throw new RuntimeException("Bad label: ", e); |
| 57 | } |
| 58 | } |
| 59 | |
Han-Wen Nienhuys | 6682a31 | 2015-02-26 14:51:57 +0000 | [diff] [blame^] | 60 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 61 | public void testDataTypeNames() throws Exception { |
| 62 | assertEquals("string", EvalUtils.getDataTypeName("foo")); |
| 63 | assertEquals("int", EvalUtils.getDataTypeName(3)); |
| 64 | assertEquals("tuple", EvalUtils.getDataTypeName(makeTuple(1, 2, 3))); |
| 65 | assertEquals("list", EvalUtils.getDataTypeName(makeList(1, 2, 3))); |
| 66 | assertEquals("dict", EvalUtils.getDataTypeName(makeDict())); |
| 67 | assertEquals("FilesetEntry", EvalUtils.getDataTypeName(makeFilesetEntry())); |
| 68 | assertEquals("None", EvalUtils.getDataTypeName(Environment.NONE)); |
| 69 | } |
| 70 | |
Han-Wen Nienhuys | 6682a31 | 2015-02-26 14:51:57 +0000 | [diff] [blame^] | 71 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 72 | public void testDatatypeMutability() throws Exception { |
| 73 | assertTrue(EvalUtils.isImmutable("foo")); |
| 74 | assertTrue(EvalUtils.isImmutable(3)); |
| 75 | assertTrue(EvalUtils.isImmutable(makeTuple(1, 2, 3))); |
| 76 | assertFalse(EvalUtils.isImmutable(makeList(1, 2, 3))); |
| 77 | assertFalse(EvalUtils.isImmutable(makeDict())); |
| 78 | assertFalse(EvalUtils.isImmutable(makeFilesetEntry())); |
| 79 | } |
| 80 | |
Han-Wen Nienhuys | 6682a31 | 2015-02-26 14:51:57 +0000 | [diff] [blame^] | 81 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 82 | public void testPrintValue() throws Exception { |
| 83 | // Note that prettyPrintValue and printValue only differ on behaviour of |
| 84 | // labels and strings at toplevel. |
| 85 | assertEquals("foo\nbar", EvalUtils.printValue("foo\nbar")); |
| 86 | assertEquals("\"foo\\nbar\"", EvalUtils.prettyPrintValue("foo\nbar")); |
| 87 | assertEquals("'", EvalUtils.printValue("'")); |
| 88 | assertEquals("\"'\"", EvalUtils.prettyPrintValue("'")); |
| 89 | assertEquals("\"", EvalUtils.printValue("\"")); |
| 90 | assertEquals("\"\\\"\"", EvalUtils.prettyPrintValue("\"")); |
| 91 | assertEquals("3", EvalUtils.printValue(3)); |
| 92 | assertEquals("3", EvalUtils.prettyPrintValue(3)); |
| 93 | assertEquals("None", EvalUtils.prettyPrintValue(Environment.NONE)); |
| 94 | |
| 95 | assertEquals("//x:x", EvalUtils.printValue(Label.parseAbsolute("//x"))); |
| 96 | assertEquals("\"//x:x\"", EvalUtils.prettyPrintValue(Label.parseAbsolute("//x"))); |
| 97 | |
| 98 | List<?> list = makeList("foo", "bar"); |
| 99 | List<?> tuple = makeTuple("foo", "bar"); |
| 100 | |
| 101 | assertEquals("(1, [\"foo\", \"bar\"], 3)", |
| 102 | EvalUtils.printValue(makeTuple(1, list, 3))); |
| 103 | assertEquals("(1, [\"foo\", \"bar\"], 3)", |
| 104 | EvalUtils.prettyPrintValue(makeTuple(1, list, 3))); |
| 105 | assertEquals("[1, (\"foo\", \"bar\"), 3]", |
| 106 | EvalUtils.printValue(makeList(1, tuple, 3))); |
| 107 | assertEquals("[1, (\"foo\", \"bar\"), 3]", |
| 108 | EvalUtils.prettyPrintValue(makeList(1, tuple, 3))); |
| 109 | |
| 110 | Map<Object, Object> dict = makeDict(); |
| 111 | dict.put(1, tuple); |
| 112 | dict.put(2, list); |
| 113 | dict.put("foo", makeList()); |
| 114 | assertEquals("{1: (\"foo\", \"bar\"), 2: [\"foo\", \"bar\"], \"foo\": []}", |
| 115 | EvalUtils.printValue(dict)); |
| 116 | assertEquals("{1: (\"foo\", \"bar\"), 2: [\"foo\", \"bar\"], \"foo\": []}", |
| 117 | EvalUtils.prettyPrintValue(dict)); |
| 118 | assertEquals("FilesetEntry(srcdir = \"//foo:bar\", files = [], " |
| 119 | + "excludes = [\"xyz\"], destdir = \"\", " |
| 120 | + "strip_prefix = \".\", symlinks = \"copy\")", |
| 121 | EvalUtils.prettyPrintValue(makeFilesetEntry())); |
| 122 | } |
| 123 | |
| 124 | private void checkFormatPositionalFails(String format, List<?> tuple, |
| 125 | String errorMessage) { |
| 126 | try { |
| 127 | EvalUtils.formatString(format, tuple); |
| 128 | fail(); |
| 129 | } catch (IllegalFormatException e) { |
| 130 | assertEquals(errorMessage, e.getMessage()); |
| 131 | } |
| 132 | } |
| 133 | |
Han-Wen Nienhuys | 6682a31 | 2015-02-26 14:51:57 +0000 | [diff] [blame^] | 134 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 135 | public void testFormatPositional() throws Exception { |
| 136 | assertEquals("foo 3", EvalUtils.formatString("%s %d", makeTuple("foo", 3))); |
| 137 | |
| 138 | // Note: formatString doesn't perform scalar x -> (x) conversion; |
| 139 | // The %-operator is responsible for that. |
| 140 | assertEquals("", EvalUtils.formatString("", makeTuple())); |
| 141 | assertEquals("foo", EvalUtils.formatString("%s", makeTuple("foo"))); |
| 142 | assertEquals("3.14159", EvalUtils.formatString("%s", makeTuple(3.14159))); |
| 143 | checkFormatPositionalFails("%s", makeTuple(1, 2, 3), |
| 144 | "not all arguments converted during string formatting"); |
| 145 | assertEquals("%foo", EvalUtils.formatString("%%%s", makeTuple("foo"))); |
| 146 | checkFormatPositionalFails("%%s", makeTuple("foo"), |
| 147 | "not all arguments converted during string formatting"); |
| 148 | checkFormatPositionalFails("% %s", makeTuple("foo"), |
| 149 | "invalid arguments for format string"); |
| 150 | assertEquals("[1, 2, 3]", EvalUtils.formatString("%s", makeTuple(makeList(1, 2, 3)))); |
| 151 | assertEquals("(1, 2, 3)", EvalUtils.formatString("%s", makeTuple(makeTuple(1, 2, 3)))); |
| 152 | assertEquals("[]", EvalUtils.formatString("%s", makeTuple(makeList()))); |
| 153 | assertEquals("()", EvalUtils.formatString("%s", makeTuple(makeTuple()))); |
| 154 | |
| 155 | checkFormatPositionalFails("%.3g", makeTuple(), "invalid arguments for format string"); |
| 156 | checkFormatPositionalFails("%.3g", makeTuple(1, 2), "invalid arguments for format string"); |
| 157 | checkFormatPositionalFails("%.s", makeTuple(), "invalid arguments for format string"); |
| 158 | } |
| 159 | |
| 160 | private String createExpectedFilesetEntryString(FilesetEntry.SymlinkBehavior symlinkBehavior) { |
| 161 | return "FilesetEntry(srcdir = \"//x:x\"," |
| 162 | + " files = [\"//x:x\"]," |
| 163 | + " excludes = []," |
| 164 | + " destdir = \"\"," |
| 165 | + " strip_prefix = \".\"," |
| 166 | + " symlinks = \"" + symlinkBehavior.toString().toLowerCase() + "\")"; |
| 167 | } |
| 168 | |
| 169 | private FilesetEntry createTestFilesetEntry(FilesetEntry.SymlinkBehavior symlinkBehavior) |
| 170 | throws Exception { |
| 171 | Label label = Label.parseAbsolute("//x"); |
| 172 | return new FilesetEntry(label, |
| 173 | Arrays.asList(label), |
| 174 | Arrays.<String>asList(), |
| 175 | "", |
| 176 | symlinkBehavior, |
| 177 | "."); |
| 178 | } |
| 179 | |
Han-Wen Nienhuys | 6682a31 | 2015-02-26 14:51:57 +0000 | [diff] [blame^] | 180 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 181 | public void testFilesetEntrySymlinkAttr() throws Exception { |
| 182 | FilesetEntry entryDereference = |
| 183 | createTestFilesetEntry(FilesetEntry.SymlinkBehavior.DEREFERENCE); |
| 184 | |
| 185 | assertEquals(createExpectedFilesetEntryString(FilesetEntry.SymlinkBehavior.DEREFERENCE), |
| 186 | EvalUtils.prettyPrintValue(entryDereference)); |
| 187 | } |
| 188 | |
| 189 | private FilesetEntry createStripPrefixFilesetEntry(String stripPrefix) throws Exception { |
| 190 | Label label = Label.parseAbsolute("//x"); |
| 191 | return new FilesetEntry( |
| 192 | label, |
| 193 | Arrays.asList(label), |
| 194 | Arrays.<String>asList(), |
| 195 | "", |
| 196 | FilesetEntry.SymlinkBehavior.DEREFERENCE, |
| 197 | stripPrefix); |
| 198 | } |
| 199 | |
Han-Wen Nienhuys | 6682a31 | 2015-02-26 14:51:57 +0000 | [diff] [blame^] | 200 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 201 | public void testFilesetEntryStripPrefixAttr() throws Exception { |
| 202 | FilesetEntry withoutStripPrefix = createStripPrefixFilesetEntry("."); |
| 203 | FilesetEntry withStripPrefix = createStripPrefixFilesetEntry("orange"); |
| 204 | |
| 205 | String prettyWithout = EvalUtils.prettyPrintValue(withoutStripPrefix); |
| 206 | String prettyWith = EvalUtils.prettyPrintValue(withStripPrefix); |
| 207 | |
| 208 | assertTrue(prettyWithout.contains("strip_prefix = \".\"")); |
| 209 | assertTrue(prettyWith.contains("strip_prefix = \"orange\"")); |
| 210 | } |
| 211 | |
Han-Wen Nienhuys | 6682a31 | 2015-02-26 14:51:57 +0000 | [diff] [blame^] | 212 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 213 | public void testRegressionCrashInPrettyPrintValue() throws Exception { |
| 214 | // Would cause crash in code such as this: |
| 215 | // Fileset(name='x', entries=[], out=[FilesetEntry(files=['a'])]) |
| 216 | // While formatting the "expected x, got y" message for the 'out' |
| 217 | // attribute, prettyPrintValue(FilesetEntry) would be recursively called |
| 218 | // with a List<Label> even though this isn't a valid datatype in the |
| 219 | // interpreter. |
| 220 | // Fileset isn't part of bazel, even though FilesetEntry is. |
| 221 | Label label = Label.parseAbsolute("//x"); |
| 222 | assertEquals("FilesetEntry(srcdir = \"//x:x\"," |
| 223 | + " files = [\"//x:x\"]," |
| 224 | + " excludes = []," |
| 225 | + " destdir = \"\"," |
| 226 | + " strip_prefix = \".\"," |
| 227 | + " symlinks = \"copy\")", |
| 228 | EvalUtils.prettyPrintValue( |
| 229 | new FilesetEntry(label, |
| 230 | Arrays.asList(label), |
| 231 | Arrays.<String>asList(), |
| 232 | "", |
| 233 | FilesetEntry.SymlinkBehavior.COPY, |
| 234 | "."))); |
| 235 | } |
| 236 | } |