Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 <[email protected]>.
*/
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 <[email protected]>.
<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
Loading