Skip to content

Commit fd21647

Browse files
committed
Add IndexDatabaseSymlinksTest
1 parent c6987dc commit fd21647

File tree

2 files changed

+223
-0
lines changed

2 files changed

+223
-0
lines changed
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
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) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
22+
* Portions Copyright (c) 2018-2019, Chris Fraire <[email protected]>.
23+
*/
24+
package org.opengrok.indexer.index;
25+
26+
import static org.junit.Assert.assertFalse;
27+
import static org.junit.Assert.assertTrue;
28+
29+
import org.junit.AfterClass;
30+
import org.junit.Before;
31+
import org.junit.BeforeClass;
32+
import org.junit.ClassRule;
33+
import org.junit.Rule;
34+
import org.junit.Test;
35+
import org.junit.rules.TestRule;
36+
import org.junit.rules.TestWatcher;
37+
import org.junit.runner.Description;
38+
import org.opengrok.indexer.condition.ConditionalRun;
39+
import org.opengrok.indexer.condition.ConditionalRunRule;
40+
import org.opengrok.indexer.condition.CtagsInstalled;
41+
import org.opengrok.indexer.condition.RepositoryInstalled;
42+
import org.opengrok.indexer.condition.UnixPresent;
43+
import org.opengrok.indexer.configuration.RuntimeEnvironment;
44+
import org.opengrok.indexer.history.RepositoryFactory;
45+
import org.opengrok.indexer.util.TestRepository;
46+
47+
import java.io.File;
48+
import java.io.IOException;
49+
import java.nio.file.Files;
50+
import java.nio.file.Path;
51+
import java.nio.file.Paths;
52+
import java.util.Arrays;
53+
import java.util.Collections;
54+
import java.util.HashSet;
55+
import java.util.TreeSet;
56+
57+
/**
58+
* Represents a container for additional tests of {@link IndexDatabase} for symlinks.
59+
*/
60+
@ConditionalRun(UnixPresent.class)
61+
@ConditionalRun(CtagsInstalled.class)
62+
@ConditionalRun(RepositoryInstalled.GitInstalled.class)
63+
@ConditionalRun(RepositoryInstalled.MercurialInstalled.class)
64+
public class IndexDatabaseSymlinksTest {
65+
66+
private static RuntimeEnvironment env;
67+
private static TestRepository repository;
68+
69+
@ClassRule
70+
public static ConditionalRunRule rule = new ConditionalRunRule();
71+
72+
@Rule
73+
public TestRule watcher = new TestWatcher() {
74+
protected void starting(Description description) {
75+
System.out.println("Starting test: " + description.getMethodName());
76+
}
77+
};
78+
79+
@BeforeClass
80+
public static void setUpClass() throws Exception {
81+
env = RuntimeEnvironment.getInstance();
82+
83+
repository = new TestRepository();
84+
repository.createExternal(IndexDatabaseSymlinksTest.class.getResourceAsStream(
85+
"/index/links_tests.zip"));
86+
87+
// Create and verify symlink from source/ to external/links_tests/links
88+
Path symlink = Paths.get(repository.getSourceRoot(), "links");
89+
Path target = Paths.get(repository.getExternalRoot(), "links_tests", "links");
90+
assertTrue(target + "should exist", target.toFile().exists());
91+
Files.createSymbolicLink(symlink, target);
92+
assertTrue(symlink + " should exist", symlink.toFile().exists());
93+
94+
env.setSourceRoot(repository.getSourceRoot());
95+
env.setDataRoot(repository.getDataRoot());
96+
env.setHistoryEnabled(true);
97+
env.setProjectsEnabled(true);
98+
RepositoryFactory.initializeIgnoredNames(env);
99+
}
100+
101+
@Before
102+
public void setUp() {
103+
repository.purgeData();
104+
env.setAllowedSymlinks(new HashSet<>());
105+
env.setCanonicalRoots(new HashSet<>());
106+
}
107+
108+
@AfterClass
109+
public static void tearDownClass() {
110+
repository.destroy();
111+
env.setAllowedSymlinks(new HashSet<>());
112+
env.setCanonicalRoots(new HashSet<>());
113+
}
114+
115+
@Test
116+
public void testSymlinksDisallowed() throws IOException, IndexerException {
117+
runIndexer();
118+
lsdir(env.getDataRootPath());
119+
120+
Path xref = Paths.get(env.getDataRootPath(), "xref");
121+
assertFalse(xref + " should not exist", xref.toFile().exists());
122+
}
123+
124+
@Test
125+
public void testSymlinksWithFullCanonicalRoot() throws IOException, IndexerException {
126+
File externalRoot = new File(repository.getExternalRoot());
127+
128+
env.setCanonicalRoots(new HashSet<>(Collections.singletonList(
129+
externalRoot.getCanonicalPath())));
130+
runIndexer();
131+
lsdir(env.getDataRootPath());
132+
133+
Path xref = Paths.get(env.getDataRootPath(), "xref");
134+
assertTrue(xref + " should exist", xref.toFile().exists());
135+
136+
Path links = xref.resolve("links");
137+
assertTrue(links + " should exist", links.toFile().exists());
138+
139+
Path gitDir = links.resolve("gt");
140+
assertTrue(gitDir + " should exist", gitDir.toFile().exists());
141+
142+
Path mercurialDir = links.resolve("mrcrl");
143+
assertTrue(mercurialDir + " should exist", mercurialDir.toFile().exists());
144+
145+
Path dupeLinkDir = links.resolve("zzz");
146+
assertTrue(dupeLinkDir + " should exist", dupeLinkDir.toFile().exists());
147+
}
148+
149+
@Test
150+
public void testSymlinksWithOneAllowedSymlink() throws IOException, IndexerException {
151+
File canonicalSourceRoot = new File(repository.getSourceRoot()).getCanonicalFile();
152+
Path linksSourceDir = Paths.get(canonicalSourceRoot.getPath(), "links");
153+
Path gitSourceDir = linksSourceDir.resolve("gt");
154+
assertTrue(gitSourceDir + " should exist", gitSourceDir.toFile().exists());
155+
156+
env.setAllowedSymlinks(new HashSet<>(Arrays.asList(
157+
linksSourceDir.toString(), gitSourceDir.toString())));
158+
runIndexer();
159+
lsdir(env.getDataRootPath());
160+
161+
Path xref = Paths.get(env.getDataRootPath(), "xref");
162+
assertTrue(xref + " should exist", xref.toFile().exists());
163+
164+
Path links = xref.resolve("links");
165+
assertTrue(links + " should exist", links.toFile().exists());
166+
167+
Path gitDir = links.resolve("gt");
168+
assertTrue(gitDir + " should exist", gitDir.toFile().exists());
169+
170+
Path mercurialDir = links.resolve("mrcrl");
171+
assertFalse(mercurialDir + " should not exist", mercurialDir.toFile().exists());
172+
173+
Path dupeLinkDir = links.resolve("zzz");
174+
/*
175+
* zzz is an implicitly-allowed symlink because its target, the gz
176+
* symlink, is explictly allowed as well as reachable by traversal by
177+
* indexDown() (to affirm that any intermediate symlinks are allowed).
178+
*/
179+
assertTrue(dupeLinkDir + " should not exist", dupeLinkDir.toFile().exists());
180+
}
181+
182+
private static void runIndexer() throws IndexerException, IOException {
183+
Indexer indexer = Indexer.getInstance();
184+
indexer.prepareIndexer(env, true, true, false, null, null);
185+
env.setDefaultProjectsFromNames(new TreeSet<>(Collections.singletonList("/c")));
186+
indexer.doIndexerExecution(true, null, null);
187+
}
188+
189+
private static void lsdir(String name) {
190+
File file = Paths.get(name).toFile();
191+
if (!file.exists()) {
192+
return;
193+
}
194+
195+
lsobj(file);
196+
if (Files.isSymbolicLink(file.toPath())) {
197+
return;
198+
}
199+
200+
String[] fileList = file.list();
201+
if (fileList == null) {
202+
return;
203+
}
204+
205+
for (String filename : fileList) {
206+
Path child = Paths.get(name, filename);
207+
lsdir(child.toString());
208+
}
209+
}
210+
211+
private static void lsobj(File file) {
212+
if (!file.exists()) {
213+
return;
214+
}
215+
System.out.print(file.getPath());
216+
if (Files.isSymbolicLink(file.toPath())) {
217+
System.out.print(" ->");
218+
} else if (file.isDirectory()) {
219+
System.out.print("/");
220+
}
221+
System.out.println();
222+
}
223+
}
Binary file not shown.

0 commit comments

Comments
 (0)