001 /*
002 * DependenciesTests.java
003 * Copyright (c) 1998-2008, The University of Sheffield.
004 *
005 * This code is from the GATE project (http://gate.ac.uk/) and is free
006 * software licenced under the GNU General Public License version 3. It is
007 * distributed without any warranty. For more details see COPYING.txt in the
008 * top level directory (or at http://gatewiki.sf.net/COPYING.txt).
009 */
010
011 package gate.yam.depend;
012
013 import gate.persist.PersistenceException;
014 import gate.util.GateException;
015 import gate.yam.YamFile;
016 import junit.framework.Test;
017 import junit.framework.TestCase;
018 import junit.framework.TestSuite;
019 import org.apache.log4j.Logger;
020 import org.springframework.core.io.FileSystemResource;
021
022 import java.io.*;
023 import java.nio.channels.FileChannel;
024 import java.util.*;
025 import java.util.regex.Matcher;
026 import java.util.regex.Pattern;
027
028 /**
029 * Tests for Dependencies
030 * @author Angus Roberts
031 */
032 public class DependenciesTests extends TestCase {
033
034 /** Logger */
035 static Logger log = Logger.getLogger("gate.yam.depend.DependenciesTests");
036
037 /**
038 * Matches the names of YamFiles as used in testing, capturing the numeric
039 * part for use as a shorthand. (see @link #shorthandToPaths(String).
040 * YamFiles used in testing are named using a conventionally, as defined in
041 * this pattern.
042 */
043 private static Pattern testFilePattern
044 = Pattern.compile("yam-depends-(\\d+).yam");
045
046 /**
047 * Some test files come in to versions - their original, and their modified
048 * version. This pattern matches the original, capturing the parts that make
049 * up the name of the actual file as used in tests.
050 */
051 private static Pattern originalTestFilePattern
052 = Pattern.compile("(yam-depends-)ORIGINAL-(\\d+.yam)");
053
054 /**
055 * A FilenameFilter that accepts yam files used by DependenciesTests.
056 * By convention, filenames are "yam-depends-\d+.yam"
057 */
058 class DependenciesTestsFileFilter implements FilenameFilter {
059 /** Accept a file if it is a yam file used in DependenciesTests*/
060 public boolean accept(File dir, String name) {
061 return testFilePattern.matcher(name).matches();
062 }
063 }
064
065 /**
066 * A FilenameFilter that accepts original versions of yam files used by
067 * DependenciesTests. By convention, filenames are
068 * "yam-depends-ORIGINAL-\d+.yam"
069 */
070 class DependenciesTestsOriginalFileFilter implements FilenameFilter {
071 /** Accept a file if it is the original version of
072 * a yam file used in DependenciesTests
073 */
074 public boolean accept(File dir, String name) {
075 return originalTestFilePattern.matcher(name).matches();
076 }
077 }
078
079 /**
080 * The directory that test yam files are found in.
081 */
082 private static File yamDir;
083
084 /**
085 * By convention, each yam file used in testing is named
086 * "yam-depends-\d+.yam". This Map maps the digit part to the full name.
087 * It is used so that we can refer to sets and graphs of files by just their
088 * digit part.
089 */
090 Map<String, String> yamFileNameMap = new HashMap<String, String>();
091
092 /**
093 * As for @link #yamFileNameMap, but maps the digit part of the name to the
094 * actual YamFile, post-generate().
095 */
096 Map<String, YamFile> yamFileMap = new HashMap<String, YamFile>();
097
098 /**
099 * A List of parsed YamFiles that make up a wiki
100 */
101 private List<YamFile> wiki1 = new ArrayList<YamFile>();
102
103 /**
104 * A Dependencies instance for wiki1
105 */
106 private Dependencies dep1;
107
108
109 /** Create a Dependencies test case
110 *
111 * @param testName The name of the test
112 */
113 public DependenciesTests(String testName) {
114 super(testName);
115 }
116
117
118
119 // TODO remove setting of directories to strings - get from where?
120 /**
121 * Set up the tests for Dependencies
122 */
123 protected void setUp() {
124
125 // set up the directory to which dependencies will be serialized
126 String testDirName = System.getProperty("gate.yam.depend.test.dir");
127 if (testDirName == null) {
128 testDirName = "test/scratch/dependencies";
129 }
130
131 File testDirFile = new File(testDirName);
132 testDirFile.mkdirs();
133 Dependencies.setSerializationDirectory(testDirFile);
134
135 // get a directory of yam files for testing
136 String yamDirName = System.getProperty("java.yam.resources.dir");
137 if (yamDirName == null) {
138 yamDirName = this.getClass().getResource("/gate/yam/resources").getFile();
139 }
140
141 log.info("Getting test yam files from: " + yamDirName);
142
143 yamDir = new File(yamDirName);
144
145 // Some of our test files have original and modified versions, named
146 // yam-depends-ORIGINAL-\d+.yam and yam-depends-MODIFIED-\d+.yam
147 // Copy the original versions to their "proper" names for loading
148 File[] originalVersions
149 = yamDir.listFiles(new DependenciesTestsOriginalFileFilter());
150 for(File origFile : originalVersions) {
151 //Work out the name as used in tests
152 Matcher matcher = originalTestFilePattern.matcher(origFile.getName());
153 if (!matcher.matches()) {
154 fail("Failed to setup - filename not conventional: "
155 + origFile.getName());
156 }
157 String newName = matcher.group(1) + matcher.group(2);
158 File newFile = new File(yamDir, newName);
159 copy(origFile, newFile);
160
161 }
162
163 // Get all the yam files used by DependenciesTests
164 File[] testFiles = yamDir.listFiles(new DependenciesTestsFileFilter());
165 for(File file : testFiles ) {
166 YamFile yamFile = YamFile.get(new FileSystemResource(file));
167 try{
168 String canPath = yamFile.getCanonicalPath();
169 log.info("Getting test file: " + canPath);
170 // Group 1 of testFilePattern is the numeric part
171 Matcher matcher = testFilePattern.matcher(file.getName());
172 if(!matcher.matches()) {
173 fail("Failed to setup - filename not conventional: "
174 + file.getName());
175 }
176 String number = matcher.group(1);
177 yamFile.generate();
178 yamFileNameMap.put(number, canPath);
179 yamFileMap.put(number, yamFile);
180 } catch(GateException ge) {
181 fail("Failed to setup: " + ge.getMessage());
182 }
183 }
184
185
186 // Add some files to a list, to use as a wiki
187 wiki1.add(yamFileMap.get("1"));
188 wiki1.add(yamFileMap.get("2"));
189 wiki1.add(yamFileMap.get("3"));
190 wiki1.add(yamFileMap.get("4"));
191 wiki1.add(yamFileMap.get("5"));
192
193 // Get dependencies for the wiki
194 try{
195 // Clear it before getting a new one - could have persisted on disk
196 Dependencies.remove("1");
197 dep1 = Dependencies.get("1");
198 } catch(PersistenceException pe) {
199 fail("Failed to set up: " + pe.getMessage());
200 }
201 assertTrue("New Dependencies not empty", dep1.isEmpty());
202
203
204
205 // Add all the files in the wiki to the dependencies
206 for(YamFile yam : wiki1) {
207 dep1.created(yam);
208 }
209
210 assertFalse(
211 "Dependencies is empty after adding links", dep1.isEmpty()
212 );
213
214
215 }
216
217
218 /**
219 * Test a few Dependencies basics: equality, hashCode, YamFile creation
220 * and removal.
221 * @throws Exception if the test fails
222 */
223 public void testCreateAndBasics() throws Exception {
224 log.info("========== DependenciesTests.tesCreateAndBasics() ==============");
225 log.info("testing dependencies.created(YamFile) and equality methods");
226
227
228 // Create a Dependencies that is the same as our global dep1
229 Dependencies dep2 = Dependencies.get("2");
230 for(YamFile yam : wiki1) {
231 dep2.created(yam);
232 }
233
234 // What does this dependencies look like?
235 assertEquals("Dependencies linksTo not correct after create",
236 shorthandToPaths("1:[2,3];2:[4,5];3:[5]"),
237 dep2.linksToAsString());
238
239 assertEquals("Dependencies linkedBy not correct after create",
240 shorthandToPaths("2:[1];3:[1];4:[2];5:[2,3]"),
241 dep2.linkedByAsString());
242
243 assertEquals("Dependencies includes not correct after create",
244 shorthandToPaths("1:[2,3,4];2:[4]"),
245 dep2.includesAsString());
246
247 assertEquals("Dependencies includedBy not correct after create",
248 shorthandToPaths("2:[1];3:[1];4:[1,2]"),
249 dep2.includedByAsString());
250
251
252 // Test equality
253 assertEquals("Same Dependencies not equal", dep1, dep1);
254
255 assertEquals(
256 "Dependencies not equal after get", dep1, Dependencies.get("1"));
257
258 assertEquals("Identical Dependencies not equal", dep1, dep2);
259
260 assertEquals(
261 "Identical Dependencies with different hash codes",
262 dep1.hashCode(), dep2.hashCode());
263
264 // Can we remove a Dependencies?
265 Dependencies.remove("2");
266 assertFalse("Dependencies still exists after removal",
267 Dependencies.exists("2"));
268
269 }
270
271 /**
272 * Test Dependencies YamFile deletion
273 * @throws Exception if the test fails
274 */
275 public void testDelete() throws Exception {
276 log.info("============== DependenciesTests.testDelete() ==================");
277 log.info("testing dependencies.deleted(YamFile)");
278
279 // Holds results from Dependencies event operations
280 Set<String> toRegenerate;
281
282 // What happens if we delete a YamFile?
283 // First, delete one that has links and includes in it
284 toRegenerate = dep1.deleted(yamFileMap.get("1"));
285
286 assertEquals("Regenerate set not correct after delete",
287 new HashSet<String>(),
288 toRegenerate);
289
290 assertEquals("Dependencies linksTo not correct after delete",
291 shorthandToPaths("2:[4,5];3:[5]"),
292 dep1.linksToAsString());
293
294 assertEquals("Dependencies linkedBy not correct after delete",
295 shorthandToPaths("4:[2];5:[2,3]"),
296 dep1.linkedByAsString());
297
298 assertEquals("Dependencies includes not correct after delete",
299 shorthandToPaths("2:[4]"),
300 dep1.includesAsString());
301
302 assertEquals("Dependencies includedBy not correct after delete",
303 shorthandToPaths("4:[2]"),
304 dep1.includedByAsString());
305
306 // Now recreate it - put it back
307 toRegenerate = dep1.created(yamFileMap.get("1"));
308
309 assertEquals("Regenerate set not correct after create",
310 new HashSet<String>(),
311 toRegenerate);
312
313
314 assertEquals("Dependencies linksTo not correct after create",
315 shorthandToPaths("1:[2,3];2:[4,5];3:[5]"),
316 dep1.linksToAsString());
317
318 assertEquals("Dependencies linkedBy not correct after create",
319 shorthandToPaths("2:[1];3:[1];4:[2];5:[2,3]"),
320 dep1.linkedByAsString());
321
322 assertEquals("Dependencies includes not correct after create",
323 shorthandToPaths("1:[2,3,4];2:[4]"),
324 dep1.includesAsString());
325
326 assertEquals("Dependencies includedBy not correct after create",
327 shorthandToPaths("2:[1];3:[1];4:[1,2]"),
328 dep1.includedByAsString());
329
330 }
331
332 /**
333 * Test Dependencies YamFile renaming
334 * @throws Exception if the test fails
335 */
336 public void testRename() throws Exception {
337 log.info("============== DependenciesTests.testRename() ==================");
338 log.info("testing dependencies.renamed(YamFile)");
339
340 // Holds results from Dependencies event operations
341 Set<String> toRegenerate;
342 List<String> toRegenerateSorted;
343
344
345 // Rename a YamFile. We don't really, just pretend that one file is a rename
346 // of another
347 toRegenerate = dep1.renamed(yamFileMap.get("2"), yamFileMap.get("6"));
348 toRegenerateSorted = new ArrayList<String>(toRegenerate);
349 Collections.sort(toRegenerateSorted);
350
351 assertEquals("Regenerate set not correct after rename",
352 numbersToList("1"),
353 toRegenerateSorted);
354
355 assertEquals("Dependencies linksTo not correct after rename",
356 shorthandToPaths("1:[3,6];3:[5];6:[4,5]"),
357 dep1.linksToAsString());
358
359 assertEquals("Dependencies linkedBy not correct after rename",
360 shorthandToPaths("3:[1];4:[6];5:[3,6];6:[1]"),
361 dep1.linkedByAsString());
362
363 assertEquals("Dependencies includes not correct after rename",
364 shorthandToPaths("1:[3,4,6];6:[4]"),
365 dep1.includesAsString());
366
367 assertEquals("Dependencies includedBy not correct after rename",
368 shorthandToPaths("3:[1];4:[1,6];6:[1]"),
369 dep1.includedByAsString());
370
371 // Put everything back in its original form for further tests
372 dep1.renamed(yamFileMap.get("6"), yamFileMap.get("2"));
373
374
375 }
376
377 /**
378 * Test Dependencies - further YamFile deletion tests
379 * @throws Exception if the test fails
380 */
381 public void testDelete2() throws Exception {
382 log.info("============== DependenciesTests.testDelete2() =================");
383 log.info("testing dependencies.deleted(YamFile)");
384
385 // Holds results from Dependencies event operations
386 Set<String> toRegenerate;
387 List<String> toRegenerateSorted;
388
389 // Delete a YamFile that will need a bit nore regeneration
390 toRegenerate = dep1.deleted(yamFileMap.get("4"));
391 toRegenerateSorted = new ArrayList<String>(toRegenerate);
392 Collections.sort(toRegenerateSorted);
393
394 assertEquals("Regenerate set not correct after delete",
395 numbersToList("1,2"),
396 toRegenerateSorted);
397
398 // And delete another
399 toRegenerate = dep1.deleted(yamFileMap.get("5"));
400 toRegenerateSorted = new ArrayList<String>(toRegenerate);
401 Collections.sort(toRegenerateSorted);
402
403 assertEquals("Regenerate set not correct after delete",
404 numbersToList("2,3"),
405 toRegenerateSorted);
406
407 // Put everything back in its original form for further tests
408 dep1.created(yamFileMap.get("4"));
409 dep1.created(yamFileMap.get("5"));
410
411 // Check all is how it should be
412 assertEquals("Dependencies linksTo not correct after delete and create",
413 shorthandToPaths("1:[2,3];2:[4,5];3:[5]"),
414 dep1.linksToAsString());
415
416 assertEquals("Dependencies linkedBy not correct after delete and create",
417 shorthandToPaths("2:[1];3:[1];4:[2];5:[2,3]"),
418 dep1.linkedByAsString());
419
420 assertEquals("Dependencies includes not correct after delete and create",
421 shorthandToPaths("1:[2,3,4];2:[4]"),
422 dep1.includesAsString());
423
424 assertEquals("Dependencies includedBy not correct after delete and create",
425 shorthandToPaths("2:[1];3:[1];4:[1,2]"),
426 dep1.includedByAsString());
427
428 }
429
430 /**
431 * Test Dependencies YamFile modification
432 * @throws Exception if the test fails
433 */
434 public void testModify() throws Exception {
435 log.info("============== DependenciesTests.testModify() ==================");
436 log.info("testing dependencies.modified(YamFile)");
437
438 // Holds results from Dependencies event operations
439 Set<String> toRegenerate;
440 List<String> toRegenerateSorted;
441
442
443 // File modification. We fake this by copying a modified version over
444 // an existing file, and re-generating the yam.
445 File currentFile = new File(yamDir, "yam-depends-2.yam");
446 File modFile = new File(yamDir, "yam-depends-MODIFIED-2.yam");
447 copy(modFile, currentFile);
448
449 // Regenerate the yam
450 yamFileMap.get("2").generate();
451
452 // Notify the modification
453 toRegenerate = dep1.modified(yamFileMap.get("2"));
454 toRegenerateSorted = new ArrayList<String>(toRegenerate);
455 Collections.sort(toRegenerateSorted);
456
457 assertEquals("Regenerate set not correct after modify",
458 numbersToList("1"),
459 toRegenerateSorted);
460
461 // Check all is how it should be
462 assertEquals("Dependencies linksTo not correct after modify",
463 shorthandToPaths("1:[2,3];2:[4,7];3:[5]"),
464 dep1.linksToAsString());
465
466 assertEquals("Dependencies linkedBy not correct after modify",
467 shorthandToPaths("2:[1];3:[1];4:[2];5:[3];7:[2]"),
468 dep1.linkedByAsString());
469
470 assertEquals("Dependencies includes not correct after modify",
471 shorthandToPaths("1:[2,3,4];2:[4]"),
472 dep1.includesAsString());
473
474 assertEquals("Dependencies includedBy not correct after modify",
475 shorthandToPaths("2:[1];3:[1];4:[1,2]"),
476 dep1.includedByAsString());
477
478 // Another File modification.
479 currentFile = new File(yamDir, "yam-depends-1.yam");
480 modFile = new File(yamDir, "yam-depends-MODIFIED-1.yam");
481 copy(modFile, currentFile);
482
483 // Regenerate the yam
484 yamFileMap.get("1").generate();
485
486 // Notify the modification
487 toRegenerate = dep1.modified(yamFileMap.get("1"));
488
489 assertEquals("Regenerate set not correct after modify",
490 new HashSet<String>(),
491 toRegenerate);
492
493 // Check all is how it should be
494 assertEquals("Dependencies linksTo not correct after modify",
495 shorthandToPaths("1:[2,3];2:[4,7];3:[5]"),
496 dep1.linksToAsString());
497
498 assertEquals("Dependencies linkedBy not correct after modify",
499 shorthandToPaths("2:[1];3:[1];4:[2];5:[3];7:[2]"),
500 dep1.linkedByAsString());
501
502 assertEquals("Dependencies includes not correct after modify",
503 shorthandToPaths("1:[3,4];2:[4]"),
504 dep1.includesAsString());
505
506 assertEquals("Dependencies includedBy not correct after modify",
507 shorthandToPaths("3:[1];4:[1,2]"),
508 dep1.includedByAsString());
509
510 // Modify all files back
511 copy(new File(yamDir, "yam-depends-ORIGINAL-1.yam"),
512 new File(yamDir, "yam-depends-1.yam"));
513 copy(new File(yamDir, "yam-depends-ORIGINAL-2.yam"),
514 new File(yamDir, "yam-depends-2.yam"));
515
516 // Regenerate the yams
517 yamFileMap.get("1").generate();
518 yamFileMap.get("2").generate();
519
520
521 }
522
523 /**
524 * Test links to non-yam files and urls
525 * @throws Exception if the test fails
526 */
527 public void testNonYamLinks() throws Exception {
528 log.info("============ DependenciesTests.testNonYamLinks() ===============");
529 log.info("testing links to non yam files and urls");
530
531 // Add a new file to the wiki, create it.
532 YamFile yf = yamFileMap.get("8");
533 wiki1.add(yf);
534 dep1.created(yf);
535
536 // Check all is how it should be
537 assertEquals("Dependencies linksTo not correct after create",
538 shorthandToPaths("1:[2,3];2:[4,5];3:[5];"
539 + "8:[../../non-existent.html,non-existent.html]"),
540 dep1.linksToAsString());
541
542 assertEquals("Dependencies linkedBy not correct after create",
543 shorthandToPaths("../../non-existent.html:[8];" + "" +
544 "non-existent.html:[8];2:[1];3:[1];4:[2];5:[2,3]"),
545 dep1.linkedByAsString());
546
547 assertEquals("Dependencies includes not correct after create",
548 shorthandToPaths("1:[2,3,4];2:[4]"),
549 dep1.includesAsString());
550
551 assertEquals("Dependencies includedBy not correct after create",
552 shorthandToPaths("2:[1];3:[1];4:[1,2]"),
553 dep1.includedByAsString());
554
555
556 // Get rid of the new file
557 dep1.deleted(yf);
558
559 // Check all is how it should be
560 assertEquals("Dependencies linksTo not correct after delete",
561 shorthandToPaths("1:[2,3];2:[4,5];3:[5]"),
562 dep1.linksToAsString());
563
564 assertEquals("Dependencies linkedBy not correct after delete",
565 shorthandToPaths("2:[1];3:[1];4:[2];5:[2,3]"),
566 dep1.linkedByAsString());
567
568 assertEquals("Dependencies includes not correct after delete",
569 shorthandToPaths("1:[2,3,4];2:[4]"),
570 dep1.includesAsString());
571
572 assertEquals("Dependencies includedBy not correct after delete",
573 shorthandToPaths("2:[1];3:[1];4:[1,2]"),
574 dep1.includedByAsString());
575
576
577 }
578
579
580 /**
581 * Test Dependencies File creation, deletion, and renaming
582 * @throws Exception if the test fails
583 */
584 public void testNonYamChanges() throws Exception {
585 log.info("========= DependenciesTests.testNonYamChanges() =============");
586
587 // Holds results from Dependencies event operations
588 Set<String> toRegenerate;
589 List<String> toRegenerateSorted;
590
591 // Create, ie upload, a file
592 log.info("testing dependencies.created(File)");
593 File nonYam = new File(yamDir, "nonYamFile.abc");
594 toRegenerate = dep1.created(nonYam);
595
596 // Should be nothing to regenerate, nothing links to it
597 assertEquals("Regenerate set not correct after created(File)",
598 new HashSet<String>(),
599 toRegenerate);
600
601 // Check all is how it should be - no changes
602 assertEquals("Dependencies linksTo not correct after create",
603 shorthandToPaths("1:[2,3];2:[4,5];3:[5]"),
604 dep1.linksToAsString());
605
606 assertEquals("Dependencies linkedBy not correct after create",
607 shorthandToPaths("2:[1];3:[1];4:[2];5:[2,3]"),
608 dep1.linkedByAsString());
609
610 assertEquals("Dependencies includes not correct after create",
611 shorthandToPaths("1:[2,3,4];2:[4]"),
612 dep1.includesAsString());
613
614 assertEquals("Dependencies includedBy not correct after create",
615 shorthandToPaths("2:[1];3:[1];4:[1,2]"),
616 dep1.includedByAsString());
617
618 // Now delete the non yam
619 toRegenerate = dep1.deleted(nonYam);
620
621 // Should be nothing to regenerate, nothing links to it
622 assertEquals("Regenerate set not correct after deleted(File)",
623 new HashSet<String>(),
624 toRegenerate);
625
626 // Now add in a page that links to a non-existent non-yam
627 YamFile linkingFile = yamFileMap.get("9");
628 wiki1.add(linkingFile);
629 toRegenerate = dep1.created(linkingFile);
630
631 // Should be nothing to regenerate, nothing dependent on 9 has changed
632 assertEquals("Regenerate set not correct after created(YamFile)",
633 new HashSet<String>(),
634 toRegenerate);
635
636 // Check all is how it should be - a new link to a non yam file
637 assertEquals("Dependencies linksTo not correct after create",
638 shorthandToPaths("1:[2,3];2:[4,5];3:[5];9:[nonYamFile.abc]"),
639 dep1.linksToAsString());
640
641 assertEquals("Dependencies linkedBy not correct after create",
642 shorthandToPaths("nonYamFile.abc:[9];2:[1];3:[1];4:[2];5:[2,3]"),
643 dep1.linkedByAsString());
644
645 assertEquals("Dependencies includes not correct after create",
646 shorthandToPaths("1:[2,3,4];2:[4]"),
647 dep1.includesAsString());
648
649 assertEquals("Dependencies includedBy not correct after create",
650 shorthandToPaths("2:[1];3:[1];4:[1,2]"),
651 dep1.includedByAsString());
652
653 // Now create the non yam file again
654 toRegenerate = dep1.created(nonYam);
655 toRegenerateSorted = new ArrayList<String>(toRegenerate);
656 Collections.sort(toRegenerateSorted);
657
658 // We should need to regenerate the web page that links to the non yam
659 assertEquals("Regenerate set not correct after created(File)",
660 numbersToList("9"),
661 toRegenerateSorted);
662
663 // Rename: we should have to regenerate the linker
664 // We don't really rename a file on the fiesystem, just pretend
665 log.info("testing dependencies.renamed(File, File)");
666 File nonYamRenamed = new File(yamDir, "nonYamFileRenamed.abc");
667 toRegenerate = dep1.renamed(nonYam, nonYamRenamed);
668 toRegenerateSorted = new ArrayList<String>(toRegenerate);
669 Collections.sort(toRegenerateSorted);
670
671 assertEquals("Regenerate set not correct after renamed(File)",
672 numbersToList("9"),
673 toRegenerateSorted);
674
675 // Check all is how it should be - link to the renamed file
676 assertEquals("Dependencies linksTo not correct after rename",
677 shorthandToPaths("1:[2,3];2:[4,5];3:[5];9:[nonYamFileRenamed.abc]"),
678 dep1.linksToAsString());
679
680 assertEquals("Dependencies linkedBy not correct after rename",
681 shorthandToPaths("nonYamFileRenamed.abc:[9];2:[1];3:[1];4:[2]"
682 + ";5:[2,3]"),
683 dep1.linkedByAsString());
684
685 assertEquals("Dependencies includes not correct after rename",
686 shorthandToPaths("1:[2,3,4];2:[4]"),
687 dep1.includesAsString());
688
689 assertEquals("Dependencies includedBy not correct after rename",
690 shorthandToPaths("2:[1];3:[1];4:[1,2]"),
691 dep1.includedByAsString());
692
693 // Delete: we should get some files to regenerate
694 log.info("testing dependencies.deleted(File)");
695 toRegenerate = dep1.deleted(nonYamRenamed);
696 toRegenerateSorted = new ArrayList<String>(toRegenerate);
697 Collections.sort(toRegenerateSorted);
698
699 assertEquals("Regenerate set not correct after deleted(File)",
700 numbersToList("9"),
701 toRegenerateSorted);
702
703 // Check all is how it should be - , with a link to a now non-existent file
704 assertEquals("Dependencies linksTo not correct after delete",
705 shorthandToPaths("1:[2,3];2:[4,5];3:[5];9:[nonYamFileRenamed.abc]"),
706 dep1.linksToAsString());
707
708 assertEquals("Dependencies linkedBy not correct after delete",
709 shorthandToPaths("nonYamFileRenamed.abc:[9];2:[1];3:[1];4:[2]"
710 + ";5:[2,3]"),
711 dep1.linkedByAsString());
712
713 assertEquals("Dependencies includes not correct after delete",
714 shorthandToPaths("1:[2,3,4];2:[4]"),
715 dep1.includesAsString());
716
717 assertEquals("Dependencies includedBy not correct after delete",
718 shorthandToPaths("2:[1];3:[1];4:[1,2]"),
719 dep1.includedByAsString());
720
721 // Remove the linking yam file - should be nothing to regenerate
722 toRegenerate = dep1.deleted(linkingFile);
723 assertEquals("Regenerate set not correct after deleted(YamFile)",
724 new HashSet<String>(),
725 toRegenerate);
726
727 // ... and we should be back to the beggining
728 assertEquals("Dependencies linksTo not correct after delete",
729 shorthandToPaths("1:[2,3];2:[4,5];3:[5]"),
730 dep1.linksToAsString());
731
732 assertEquals("Dependencies linkedBy not correct after delete",
733 shorthandToPaths("2:[1];3:[1];4:[2]"
734 + ";5:[2,3]"),
735 dep1.linkedByAsString());
736
737 assertEquals("Dependencies includes not correct after delete",
738 shorthandToPaths("1:[2,3,4];2:[4]"),
739 dep1.includesAsString());
740
741 assertEquals("Dependencies includedBy not correct after delete",
742 shorthandToPaths("2:[1];3:[1];4:[1,2]"),
743 dep1.includedByAsString());
744
745
746
747 }
748
749 /**
750 * Test Dependencies serialization
751 * @throws Exception if the test fails
752 */
753 public void testSerialization() throws Exception {
754 log.info("============= DependenciesTests.testSerialization() ============");
755 log.info("testing serialization and deserialization of Dependencies");
756
757 Dependencies.remove("1");
758 Dependencies dep1 = Dependencies.get("1");
759
760 // Add all the files in a wiki to the depencies
761 for(YamFile yam : wiki1) {
762 dep1.created(yam);
763 }
764
765 Dependencies.serialize();
766 Dependencies.clear();
767
768 assertTrue("Dependencies removed", Dependencies.exists("1"));
769
770 Dependencies dep1Reloaded = Dependencies.get("1");
771
772 assertEquals(
773 "Dependencies not consistently serialized / deserialized",
774 dep1, dep1Reloaded
775 );
776
777 Dependencies.remove("1");
778
779 }
780
781
782 /**
783 * Suite of tests for Dependencies
784 * @return The suite of tests
785 */
786 public static Test suite() {
787 TestSuite suite= new TestSuite();
788 suite.addTest(new DependenciesTests("testCreateAndBasics"));
789 suite.addTest(new DependenciesTests("testDelete"));
790 suite.addTest(new DependenciesTests("testRename"));
791 suite.addTest(new DependenciesTests("testDelete2"));
792 suite.addTest(new DependenciesTests("testModify"));
793 suite.addTest(new DependenciesTests("testNonYamLinks"));
794 suite.addTest(new DependenciesTests("testNonYamChanges"));
795 suite.addTest(new DependenciesTests("testSerialization"));
796 return suite;
797 }
798
799 /**
800 * <p>Replace all file numbers in str with the equivalent canonical paths in
801 * yamFileNameMap. All files used in Dependencies testing are named by
802 * convention as "yam-depends-\d+.yam". Dependencies will report its
803 * internal state graphs in the form "pathA:[pathB,pathC];pathB[pathD]",
804 * where pathX is the canonical path of a file.</p>
805 * <p>For test files, we can refer to a Dependencies graph in a shorthand form
806 * using just the digit part of the test name, e.g. "1:[2,3];2[4]" and then
807 * translate this to full canonical paths using this method.</p>
808 * <p>Non-yam files are referred to by their path relative to their linking
809 * node. They are replaced by their full canonical path. For example,
810 * "1:[some-file.html]", where some-file is not from yam, will become
811 * "/parent/path/yam-depends-1.yam:[/parent/path/some-file.html]"
812 * </p>
813 * @param str A string in which we want to replace numbers with test file
814 * canonical paths
815 * @return The equivalent string with numbers replaced by test file
816 * canonical paths
817 */
818 public String shorthandToPaths(String str) {
819
820 StringBuilder bldr = new StringBuilder();
821
822 for(String nodeAndArcs : str.split("(\\]\\;)|(\\])")) {
823 String[] nodeAndArcsSplit = nodeAndArcs.split("\\:\\[");
824 String node = nodeAndArcsSplit[0];
825 String arcs = nodeAndArcsSplit[1];
826
827 String nodePath = null;
828 if(node.matches("\\d+")) {
829 // We've got a number representing a yam file: map it to a filename
830 nodePath = yamFileNameMap.get(node);
831 } else {
832 // We've got a string representing a non-yam file
833 // A non-yam node is relative to its sole arc
834 // e.g. abc.html:[2]
835 File yamParent = new File(yamFileNameMap.get(arcs)).getParentFile();
836 try{
837 nodePath = new File(yamParent, node).getCanonicalPath();
838 } catch(IOException ioe) {
839 fail("Couldn't resolve link canonical path: " + ioe.getMessage());
840 }
841 }
842
843 bldr.append(nodePath);
844 bldr.append(":[");
845 for(String arc: arcs.split("\\,")) {
846 if(arc.matches("\\d+")) {
847 // We've got a number representing a yam file: map it to a filename
848 bldr.append(yamFileNameMap.get(arc));
849 } else {
850 // We've got a string representing a non-yam file
851 // An arc to a non-yam is relative to its node
852 File yamParent = new File(nodePath).getParentFile();
853 File link = new File(yamParent, arc);
854 try{
855 bldr.append(link.getCanonicalPath());
856 } catch(IOException ioe) {
857 fail("Couldn't resolve link canonical path: " + ioe.getMessage());
858 }
859 }
860 bldr.append(",");
861 }
862 bldr.deleteCharAt(bldr.length() - 1);
863 bldr.append("];");
864 }
865 bldr.deleteCharAt(bldr.length() - 1);
866
867 return bldr.toString();
868 }
869
870 /**
871 * Replace all file numbers in str with the equivalent canonical paths in
872 * yamFileNameMap, as described in
873 * @link DependenciesTests#shorthandToPaths(String).
874 * By convention, the file numbers in str are comma separated
875 * @param str A comma separated list of numbers
876 * @return A List of canonical paths equivalent to the numbers in str
877 */
878 private List<String> numbersToList(String str) {
879
880 List<String> pathList = new ArrayList<String>();
881
882 for(String number : str.split(",")) {
883 pathList.add(yamFileNameMap.get(number));
884 }
885
886 return pathList;
887 }
888
889 /**
890 * Copy one File to another. Testing fails if the copy fails.
891 * @param in The File that will be copied
892 * @param out The File to which in will be copied
893 */
894 private void copy(File in, File out) {
895
896 log.info("Copying yam file from: " + in.getName()
897 + " to: " + out.getName());
898
899 try {
900 FileChannel ic = new FileInputStream(in).getChannel();
901 FileChannel oc = new FileOutputStream(out).getChannel();
902 ic.transferTo(0, ic.size(), oc);
903 ic.close();
904 oc.close();
905 } catch (IOException ioe) {
906 fail("Failed testing while copying modified file: " + ioe.getMessage());
907 }
908 }
909
910 }
|