1 /**
2  * Copyright (c) 2008, http://www.snakeyaml.org
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.pyyaml;
17 
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.InputStream;
21 import java.io.Reader;
22 import java.util.ArrayList;
23 import java.util.Iterator;
24 import java.util.List;
25 
26 import org.yaml.snakeyaml.Yaml;
27 import org.yaml.snakeyaml.composer.Composer;
28 import org.yaml.snakeyaml.constructor.AbstractConstruct;
29 import org.yaml.snakeyaml.constructor.Constructor;
30 import org.yaml.snakeyaml.events.AliasEvent;
31 import org.yaml.snakeyaml.events.CollectionStartEvent;
32 import org.yaml.snakeyaml.events.Event;
33 import org.yaml.snakeyaml.events.ScalarEvent;
34 import org.yaml.snakeyaml.nodes.MappingNode;
35 import org.yaml.snakeyaml.nodes.Node;
36 import org.yaml.snakeyaml.nodes.NodeTuple;
37 import org.yaml.snakeyaml.nodes.ScalarNode;
38 import org.yaml.snakeyaml.nodes.SequenceNode;
39 import org.yaml.snakeyaml.parser.ParserImpl;
40 import org.yaml.snakeyaml.reader.StreamReader;
41 import org.yaml.snakeyaml.reader.UnicodeReader;
42 import org.yaml.snakeyaml.resolver.Resolver;
43 
44 /**
45  * imported from PyYAML
46  */
47 public class PyStructureTest extends PyImportTest {
48 
compareEvents(List<Event> events1, List<Event> events2, boolean full)49     private void compareEvents(List<Event> events1, List<Event> events2, boolean full) {
50         assertEquals(events1.size(), events2.size());
51         Iterator<Event> iter1 = events1.iterator();
52         Iterator<Event> iter2 = events2.iterator();
53         while (iter1.hasNext()) {
54             Event event1 = iter1.next();
55             Event event2 = iter2.next();
56             assertEquals(event1.getClass(), event2.getClass());
57             if (event1 instanceof AliasEvent && full) {
58                 assertEquals(((AliasEvent) event1).getAnchor(), ((AliasEvent) event2).getAnchor());
59             }
60             if (event1 instanceof CollectionStartEvent) {
61                 String tag1 = ((CollectionStartEvent) event1).getTag();
62                 String tag2 = ((CollectionStartEvent) event1).getTag();
63                 if (tag1 != null && !"!".equals(tag1) && tag2 != null && !"!".equals(tag1)) {
64                     assertEquals(tag1, tag2);
65                 }
66             }
67             if (event1 instanceof ScalarEvent) {
68                 ScalarEvent scalar1 = (ScalarEvent) event1;
69                 ScalarEvent scalar2 = (ScalarEvent) event2;
70                 if (scalar1.getImplicit().bothFalse() && scalar2.getImplicit().bothFalse()) {
71                     assertEquals(scalar1.getTag(), scalar2.getTag());
72                 }
73                 assertEquals(scalar1.getValue(), scalar2.getValue());
74             }
75         }
76     }
77 
testParser()78     public void testParser() {
79         File[] files = getStreamsByExtension(".data", true);
80         assertTrue("No test files found.", files.length > 0);
81         for (File file : files) {
82             if (!file.getName().contains("scan-line-b")) {
83                 continue;
84             }
85             try {
86                 InputStream input = new FileInputStream(file);
87                 List<Event> events1 = parse(input);
88                 input.close();
89                 assertFalse(events1.isEmpty());
90                 int index = file.getAbsolutePath().lastIndexOf('.');
91                 String canonicalName = file.getAbsolutePath().substring(0, index) + ".canonical";
92                 File canonical = new File(canonicalName);
93                 List<Event> events2 = canonicalParse(new FileInputStream(canonical));
94                 assertFalse(events2.isEmpty());
95                 compareEvents(events1, events2, false);
96             } catch (Exception e) {
97                 System.out.println("Failed File: " + file);
98                 // fail("Failed File: " + file + "; " + e.getMessage());
99                 throw new RuntimeException(e);
100             }
101         }
102     }
103 
testParserOnCanonical()104     public void testParserOnCanonical() {
105         File[] canonicalFiles = getStreamsByExtension(".canonical", false);
106         assertTrue("No test files found.", canonicalFiles.length > 0);
107         for (File file : canonicalFiles) {
108             try {
109                 InputStream input = new FileInputStream(file);
110                 List<Event> events1 = parse(input);
111                 input.close();
112                 assertFalse(events1.isEmpty());
113                 List<Event> events2 = canonicalParse(new FileInputStream(file));
114                 assertFalse(events2.isEmpty());
115                 compareEvents(events1, events2, true);
116             } catch (Exception e) {
117                 System.out.println("Failed File: " + file);
118                 // fail("Failed File: " + file + "; " + e.getMessage());
119                 throw new RuntimeException(e);
120             }
121         }
122     }
123 
compareNodes(Node node1, Node node2)124     private void compareNodes(Node node1, Node node2) {
125         assertEquals(node1.getClass(), node2.getClass());
126         if (node1 instanceof ScalarNode) {
127             ScalarNode scalar1 = (ScalarNode) node1;
128             ScalarNode scalar2 = (ScalarNode) node2;
129             assertEquals(scalar1.getTag(), scalar2.getTag());
130             assertEquals(scalar1.getValue(), scalar2.getValue());
131         } else {
132             if (node1 instanceof SequenceNode) {
133                 SequenceNode seq1 = (SequenceNode) node1;
134                 SequenceNode seq2 = (SequenceNode) node2;
135                 assertEquals(seq1.getTag(), seq2.getTag());
136                 assertEquals(seq1.getValue().size(), seq2.getValue().size());
137                 Iterator<Node> iter2 = seq2.getValue().iterator();
138                 for (Node child1 : seq1.getValue()) {
139                     Node child2 = iter2.next();
140                     compareNodes(child1, child2);
141                 }
142             } else {
143                 MappingNode seq1 = (MappingNode) node1;
144                 MappingNode seq2 = (MappingNode) node2;
145                 assertEquals(seq1.getTag(), seq2.getTag());
146                 assertEquals(seq1.getValue().size(), seq2.getValue().size());
147                 Iterator<NodeTuple> iter2 = seq2.getValue().iterator();
148                 for (NodeTuple child1 : seq1.getValue()) {
149                     NodeTuple child2 = iter2.next();
150                     compareNodes(child1.getKeyNode(), child2.getKeyNode());
151                     compareNodes(child1.getValueNode(), child2.getValueNode());
152                 }
153             }
154         }
155     }
156 
testComposer()157     public void testComposer() {
158         File[] files = getStreamsByExtension(".data", true);
159         assertTrue("No test files found.", files.length > 0);
160         for (File file : files) {
161             try {
162                 InputStream input = new FileInputStream(file);
163                 List<Node> events1 = compose_all(input);
164                 input.close();
165                 int index = file.getAbsolutePath().lastIndexOf('.');
166                 String canonicalName = file.getAbsolutePath().substring(0, index) + ".canonical";
167                 File canonical = new File(canonicalName);
168                 InputStream input2 = new FileInputStream(canonical);
169                 List<Node> events2 = canonical_compose_all(input2);
170                 input2.close();
171                 assertEquals(events1.size(), events2.size());
172                 Iterator<Node> iter1 = events1.iterator();
173                 Iterator<Node> iter2 = events2.iterator();
174                 while (iter1.hasNext()) {
175                     compareNodes(iter1.next(), iter2.next());
176                 }
177             } catch (Exception e) {
178                 System.out.println("Failed File: " + file);
179                 // fail("Failed File: " + file + "; " + e.getMessage());
180                 throw new RuntimeException(e);
181             }
182         }
183     }
184 
compose_all(InputStream file)185     private List<Node> compose_all(InputStream file) {
186         Composer composer = new Composer(new ParserImpl(new StreamReader(new UnicodeReader(file))),
187                 new Resolver());
188         List<Node> documents = new ArrayList<Node>();
189         while (composer.checkNode()) {
190             documents.add(composer.getNode());
191         }
192         return documents;
193     }
194 
canonical_compose_all(InputStream file)195     private List<Node> canonical_compose_all(InputStream file) {
196         StreamReader reader = new StreamReader(new UnicodeReader(file));
197         StringBuilder buffer = new StringBuilder();
198         while (reader.peek() != '\0') {
199             buffer.append(reader.peek());
200             reader.forward();
201         }
202         CanonicalParser parser = new CanonicalParser(buffer.toString());
203         Composer composer = new Composer(parser, new Resolver());
204         List<Node> documents = new ArrayList<Node>();
205         while (composer.checkNode()) {
206             documents.add(composer.getNode());
207         }
208         return documents;
209     }
210 
211     class CanonicalLoader extends Yaml {
CanonicalLoader()212         public CanonicalLoader() {
213             super(new MyConstructor());
214         }
215 
216         @Override
loadAll(Reader yaml)217         public Iterable<Object> loadAll(Reader yaml) {
218             StreamReader reader = new StreamReader(yaml);
219             StringBuilder buffer = new StringBuilder();
220             while (reader.peek() != '\0') {
221                 buffer.append(reader.peek());
222                 reader.forward();
223             }
224             CanonicalParser parser = new CanonicalParser(buffer.toString());
225             Composer composer = new Composer(parser, resolver);
226             this.constructor.setComposer(composer);
227             Iterator<Object> result = new Iterator<Object>() {
228                 public boolean hasNext() {
229                     return constructor.checkData();
230                 }
231 
232                 public Object next() {
233                     return constructor.getData();
234                 }
235 
236                 public void remove() {
237                     throw new UnsupportedOperationException();
238                 }
239             };
240             return new YamlIterable(result);
241         }
242 
243         private class YamlIterable implements Iterable<Object> {
244             private Iterator<Object> iterator;
245 
YamlIterable(Iterator<Object> iterator)246             public YamlIterable(Iterator<Object> iterator) {
247                 this.iterator = iterator;
248             }
249 
iterator()250             public Iterator<Object> iterator() {
251                 return iterator;
252             }
253 
254         }
255 
256     }
257 
258     private class MyConstructor extends Constructor {
MyConstructor()259         public MyConstructor() {
260             this.yamlConstructors.put(null, new ConstructUndefined());
261         }
262 
263         private class ConstructUndefined extends AbstractConstruct {
construct(Node node)264             public Object construct(Node node) {
265                 return constructScalar((ScalarNode) node);
266             }
267         }
268     }
269 
testConstructor()270     public void testConstructor() {
271         File[] files = getStreamsByExtension(".data", true);
272         assertTrue("No test files found.", files.length > 0);
273         Yaml myYaml = new Yaml(new MyConstructor());
274         Yaml canonicalYaml = new CanonicalLoader();
275         for (File file : files) {
276             try {
277                 InputStream input = new FileInputStream(file);
278                 Iterable<Object> documents1 = myYaml.loadAll(input);
279                 int index = file.getAbsolutePath().lastIndexOf('.');
280                 String canonicalName = file.getAbsolutePath().substring(0, index) + ".canonical";
281                 File canonical = new File(canonicalName);
282                 InputStream input2 = new FileInputStream(canonical);
283                 Iterable<Object> documents2 = canonicalYaml.loadAll(input2);
284                 input2.close();
285                 Iterator<Object> iter2 = documents2.iterator();
286                 for (Object object1 : documents1) {
287                     Object object2 = iter2.next();
288                     if (object2 != null) {
289                         assertFalse(System.identityHashCode(object1) == System
290                                 .identityHashCode(object2));
291                     }
292                     assertEquals("" + object1, object1, object2);
293                 }
294                 input.close();
295             } catch (Exception e) {
296                 System.out.println("Failed File: " + file);
297                 // fail("Failed File: " + file + "; " + e.getMessage());
298                 throw new RuntimeException(e);
299             }
300         }
301     }
302 }
303