Skip to content

Commit

Permalink
fall back to the default temporary directory for ctags check
Browse files Browse the repository at this point in the history
fixes #4574
  • Loading branch information
vladak committed Oct 29, 2024
1 parent 785896c commit d186ae6
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ public synchronized boolean validateUniversalCtags() {
ctagsLanguages.addAll(languages);
}

ctagsFound = CtagsUtil.validate(ctagsBinary);
ctagsFound = CtagsUtil.isValid(ctagsBinary);
}

if (ctagsFound) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import org.apache.commons.lang3.SystemUtils;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.VisibleForTesting;
import org.opengrok.indexer.analysis.Ctags;
import org.opengrok.indexer.analysis.Definitions;
import org.opengrok.indexer.configuration.RuntimeEnvironment;
Expand Down Expand Up @@ -60,29 +61,33 @@ private CtagsUtil() {

/**
* Check that {@code ctags} program exists and is working.
* @param ctagsBinary name of the ctags program or path
* @param ctagsBinary name of the {@code ctags} program or path
* @return true if the program works, false otherwise
*/
public static boolean validate(String ctagsBinary) {
public static boolean isValid(String ctagsBinary) {
if (!isUniversalCtags(ctagsBinary)) {
return false;
}

return canProcessFiles(RuntimeEnvironment.getInstance().getSourceRootFile());
// The source root can be read-only. In such case, fall back to the default
// temporary directory as a second-best choice how to test that ctags is working.
return (canProcessFiles(RuntimeEnvironment.getInstance().getSourceRootFile()) ||
canProcessFiles(new File(System.getProperty("java.io.tmpdir"))));
}

/**
* Run ctags program on a known temporary file to be created under given path and see if it was possible
* to get some symbols.
* Run {@code ctags} program on a known temporary file to be created under given path
* and see if it was possible to get some symbols.
* @param baseDir directory to use for storing the temporary file
* @return true if at least one symbol was found, false otherwise
*/
private static boolean canProcessFiles(File baseDir) {
@VisibleForTesting
static boolean canProcessFiles(File baseDir) {
Path inputPath;
try {
inputPath = File.createTempFile("ctagsValidation", ".c", baseDir).toPath();
} catch (IOException e) {
LOGGER.log(Level.WARNING, "cannot create temporary file in ''{0}''", baseDir);
LOGGER.log(Level.WARNING, String.format("cannot create temporary file in '%s'", baseDir), e);
return false;
}
final String resourceFileName = "sample.c";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
*/

/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, Chris Fraire <cfraire@me.com>.
*/
package org.opengrok.indexer.util;

import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.opengrok.indexer.configuration.RuntimeEnvironment;

import java.io.IOException;
Expand All @@ -35,6 +37,9 @@
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.times;

/**
* Represents a container for tests of {@link CtagsUtil}.
Expand All @@ -51,19 +56,40 @@ void getLanguages() {
}

@Test
void validate() throws IOException {
void testIsValid() throws IOException {
RuntimeEnvironment env = RuntimeEnvironment.getInstance();
Path tmpSourceRoot = Files.createTempDirectory("srcRootCtagsValidationTest");
env.setSourceRoot(tmpSourceRoot.toString());
assertTrue(env.getSourceRootFile().exists());

assertTrue(CtagsUtil.validate(env.getCtags()));
assertTrue(CtagsUtil.isValid(env.getCtags()));

Files.delete(tmpSourceRoot);
}

/**
* Simulate non-writable source root and verify that {@link CtagsUtil#isValid(String)} still returns true
* as it should fall back to default temporary directory.
*/
@Test
void testValidateWithInvalidExtraOptions() throws IOException {
void testIsValidNoWritableSourceRoot() throws IOException {
RuntimeEnvironment env = RuntimeEnvironment.getInstance();
Path tmpSourceRoot = Files.createTempDirectory("negativeCtagsValidationTest");
env.setSourceRoot(tmpSourceRoot.toString());
assertTrue(env.getSourceRootFile().exists());

try (MockedStatic<CtagsUtil> mocked = mockStatic(CtagsUtil.class, Mockito.CALLS_REAL_METHODS)) {
mocked.when(() -> CtagsUtil.canProcessFiles(env.getSourceRootFile())).thenReturn(false);
assertTrue(CtagsUtil.isValid(env.getCtags()));
mocked.verify(() -> CtagsUtil.canProcessFiles(eq(env.getSourceRootFile())),
times(2)); // one extra for the lambda call above
}

Files.delete(tmpSourceRoot);
}

@Test
void testIsValidWithInvalidExtraOptions() throws IOException {
RuntimeEnvironment env = RuntimeEnvironment.getInstance();
Path tmpSourceRoot = Files.createTempDirectory("srcRootCtagsValidationTestExtraArgs");
env.setSourceRoot(tmpSourceRoot.toString());
Expand All @@ -74,7 +100,7 @@ void testValidateWithInvalidExtraOptions() throws IOException {
String extraOptionsAbsPath = extraOptionsPath.toAbsolutePath().toString();

env.setCTagsExtraOptionsFile(extraOptionsAbsPath);
assertFalse(CtagsUtil.validate(env.getCtags()));
assertFalse(CtagsUtil.isValid(env.getCtags()));

// cleanup
env.setCTagsExtraOptionsFile(null);
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Portions Copyright (c) 2018, 2020, Chris Fraire <cfraire@me.com>.
<maven-surefire.version>3.0.0-M5</maven-surefire.version>
<apache-commons-lang3.version>3.13.0</apache-commons-lang3.version>
<micrometer.version>1.11.4</micrometer.version>
<mockito.version>3.12.4</mockito.version>
<mockito.version>5.2.0</mockito.version>
<commons-io.version>2.14.0</commons-io.version>
</properties>

Expand Down

0 comments on commit d186ae6

Please sign in to comment.