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, 2018, Oracle and/or its affiliates. All rights reserved. 22 * Portions Copyright (c) 2018-2019, Chris Fraire <cfraire@me.com>. 23 */ 24 package org.opengrok.indexer.history; 25 26 import java.io.ByteArrayInputStream; 27 import java.io.File; 28 import java.io.FileOutputStream; 29 import java.io.FileWriter; 30 import java.io.IOException; 31 import java.io.Reader; 32 import java.io.StringReader; 33 import java.nio.channels.FileChannel; 34 import java.util.ArrayList; 35 import java.util.List; 36 import org.junit.After; 37 import static org.junit.Assert.assertEquals; 38 import static org.junit.Assert.assertNotNull; 39 import static org.junit.Assert.assertTrue; 40 import static org.junit.Assert.fail; 41 import org.junit.Before; 42 import org.junit.Rule; 43 import org.junit.Test; 44 import org.opengrok.indexer.condition.ConditionalRun; 45 import org.opengrok.indexer.condition.ConditionalRunRule; 46 import org.opengrok.indexer.condition.RepositoryInstalled; 47 import org.opengrok.indexer.util.Executor; 48 import org.opengrok.indexer.util.IOUtils; 49 import org.opengrok.indexer.util.TestRepository; 50 51 /** 52 * 53 * @author austvik 54 */ 55 @ConditionalRun(RepositoryInstalled.CvsInstalled.class) 56 public class CVSRepositoryTest { 57 58 @Rule 59 public ConditionalRunRule rule = new ConditionalRunRule(); 60 61 CVSRepository instance; 62 63 private TestRepository repository; 64 65 /** 66 * Set up a test repository. Should be called by the tests that need it. The 67 * test repository will be destroyed automatically when the test finishes. 68 */ setUpTestRepository()69 private void setUpTestRepository() throws IOException { 70 repository = new TestRepository(); 71 repository.create(getClass().getResourceAsStream("repositories.zip")); 72 73 // Checkout cvsrepo anew in order to get the CVS/Root files point to 74 // the temporary directory rather than the OpenGrok workspace directory 75 // it was created from. This is necessary since 'cvs update' changes 76 // the CVS parent directory after branch has been created. 77 File root = new File(repository.getSourceRoot(), "cvs_test"); 78 File cvsrepodir = new File(root, "cvsrepo"); 79 IOUtils.removeRecursive(cvsrepodir.toPath()); 80 File cvsroot = new File(root, "cvsroot"); 81 runCvsCommand(root, "-d", cvsroot.getAbsolutePath(), "checkout", "cvsrepo"); 82 } 83 84 @After tearDown()85 public void tearDown() { 86 instance = null; 87 88 if (repository != null) { 89 repository.destroy(); 90 repository = null; 91 } 92 } 93 94 @Before setUp()95 public void setUp() { 96 instance = new CVSRepository(); 97 } 98 99 /** 100 * Run the 'cvs' command with some arguments. 101 * 102 * @param reposRoot directory of the repository root 103 * @param args arguments to use for the command 104 */ runCvsCommand(File reposRoot, String ... args)105 public static void runCvsCommand(File reposRoot, String ... args) { 106 List<String> cmdargs = new ArrayList<>(); 107 CVSRepository repo = new CVSRepository(); 108 cmdargs.add(repo.getRepoCommand()); 109 for (String arg: args) { 110 cmdargs.add(arg); 111 } 112 Executor exec = new Executor(cmdargs, reposRoot); 113 int exitCode = exec.exec(); 114 if (exitCode != 0) { 115 fail("cvs command '" + cmdargs.toString() + "'failed." 116 + "\nexit code: " + exitCode 117 + "\nstdout:\n" + exec.getOutputString() 118 + "\nstderr:\n" + exec.getErrorString()); 119 } 120 } 121 122 /** 123 * Get the CVS repository, test that getBranch() returns null if there is 124 * no branch. 125 * @throws Exception 126 */ 127 @Test testGetBranchNoBranch()128 public void testGetBranchNoBranch() throws Exception { 129 setUpTestRepository(); 130 File root = new File(repository.getSourceRoot(), "cvs_test/cvsrepo"); 131 CVSRepository cvsrepo 132 = (CVSRepository) RepositoryFactory.getRepository(root); 133 assertEquals(null, cvsrepo.getBranch()); 134 } 135 136 /** 137 * Get the CVS repository, create new branch, change a file and verify that 138 * getBranch() returns the branch and check newly added commits annotate 139 * with branch revision numbers. 140 * Last, check that history entries of the file follow through before the 141 * branch was created. 142 * @throws Exception 143 */ 144 @Test testNewBranch()145 public void testNewBranch() throws Exception { 146 setUpTestRepository(); 147 File root = new File(repository.getSourceRoot(), "cvs_test/cvsrepo"); 148 149 // Create new branch and switch to it. 150 runCvsCommand(root, "tag", "-b", "mybranch"); 151 // Note that the 'update' command will change the entries in 'cvsroot' directory. 152 runCvsCommand(root, "update", "-r", "mybranch"); 153 154 // Now the repository object can be instantiated so that determineBranch() 155 // will be called. 156 CVSRepository cvsrepo 157 = (CVSRepository) RepositoryFactory.getRepository(root); 158 159 assertEquals("mybranch", cvsrepo.getBranch()); 160 161 // Change the content and commit. 162 File mainC = new File(root, "main.c"); 163 FileChannel outChan = new FileOutputStream(mainC, true).getChannel(); 164 outChan.truncate(0); 165 outChan.close(); 166 FileWriter fw = new FileWriter(mainC); 167 fw.write("#include <foo.h>\n"); 168 fw.close(); 169 runCvsCommand(root, "commit", "-m", "change on a branch", "main.c"); 170 171 // Check that annotation for the changed line has branch revision. 172 Annotation annotation = cvsrepo.annotate(mainC, null); 173 assertEquals("1.2.2.1", annotation.getRevision(1)); 174 175 History mainCHistory = cvsrepo.getHistory(mainC); 176 assertEquals(3, mainCHistory.getHistoryEntries().size()); 177 assertEquals("1.2.2.1", mainCHistory.getHistoryEntries().get(0).getRevision()); 178 assertEquals("1.2", mainCHistory.getHistoryEntries().get(1).getRevision()); 179 assertEquals("1.1", mainCHistory.getHistoryEntries().get(2).getRevision()); 180 } 181 182 /** 183 * Test of fileHasAnnotation method, of class CVSRepository. 184 */ 185 @Test testFileHasAnnotation()186 public void testFileHasAnnotation() { 187 boolean result = instance.fileHasAnnotation(null); 188 assertTrue(result); 189 } 190 191 /** 192 * Test of fileHasHistory method, of class CVSRepository. 193 */ 194 @Test testFileHasHistory()195 public void testFileHasHistory() { 196 boolean result = instance.fileHasHistory(null); 197 assertTrue(result); 198 } 199 200 /** 201 * Test of parseAnnotation method, of class CVSRepository. 202 * @throws java.lang.Exception 203 */ 204 @Test testParseAnnotation()205 public void testParseAnnotation() throws Exception { 206 String revId1 = "1.1"; 207 String revId2 = "1.2.3"; 208 String revId3 = "1.0"; 209 String author1 = "author1"; 210 String author2 = "author_long2"; 211 String author3 = "author3"; 212 String output = "just jibberish in output\n\n" + revId1 + " (" + author1 + " 01-Mar-07) \n" + 213 revId2 + " (" + author2 + " 02-Mar-08) if (some code)\n" + 214 revId3 + " (" + author3 + " 30-Apr-07) call_function(i);\n"; 215 216 String fileName = "something.ext"; 217 218 CVSAnnotationParser parser = new CVSAnnotationParser(fileName); 219 parser.processStream(new ByteArrayInputStream(output.getBytes())); 220 Annotation result = parser.getAnnotation(); 221 222 assertNotNull(result); 223 assertEquals(3, result.size()); 224 for (int i = 1; i <= 3; i++) { 225 assertEquals(true, result.isEnabled(i)); 226 } 227 assertEquals(revId1, result.getRevision(1)); 228 assertEquals(revId2, result.getRevision(2)); 229 assertEquals(revId3, result.getRevision(3)); 230 assertEquals(author1, result.getAuthor(1)); 231 assertEquals(author2, result.getAuthor(2)); 232 assertEquals(author3, result.getAuthor(3)); 233 assertEquals(author2.length(), result.getWidestAuthor()); 234 assertEquals(revId2.length(), result.getWidestRevision()); 235 assertEquals(fileName, result.getFilename()); 236 } 237 238 } 239