4bbc30cea66250f7a3c9214767bea92d712cddfe
[smo/teiv.git] /
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2024 Ericsson
4  *  Modifications Copyright (C) 2024 OpenInfra Foundation Europe
5  *  ================================================================================
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  *  SPDX-License-Identifier: Apache-2.0
19  *  ============LICENSE_END=========================================================
20  */
21 package org.oran.smo.yangtools.parser.test;
22
23 import static org.junit.Assert.assertTrue;
24 import static org.junit.Assert.assertFalse;
25
26 import java.io.ByteArrayOutputStream;
27 import java.io.File;
28 import java.io.FileInputStream;
29 import java.io.IOException;
30 import java.io.OutputStream;
31 import java.util.Arrays;
32 import java.util.List;
33
34 import org.junit.Test;
35
36 import org.oran.smo.yangtools.parser.findings.ParserFindingType;
37 import org.oran.smo.yangtools.parser.model.YangModel;
38 import org.oran.smo.yangtools.parser.model.statements.yang.CY;
39 import org.oran.smo.yangtools.parser.model.statements.yang.YAction;
40 import org.oran.smo.yangtools.parser.model.statements.yang.YContainer;
41 import org.oran.smo.yangtools.parser.model.statements.yang.YLeaf;
42 import org.oran.smo.yangtools.parser.model.statements.yang.YModule;
43 import org.oran.smo.yangtools.parser.model.yangdom.OriginalFileNameOutputFileNameResolver;
44 import org.oran.smo.yangtools.parser.model.yangdom.OutputFileNameResolver;
45 import org.oran.smo.yangtools.parser.model.yangdom.OutputStreamResolver;
46 import org.oran.smo.yangtools.parser.testutils.YangTestCommon;
47
48 public class YangDomWriteOutTest extends YangTestCommon {
49
50     private static final String OUT_DIR = "target/test-output/out-files";
51
52     @Test
53     public void testSimpleWriteOut() throws IOException {
54
55         parseAbsoluteImplementsYangModels(Arrays.asList("src/test/resources/basics/yangdom-write-out-test/module1.yang"));
56
57         final YModule module = getModule("module1");
58         assertTrue(module != null);
59
60         // write out with default resolver
61
62         createCleanTargetDir();
63         yangDeviceModel.getTopLevelSchema().writeOut(new File(OUT_DIR));
64
65         assertTrue(new File(OUT_DIR, "module1-2020-09-30.yang").exists());
66
67         // write out with file-name resolver
68
69         createCleanTargetDir();
70         yangDeviceModel.getTopLevelSchema().writeOut(new File(OUT_DIR), new OriginalFileNameOutputFileNameResolver());
71
72         assertTrue(new File(OUT_DIR, "module1.yang").exists());
73
74         // write out with custom resolver
75
76         yangDeviceModel.getTopLevelSchema().writeOut(new File(OUT_DIR), new OutputFileNameResolver() {
77             @Override
78             public String getOutputFileNameForYangInput(YangModel yangModelInput) {
79                 return "out-module.yang";
80             }
81         });
82
83         assertTrue(new File(OUT_DIR, "out-module.yang").exists());
84
85         // read back in the module and make sure content is correct.
86
87         setUp();
88         parseAbsoluteImplementsYangModels(Arrays.asList(new File(OUT_DIR, "out-module.yang").getAbsolutePath()));
89
90         final YModule module1 = getModule("module1");
91         assertTrue(module1 != null);
92
93         assertTrue(module1.getNamespace().getNamespace().equals("test:module1"));
94         assertTrue(module1.getRevisions().get(0).getValue().equals("2020-09-30"));
95
96         final YContainer cont1 = getContainer(module1, "cont1");
97         assertTrue(cont1 != null);
98
99         final YAction action11 = getChild(cont1, CY.ACTION, "action11");
100         assertTrue(action11 != null);
101
102         final YContainer cont112 = action11.getInput().getContainers().get(0);
103         assertTrue(cont112 != null);
104     }
105
106     @Test
107     public void testSimpleStreamOut() throws IOException {
108
109         parseAbsoluteImplementsYangModels(Arrays.asList("src/test/resources/basics/yangdom-write-out-test/module1.yang"));
110
111         final YModule module = getModule("module1");
112         assertTrue(module != null);
113
114         // write out to stream
115
116         final ByteArrayOutputStream os = new ByteArrayOutputStream();
117         final OutputStreamResolver resolver = new OutputStreamResolver() {
118             @Override
119             public OutputStream getOutputStreamForYangInput(YangModel yangModelInput) {
120                 return os;
121             }
122         };
123
124         yangDeviceModel.getTopLevelSchema().writeOut(resolver);
125
126         final byte[] streamResult = os.toByteArray();
127         assertTrue(streamResult.length > 0);
128
129         // write out the module to file
130
131         createCleanTargetDir();
132         yangDeviceModel.getTopLevelSchema().writeOut(new File(OUT_DIR), new OriginalFileNameOutputFileNameResolver());
133
134         assertTrue(new File(OUT_DIR, "module1.yang").exists());
135
136         // contents of file and byte[] must match exactly
137
138         final FileInputStream fis = new FileInputStream(new File(OUT_DIR, "module1.yang"));
139         final ByteArrayOutputStream fileBuffer = new ByteArrayOutputStream();
140
141         int nRead;
142         byte[] data = new byte[100000];
143
144         while ((nRead = fis.read(data, 0, data.length)) != -1) {
145             fileBuffer.write(data, 0, nRead);
146         }
147         fis.close();
148         final byte[] fileContents = fileBuffer.toByteArray();
149
150         assertTrue(streamResult.length == fileContents.length);
151     }
152
153     @Test
154     public void testWriteOutToFileChangedOnly() throws IOException {
155
156         parseAbsoluteImplementsYangModels(Arrays.asList("src/test/resources/basics/yangdom-write-out-test/module1.yang"));
157
158         final YModule module = getModule("module1");
159         assertTrue(module != null);
160
161         final YContainer cont1 = module.getContainers().get(0);
162         cont1.getYangModelRoot().getDomDocumentRoot().setDomHasBeenModified();
163
164         createCleanTargetDir();
165         final List<YangModel> writeOutChanged = yangDeviceModel.getTopLevelSchema().writeOutChanged(new File(OUT_DIR),
166                 new OriginalFileNameOutputFileNameResolver());
167
168         assertTrue(new File(OUT_DIR, "module1.yang").exists());
169         assertTrue(writeOutChanged.size() == 1);
170     }
171
172     @Test
173     public void testWriteOutToStreamChangedOnly() throws IOException {
174
175         parseAbsoluteImplementsYangModels(Arrays.asList("src/test/resources/basics/yangdom-write-out-test/module1.yang"));
176
177         final YModule module = getModule("module1");
178         assertTrue(module != null);
179
180         final YContainer cont1 = module.getContainers().get(0);
181         cont1.getYangModelRoot().getDomDocumentRoot().setDomHasBeenModified();
182
183         // write out to stream
184
185         final ByteArrayOutputStream os = new ByteArrayOutputStream();
186         final OutputStreamResolver resolver = new OutputStreamResolver() {
187             @Override
188             public OutputStream getOutputStreamForYangInput(YangModel yangModelInput) {
189                 return os;
190             }
191         };
192
193         final List<YangModel> writeOutChanged = yangDeviceModel.getTopLevelSchema().writeOutChanged(resolver);
194         assertTrue(writeOutChanged.size() == 1);
195
196         final byte[] streamResult = os.toByteArray();
197         assertTrue(streamResult.length > 0);
198     }
199
200     @Test
201     public void testWriteOutChangedOnlyButModuleNotChanged() throws IOException {
202
203         parseAbsoluteImplementsYangModels(Arrays.asList("src/test/resources/basics/yangdom-write-out-test/module1.yang"));
204
205         final YModule module = getModule("module1");
206         assertTrue(module != null);
207
208         // Don't mark as modified, should not be written out.
209
210         //      final YContainer cont1 = module.getContainers().get(0);
211         //      cont1.getYangModelRoot().getDomDocumentRoot().setDomHasBeenModified();
212
213         createCleanTargetDir();
214         final List<YangModel> writeOutChanged = yangDeviceModel.getTopLevelSchema().writeOutChanged(new File(OUT_DIR),
215                 new OriginalFileNameOutputFileNameResolver());
216
217         assertFalse(new File(OUT_DIR, "module1.yang").exists());
218         assertTrue(writeOutChanged.size() == 0);
219     }
220
221     @Test
222     public void testWeirdStringsAndCharactersWriteOut() throws IOException {
223
224         parseAbsoluteImplementsYangModels(Arrays.asList("src/test/resources/basics/yangdom-write-out-test/module1.yang"));
225         assertHasFindingOfType(ParserFindingType.P011_INVALID_CHARACTER_ESCAPING_IN_QUOTED_TEXT.toString());
226         assertHasFindingOfType(ParserFindingType.P101_EMPTY_DOCUMENTATION_VALUE.toString());
227
228         final YModule module = getModule("module1");
229         assertTrue(module != null);
230
231         checkDescriptions(module);
232
233         // write out with file-name resolver
234
235         createCleanTargetDir();
236         yangDeviceModel.getTopLevelSchema().writeOut(new File(OUT_DIR), new OriginalFileNameOutputFileNameResolver());
237
238         assertTrue(new File(OUT_DIR, "module1.yang").exists());
239
240         // read back in the module and make sure content is correct.
241
242         setUp();
243         parseAbsoluteImplementsYangModels(Arrays.asList(new File(OUT_DIR, "module1.yang").getAbsolutePath()));
244
245         /*
246          * The writing-out of the strings should have cleaned up any illegal escaping, so we shouldn't see this again.
247          */
248         assertHasFindingOfType(ParserFindingType.P101_EMPTY_DOCUMENTATION_VALUE.toString());
249
250         final YModule module1 = getModule("module1");
251         assertTrue(module1 != null);
252
253         checkDescriptions(module1);
254     }
255
256     private void checkDescriptions(final YModule module) {
257         final YContainer cont2 = getContainer(module, "cont2");
258         assertTrue(cont2 != null);
259
260         final YLeaf leaf21 = getLeaf(cont2, "leaf21");
261         assertTrue(leaf21.getDescription().getValue().equals("simple string with space character"));
262
263         final YLeaf leaf22 = getLeaf(cont2, "leaf22");
264         assertTrue(leaf22.getDescription().getValue().equals("simple string\twith tab character"));
265
266         final YLeaf leaf23 = getLeaf(cont2, "leaf23");
267         assertTrue(leaf23.getDescription().getValue().equals("simple string with \" escaped quote character"));
268
269         final YLeaf leaf24 = getLeaf(cont2, "leaf24");
270         assertTrue(leaf24.getDescription().getValue().equals("simple string with \\' escaped single-quote character"));
271
272         final YLeaf leaf25 = getLeaf(cont2, "leaf25");
273         assertTrue(leaf25.getDescription().getValue().equals("exact characters\ttab and quote \""));
274
275         final YLeaf leaf26 = getLeaf(cont2, "leaf26");
276         assertTrue(leaf26.getDescription().getValue().equals(
277                 "exact characters stretching over\n   multiple lines - note three spaces at start of line"));
278
279         final YLeaf leaf27 = getLeaf(cont2, "leaf27");
280         assertTrue(leaf27.getDescription().getValue().equals("+"));
281
282         final YLeaf leaf28 = getLeaf(cont2, "leaf28");
283         assertTrue(leaf28.getDescription().getValue().equals(";"));
284
285         final YLeaf leaf29 = getLeaf(cont2, "leaf29");
286         assertTrue(leaf29.getDescription().getValue().equals(";;"));
287
288         final YLeaf leaf30 = getLeaf(cont2, "leaf30");
289         assertTrue(leaf30.getDescription().getValue().equals("Hello+World!"));
290
291         final YLeaf leaf31 = getLeaf(cont2, "leaf31");
292         assertTrue(leaf31.getDescription().getValue().equals("on next line"));
293
294         final YLeaf leaf32 = getLeaf(cont2, "leaf32");
295         assertTrue(leaf32.getDescription().getValue().equals("some on this line some on the next line"));
296
297         final YLeaf leaf33 = getLeaf(cont2, "leaf33");
298         assertTrue(leaf33.getDescription().getValue().equals("First paragraph. \nSecond paragraph."));
299
300         final YLeaf leaf34 = getLeaf(cont2, "leaf34");
301         assertTrue(leaf34.getDescription().getValue().equals("this_is_//_not_a_comment"));
302
303         final YLeaf leaf35 = getLeaf(cont2, "leaf35");
304         assertTrue(leaf35.getDescription().getValue().equals("this_is_/*_not_a_comment"));
305
306         final YLeaf leaf36 = getLeaf(cont2, "leaf36");
307         assertTrue(leaf36.getDescription().getValue().equals("this_is_*/_not_a_comment"));
308
309         final YLeaf leaf37 = getLeaf(cont2, "leaf37");
310         assertTrue(leaf37.getDescription().getValue().equals(""));
311
312         final YLeaf leaf38 = getLeaf(cont2, "leaf38");
313         assertTrue(leaf38.getDescription().getValue().equals("{"));
314
315         final YLeaf leaf39 = getLeaf(cont2, "leaf39");
316         assertTrue(leaf39.getDescription().getValue().equals("}"));
317
318         final YLeaf leaf40 = getLeaf(cont2, "leaf40");
319         assertTrue(leaf40.getDescription().getValue().equals("\""));
320     }
321
322     private void createCleanTargetDir() {
323
324         final File dir = new File(OUT_DIR);
325
326         if (!dir.exists()) {
327             dir.mkdirs();
328         }
329
330         final File[] listFiles = dir.listFiles();
331         for (final File file : listFiles) {
332             file.delete();
333         }
334     }
335 }