1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * See LICENSE.txt included in this distribution for the specific 9 * language governing permissions and limitations under the License. 10 * 11 * When distributing Covered Code, include this CDDL HEADER in each 12 * file and include the License file at LICENSE.txt. 13 * If applicable, add the following below this CDDL HEADER, with the 14 * fields enclosed by brackets "[]" replaced with your own identifying 15 * information: Portions Copyright [yyyy] [name of copyright owner] 16 * 17 * CDDL HEADER END 18 */ 19 20 /* 21 * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. 22 * Portions Copyright (c) 2020, Chris Fraire <cfraire@me.com>. 23 */ 24 package org.opengrok.indexer.configuration; 25 26 import java.beans.ExceptionListener; 27 import java.beans.XMLDecoder; 28 import java.beans.XMLEncoder; 29 import java.io.BufferedOutputStream; 30 31 import java.io.File; 32 import java.io.FileInputStream; 33 import java.io.FileOutputStream; 34 import java.io.IOException; 35 import java.nio.file.Files; 36 import java.util.ArrayList; 37 import java.util.LinkedList; 38 import java.util.List; 39 40 import org.junit.jupiter.api.BeforeAll; 41 import org.junit.jupiter.api.Test; 42 import org.opengrok.indexer.analysis.c.CAnalyzerFactoryTest; 43 import org.opengrok.indexer.history.RepositoryFactory; 44 import org.opengrok.indexer.util.IOUtils; 45 import org.opengrok.indexer.util.TestRepository; 46 47 import static org.junit.jupiter.api.Assertions.assertEquals; 48 import static org.junit.jupiter.api.Assertions.assertFalse; 49 import static org.junit.jupiter.api.Assertions.assertNotNull; 50 import static org.junit.jupiter.api.Assertions.assertTrue; 51 52 /** 53 * 54 * @author Trond Norbye 55 */ 56 public class IgnoredNamesTest { 57 58 private final RuntimeEnvironment env = RuntimeEnvironment.getInstance(); 59 private static TestRepository repository; 60 61 @BeforeAll setUpClass()62 public static void setUpClass() throws Exception { 63 repository = new TestRepository(); 64 repository.create(CAnalyzerFactoryTest.class.getClassLoader().getResource("sources")); 65 66 // Populate ignored lists with repository specific entries. 67 RepositoryFactory.initializeIgnoredNames(RuntimeEnvironment.getInstance()); 68 } 69 70 /** 71 * Check that RepositoryFactory added repository specific entries to 72 * IgnoredNames. 73 */ 74 @Test testIgnoredSpecialPatterns()75 void testIgnoredSpecialPatterns() { 76 IgnoredNames instance = env.getIgnoredNames(); 77 78 /* Test handling of special directories. */ 79 assertTrue(instance.ignore("usr/src/.git")); 80 assertFalse(instance.ignore("usr/src/.git/foo")); 81 assertFalse(instance.ignore("usr/src/foo.git")); 82 } 83 84 @Test testAbsolutePathCheckWithPattern()85 void testAbsolutePathCheckWithPattern() { 86 IgnoredNames instance = new IgnoredNames(); 87 String currentDir = new File("").getAbsolutePath(); 88 String currentDirName = currentDir.substring(currentDir.lastIndexOf('/') + 1); 89 90 // Absolute path should not be matched against filenames. 91 instance.add("*" + currentDirName + "*"); 92 assertFalse(instance.ignore("foo")); 93 94 // Filename matching should still work. 95 instance.add("*foo*"); 96 assertTrue(instance.ignore("foo")); 97 } 98 99 @Test testIgnoredPatterns()100 void testIgnoredPatterns() { 101 IgnoredNames instance = new IgnoredNames(); 102 103 List<String> names = instance.getItems(); 104 assertNotNull(names); 105 106 /* self-test */ 107 for (String name : names) { 108 assertTrue(instance.ignore(name)); 109 } 110 111 /* Make sure common paths are not ignored by default. */ 112 assertFalse(instance.ignore("usr/src/foo/bin")); 113 assertFalse(instance.ignore("usr/src/foo/bin/bar.ksh")); 114 assertFalse(instance.ignore("usr/src/bar/obj")); 115 assertFalse(instance.ignore("usr/src/bar/obj/foo.ksh")); 116 assertFalse(instance.ignore("usr/src/foo/bar/usr.lib/main.c")); 117 assertFalse(instance.ignore("usr/src/foo/bar/usr.lib")); 118 119 /* cumulative test */ 120 names = new ArrayList<>(); 121 names.add("*.o"); 122 123 instance.setItems(names); 124 names = instance.getItems(); 125 assertEquals(1, names.size()); 126 127 assertTrue(instance.ignore("foo.o")); 128 assertFalse(instance.ignore("foo")); 129 assertTrue(instance.ignore(".o")); 130 assertFalse(instance.ignore("foo.oo")); 131 132 instance.add("f:Makefile"); 133 names = instance.getItems(); 134 assertEquals(2, names.size()); 135 assertTrue(instance.ignore(new File(repository.getSourceRoot() 136 + "/c/Makefile"))); 137 138 assertFalse(instance.ignore("main.c")); 139 140 instance.add("o*o?.a?c*"); 141 assertTrue(instance.ignore("opengrok.abc")); 142 assertTrue(instance.ignore("opengrok.abcd")); 143 assertFalse(instance.ignore("opengrok.ac")); 144 assertFalse(instance.ignore("grok.abcd")); 145 146 instance.add("d:haskell"); 147 assertTrue(instance.ignore(new File(repository.getSourceRoot() 148 + "/haskell"))); 149 150 instance.clear(); 151 names = instance.getItems(); 152 assertEquals(0, names.size()); 153 } 154 155 /** 156 * Make sure that encoding and decoding IgnoredNames object is 1:1 operation. 157 */ 158 @Test testEncodeDecode()159 void testEncodeDecode() throws IOException { 160 IgnoredNames in = new IgnoredNames(); 161 // Add file and directory to list of ignored items. 162 in.add("f:foo.txt"); 163 in.add("d:bar"); 164 165 // Create an exception listener to detect errors while encoding and decoding 166 final LinkedList<Exception> exceptions = new LinkedList<>(); 167 ExceptionListener listener = exceptions::addLast; 168 169 // Actually create the file and directory for much better test coverage. 170 File tmpdir = Files.createTempDirectory("ignoredNames").toFile(); 171 File foo = new File(tmpdir, "foo.txt"); 172 foo.createNewFile(); 173 assertTrue(foo.isFile()); 174 File bar = new File(tmpdir, "bar"); 175 bar.mkdir(); 176 assertTrue(bar.isDirectory()); 177 178 // Store the IgnoredNames object as XML file. 179 File testXML = new File(tmpdir, "Test.xml"); 180 XMLEncoder e = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(testXML))); 181 e.setExceptionListener(listener); 182 e.writeObject(in); 183 e.close(); 184 185 // Restore the IgnoredNames object from XML file. 186 XMLDecoder d = new XMLDecoder(new FileInputStream(testXML)); 187 IgnoredNames in2 = (IgnoredNames) d.readObject(); 188 d.close(); 189 190 // Verify that the XML encoding/decoding did not fail. 191 if (!exceptions.isEmpty()) { 192 // Can only chain one of the exceptions. Take the first one. 193 throw new AssertionError("Got " + exceptions.size() + " exception(s)", exceptions.getFirst()); 194 } 195 196 // Make sure the complete list of items is equal after decoding. 197 // This will is a simple casual test that cannot verify that sub-classes 198 // are intact. For that there are the following tests. 199 assertTrue(in.getItems().containsAll(in2.getItems())); 200 201 // Use the restored object to test the matching of file and directory. 202 assertTrue(in2.ignore("foo.txt")); 203 assertTrue(in2.ignore("bar")); 204 assertTrue(in2.ignore(foo)); 205 assertTrue(in2.ignore(bar)); 206 207 // Cleanup. 208 IOUtils.removeRecursive(tmpdir.toPath()); 209 } 210 } 211