xref: /OpenGrok/opengrok-indexer/src/test/java/org/opengrok/indexer/index/IndexerRepoTest.java (revision eecd4f60f3a13ea423e84d9a403830200ce60b9a)
1b5840353SAdam Hornáček /*
2b5840353SAdam Hornáček  * CDDL HEADER START
3b5840353SAdam Hornáček  *
4b5840353SAdam Hornáček  * The contents of this file are subject to the terms of the
5b5840353SAdam Hornáček  * Common Development and Distribution License (the "License").
6b5840353SAdam Hornáček  * You may not use this file except in compliance with the License.
7b5840353SAdam Hornáček  *
8b5840353SAdam Hornáček  * See LICENSE.txt included in this distribution for the specific
9b5840353SAdam Hornáček  * language governing permissions and limitations under the License.
10b5840353SAdam Hornáček  *
11b5840353SAdam Hornáček  * When distributing Covered Code, include this CDDL HEADER in each
12b5840353SAdam Hornáček  * file and include the License file at LICENSE.txt.
13b5840353SAdam Hornáček  * If applicable, add the following below this CDDL HEADER, with the
14b5840353SAdam Hornáček  * fields enclosed by brackets "[]" replaced with your own identifying
15b5840353SAdam Hornáček  * information: Portions Copyright [yyyy] [name of copyright owner]
16b5840353SAdam Hornáček  *
17b5840353SAdam Hornáček  * CDDL HEADER END
18b5840353SAdam Hornáček  */
19b5840353SAdam Hornáček 
20b5840353SAdam Hornáček /*
21*eecd4f60SVladimir Kotal  * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
225d9f3aa0SAdam Hornáček  * Portions Copyright (c) 2017, 2019, Chris Fraire <cfraire@me.com>.
23b5840353SAdam Hornáček  */
249805b761SAdam Hornáček package org.opengrok.indexer.index;
25b5840353SAdam Hornáček 
26b5840353SAdam Hornáček import java.io.File;
271161d3e8SAdam Hornacek 
28b5840353SAdam Hornáček import java.io.IOException;
299a303f19SAdam Hornacek import java.net.URISyntaxException;
30b5840353SAdam Hornáček import java.nio.file.Files;
31b5840353SAdam Hornáček import java.nio.file.Path;
32b5840353SAdam Hornáček import java.nio.file.Paths;
33b5840353SAdam Hornáček import java.util.Arrays;
34b5840353SAdam Hornáček import java.util.HashSet;
35b5840353SAdam Hornáček import java.util.List;
36b5840353SAdam Hornáček 
3752d10766SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertEquals;
3852d10766SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertNotNull;
3952d10766SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertNull;
4052d10766SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertTrue;
4152d10766SAdam Hornacek import static org.opengrok.indexer.condition.RepositoryInstalled.Type.MERCURIAL;
42b5840353SAdam Hornáček 
4352d10766SAdam Hornacek import org.junit.jupiter.api.AfterEach;
4452d10766SAdam Hornacek import org.junit.jupiter.api.BeforeEach;
4552d10766SAdam Hornacek import org.junit.jupiter.api.Test;
46*eecd4f60SVladimir Kotal import org.junit.jupiter.params.ParameterizedTest;
47*eecd4f60SVladimir Kotal import org.junit.jupiter.params.provider.ValueSource;
4852d10766SAdam Hornacek import org.opengrok.indexer.condition.EnabledForRepository;
499805b761SAdam Hornáček import org.opengrok.indexer.configuration.Project;
509805b761SAdam Hornáček import org.opengrok.indexer.configuration.RuntimeEnvironment;
519805b761SAdam Hornáček import org.opengrok.indexer.history.HistoryException;
529805b761SAdam Hornáček import org.opengrok.indexer.history.HistoryGuru;
539805b761SAdam Hornáček import org.opengrok.indexer.history.MercurialRepositoryTest;
549805b761SAdam Hornáček import org.opengrok.indexer.history.RepositoryInfo;
559805b761SAdam Hornáček import org.opengrok.indexer.util.TestRepository;
569805b761SAdam Hornáček import org.opengrok.indexer.util.IOUtils;
57b5840353SAdam Hornáček 
58b5840353SAdam Hornáček /**
59b5840353SAdam Hornáček  * Test indexer w.r.t. repositories.
60b5840353SAdam Hornáček  * @author Vladimir Kotal
61b5840353SAdam Hornáček  */
62*eecd4f60SVladimir Kotal class IndexerRepoTest {
63b5840353SAdam Hornáček 
64b5840353SAdam Hornáček     private TestRepository repository;
65b5840353SAdam Hornáček 
6652d10766SAdam Hornacek     @BeforeEach
setUp()679a303f19SAdam Hornacek     public void setUp() throws IOException, URISyntaxException {
68b5840353SAdam Hornáček         repository = new TestRepository();
69b5840353SAdam Hornáček         // For these tests we need Mercurial repository with renamed files.
709a303f19SAdam Hornacek         repository.create(HistoryGuru.class.getResource("/repositories"));
71b5840353SAdam Hornáček     }
72b5840353SAdam Hornáček 
7352d10766SAdam Hornacek     @AfterEach
tearDown()74b5840353SAdam Hornáček     public void tearDown() {
75b5840353SAdam Hornáček         repository.destroy();
76b5840353SAdam Hornáček     }
77b5840353SAdam Hornáček 
786e965927SVladimir Kotal     @EnabledForRepository(MERCURIAL)
79*eecd4f60SVladimir Kotal     @ParameterizedTest
80*eecd4f60SVladimir Kotal     @ValueSource(booleans = {false, true})
testPerProjectHistory(boolean globalOn)81*eecd4f60SVladimir Kotal     void testPerProjectHistory(boolean globalOn) throws IndexerException, IOException, HistoryException {
82b5840353SAdam Hornáček         RuntimeEnvironment env = RuntimeEnvironment.getInstance();
83b5840353SAdam Hornáček 
84b5840353SAdam Hornáček         // Make sure we start from scratch.
85b5840353SAdam Hornáček         Path dataRoot = Files.createTempDirectory("dataForPerProjectHistoryTest");
86b5840353SAdam Hornáček         env.setDataRoot(dataRoot.toString());
87b5840353SAdam Hornáček         env.setProjectsEnabled(true);
88b5840353SAdam Hornáček         env.setHistoryEnabled(globalOn);
89b5840353SAdam Hornáček 
90*eecd4f60SVladimir Kotal         // The projects have to be added first so that prepareIndexer() can use their configuration.
91b5840353SAdam Hornáček         Project proj = new Project("mercurial", "/mercurial");
92b5840353SAdam Hornáček         proj.setHistoryEnabled(!globalOn);
93b5840353SAdam Hornáček         env.getProjects().clear();
94b5840353SAdam Hornáček         env.getProjects().put("mercurial", proj);
95*eecd4f60SVladimir Kotal         proj = new Project("git", "/git");
96*eecd4f60SVladimir Kotal         env.getProjects().put("git", proj);
97b5840353SAdam Hornáček 
98*eecd4f60SVladimir Kotal         HistoryGuru.getInstance().clear();
99b5840353SAdam Hornáček         Indexer.getInstance().prepareIndexer(
100b5840353SAdam Hornáček                 env,
101b5840353SAdam Hornáček                 true, // search for repositories
102b5840353SAdam Hornáček                 true, // scan and add projects
103b5840353SAdam Hornáček                 false, // don't create dictionary
104b5840353SAdam Hornáček                 null, // subFiles - not needed since we don't list files
10518d0c95fSVladimir Kotal                 null); // repositories - not needed when not refreshing history
106*eecd4f60SVladimir Kotal         env.generateProjectRepositoriesMap();
107b5840353SAdam Hornáček 
108*eecd4f60SVladimir Kotal         // The repositories of the git project should follow the global history setting.
109b5840353SAdam Hornáček         File repoRoot = new File(env.getSourceRootFile(), "git");
110b5840353SAdam Hornáček         File fileInRepo = new File(repoRoot, "main.c");
111b5840353SAdam Hornáček         assertTrue(fileInRepo.exists());
112b5840353SAdam Hornáček         if (globalOn) {
113b5840353SAdam Hornáček             assertNotNull(HistoryGuru.getInstance().getHistory(fileInRepo));
114b5840353SAdam Hornáček         } else {
115b5840353SAdam Hornáček             assertNull(HistoryGuru.getInstance().getHistory(fileInRepo));
116b5840353SAdam Hornáček         }
117b5840353SAdam Hornáček 
118*eecd4f60SVladimir Kotal         // The repositories of the mercurial project should be opposite to the global history setting.
119b5840353SAdam Hornáček         repoRoot = new File(env.getSourceRootFile(), "mercurial");
120b5840353SAdam Hornáček         fileInRepo = new File(repoRoot, "main.c");
121b5840353SAdam Hornáček         assertTrue(fileInRepo.exists());
122b5840353SAdam Hornáček         if (globalOn) {
123b5840353SAdam Hornáček             assertNull(HistoryGuru.getInstance().getHistory(fileInRepo));
124b5840353SAdam Hornáček         } else {
125b5840353SAdam Hornáček             assertNotNull(HistoryGuru.getInstance().getHistory(fileInRepo));
126b5840353SAdam Hornáček         }
127b5840353SAdam Hornáček 
128b5840353SAdam Hornáček         IOUtils.removeRecursive(dataRoot);
129b5840353SAdam Hornáček     }
130b5840353SAdam Hornáček 
131b5840353SAdam Hornáček     /**
132b5840353SAdam Hornáček      * Test that symlinked directories from source root get their relative
133b5840353SAdam Hornáček      * path set correctly in RepositoryInfo objects.
134b5840353SAdam Hornáček      */
13552d10766SAdam Hornacek     @EnabledForRepository(MERCURIAL)
136b5840353SAdam Hornáček     @Test
testSymlinks()137*eecd4f60SVladimir Kotal     void testSymlinks() throws IndexerException, IOException {
138b5840353SAdam Hornáček 
139b5840353SAdam Hornáček         final String SYMLINK = "symlink";
140b5840353SAdam Hornáček         RuntimeEnvironment env = RuntimeEnvironment.getInstance();
141b5840353SAdam Hornáček 
142b5840353SAdam Hornáček         // Set source root to pristine directory so that there is only one
143b5840353SAdam Hornáček         // repository to deal with (which makes this faster and easier to write)
144b5840353SAdam Hornáček         // and clone the mercurial repository outside of the source root.
145b5840353SAdam Hornáček         Path realSource = Files.createTempDirectory("real");
146b5840353SAdam Hornáček         Path sourceRoot = Files.createTempDirectory("src");
147b5840353SAdam Hornáček         MercurialRepositoryTest.runHgCommand(sourceRoot.toFile(),
148b5840353SAdam Hornáček                 "clone", repository.getSourceRoot() + File.separator + "mercurial",
149b5840353SAdam Hornáček                 realSource.toString());
150b5840353SAdam Hornáček 
151b5840353SAdam Hornáček         // Create symlink from source root to the real repository.
152b5840353SAdam Hornáček         String symlinkPath = sourceRoot.toString() + File.separator + SYMLINK;
153b5840353SAdam Hornáček         Files.createSymbolicLink(Paths.get(symlinkPath), realSource);
154b5840353SAdam Hornáček 
155b5840353SAdam Hornáček         // Use alternative source root.
156b5840353SAdam Hornáček         env.setSourceRoot(sourceRoot.toString());
157b5840353SAdam Hornáček         // Need to have history cache enabled in order to perform scan of repositories.
158b5840353SAdam Hornáček         env.setHistoryEnabled(true);
159b5840353SAdam Hornáček         // Normally the Indexer would add the symlink automatically.
160b5840353SAdam Hornáček         env.setAllowedSymlinks(new HashSet<>(Arrays.asList(symlinkPath)));
161b5840353SAdam Hornáček 
162b5840353SAdam Hornáček         // Do a rescan of the projects, and only that (we don't care about
163b5840353SAdam Hornáček         // the other aspects of indexing in this test case).
164b5840353SAdam Hornáček         Indexer.getInstance().prepareIndexer(
165b5840353SAdam Hornáček                 env,
166b5840353SAdam Hornáček                 true, // search for repositories
167b5840353SAdam Hornáček                 true, // scan and add projects
168b5840353SAdam Hornáček                 false, // don't create dictionary
169b5840353SAdam Hornáček                 null, // subFiles - not needed since we don't list files
17018d0c95fSVladimir Kotal                 null); // repositories - not needed when not refreshing history
171b5840353SAdam Hornáček 
17218d0c95fSVladimir Kotal         // Check the repository paths.
173b5840353SAdam Hornáček         List<RepositoryInfo> repos = env.getRepositories();
174b5840353SAdam Hornáček         assertEquals(repos.size(), 1);
175b5840353SAdam Hornáček         RepositoryInfo repo = repos.get(0);
1766e4ec685SVladimir Kotal         assertEquals(File.separator + SYMLINK, repo.getDirectoryNameRelative());
177b5840353SAdam Hornáček         String epath = sourceRoot.toString() + File.separator + SYMLINK;
178b5840353SAdam Hornáček         String apath = repo.getDirectoryName();
17952d10766SAdam Hornacek         assertTrue(epath.equals(apath) || apath.equals("/private" + epath),
18052d10766SAdam Hornacek                 "Should match (with macOS leeway):\n" + epath + "\nv.\n" + apath);
181b5840353SAdam Hornáček 
182b5840353SAdam Hornáček         // Check that history exists for a file in the repository.
183b5840353SAdam Hornáček         File repoRoot = new File(env.getSourceRootFile(), SYMLINK);
184b5840353SAdam Hornáček         File fileInRepo = new File(repoRoot, "main.c");
185b5840353SAdam Hornáček         assertTrue(fileInRepo.exists());
186b5840353SAdam Hornáček         assertTrue(HistoryGuru.getInstance().hasHistory(fileInRepo));
187b5840353SAdam Hornáček         assertTrue(HistoryGuru.getInstance().hasCacheForFile(fileInRepo));
188b5840353SAdam Hornáček 
189b5840353SAdam Hornáček         // cleanup
190b5840353SAdam Hornáček         IOUtils.removeRecursive(realSource);
191b5840353SAdam Hornáček         IOUtils.removeRecursive(sourceRoot);
192b5840353SAdam Hornáček     }
193b5840353SAdam Hornáček }
194