blob: 7aad74fba9037ac96035ac1b47f36ca2b5bce3ee [file] [log] [blame]
Ulf Adams89f012d2015-02-26 13:39:28 +00001// 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
15package com.google.devtools.build.lib.syntax;
16
Han-Wen Nienhuys6682a312015-02-26 14:51:57 +000017import static org.junit.Assert.assertEquals;
18import static org.junit.Assert.assertFalse;
19import static org.junit.Assert.assertTrue;
20import static org.junit.Assert.fail;
21
Ulf Adams89f012d2015-02-26 13:39:28 +000022import com.google.common.collect.Lists;
23
Han-Wen Nienhuys6682a312015-02-26 14:51:57 +000024import org.junit.Test;
25import org.junit.runner.RunWith;
26import org.junit.runners.JUnit4;
Ulf Adams89f012d2015-02-26 13:39:28 +000027
28import java.util.Arrays;
29import java.util.IllegalFormatException;
30import java.util.LinkedHashMap;
31import java.util.List;
32import 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 Nienhuys6682a312015-02-26 14:51:57 +000038@RunWith(JUnit4.class)
39public class EvalUtilsTest {
Ulf Adams89f012d2015-02-26 13:39:28 +000040
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 Nienhuys6682a312015-02-26 14:51:57 +000060 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +000061 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 Nienhuys6682a312015-02-26 14:51:57 +000071 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +000072 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 Nienhuys6682a312015-02-26 14:51:57 +000081 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +000082 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 Nienhuys6682a312015-02-26 14:51:57 +0000134 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000135 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 Nienhuys6682a312015-02-26 14:51:57 +0000180 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000181 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 Nienhuys6682a312015-02-26 14:51:57 +0000200 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000201 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 Nienhuys6682a312015-02-26 14:51:57 +0000212 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000213 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}