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