diff --git a/cli/src/main/java/com/devonfw/tools/ide/context/AbstractIdeContext.java b/cli/src/main/java/com/devonfw/tools/ide/context/AbstractIdeContext.java index 3f041c37c..513b6a0b2 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/context/AbstractIdeContext.java +++ b/cli/src/main/java/com/devonfw/tools/ide/context/AbstractIdeContext.java @@ -12,8 +12,6 @@ import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Objects; -import java.util.function.Function; import com.devonfw.tools.ide.cli.CliAbortException; import com.devonfw.tools.ide.cli.CliArgument; @@ -34,8 +32,9 @@ import com.devonfw.tools.ide.io.FileAccess; import com.devonfw.tools.ide.io.FileAccessImpl; import com.devonfw.tools.ide.log.IdeLogLevel; +import com.devonfw.tools.ide.log.IdeLogger; +import com.devonfw.tools.ide.log.IdeLoggerImpl; import com.devonfw.tools.ide.log.IdeSubLogger; -import com.devonfw.tools.ide.log.IdeSubLoggerNone; import com.devonfw.tools.ide.merge.DirectoryMerger; import com.devonfw.tools.ide.network.ProxyContext; import com.devonfw.tools.ide.os.SystemInfo; @@ -60,7 +59,7 @@ public abstract class AbstractIdeContext implements IdeContext { private static final String IDE_URLS_GIT = "https://github.com/devonfw/ide-urls.git"; - private final Map loggers; + private final IdeLoggerImpl logger; private Path ideHome; @@ -116,8 +115,6 @@ public abstract class AbstractIdeContext implements IdeContext { private DirectoryMerger workspaceMerger; - private final Function loggerFactory; - private boolean offlineMode; private boolean forceMode; @@ -137,18 +134,15 @@ public abstract class AbstractIdeContext implements IdeContext { /** * The constructor. * - * @param minLogLevel the minimum {@link IdeLogLevel} to enable. Should be {@link IdeLogLevel#INFO} by default. - * @param factory the {@link Function} to create {@link IdeSubLogger} per {@link IdeLogLevel}. + * @param logger the {@link IdeLogger}. * @param userDir the optional {@link Path} to current working directory. * @param toolRepository @param toolRepository the {@link ToolRepository} of the context. If it is set to {@code null} {@link DefaultToolRepository} will * be used. */ - public AbstractIdeContext(IdeLogLevel minLogLevel, Function factory, Path userDir, ToolRepository toolRepository) { + public AbstractIdeContext(IdeLoggerImpl logger, Path userDir, ToolRepository toolRepository) { super(); - this.loggerFactory = factory; - this.loggers = new HashMap<>(); - setLogLevel(minLogLevel); + this.logger = logger; this.systemInfo = SystemInfoImpl.INSTANCE; this.commandletManager = new CommandletManagerImpl(this); this.fileAccess = new FileAccessImpl(this); @@ -309,14 +303,6 @@ public String getMessageIdeHome() { */ public boolean isTest() { - return isMock(); - } - - /** - * @return {@code true} if this is a mock context for JUnits, {@code false} otherwise. - */ - public boolean isMock() { - return false; } @@ -708,9 +694,7 @@ protected ProcessContext createProcessContext() { @Override public IdeSubLogger level(IdeLogLevel level) { - IdeSubLogger logger = this.loggers.get(level); - Objects.requireNonNull(logger); - return logger; + return this.logger.level(level); } @Override @@ -793,24 +777,6 @@ private static void addMapping(Map mapping, String key, O option) } } - /** - * Sets the log level. - * - * @param logLevel {@link IdeLogLevel} - */ - public void setLogLevel(IdeLogLevel logLevel) { - - for (IdeLogLevel level : IdeLogLevel.values()) { - IdeSubLogger logger; - if (level.ordinal() < logLevel.ordinal()) { - logger = new IdeSubLoggerNone(level); - } else { - logger = this.loggerFactory.apply(level); - } - this.loggers.put(level, logger); - } - } - @Override public Step getCurrentStep() { @@ -918,7 +884,13 @@ private boolean applyAndRun(CliArguments arguments, Commandlet cmd) { } else if (cmd.isIdeRootRequired() && (this.ideRoot == null)) { throw new CliException(getMessageIdeRootNotFound(), ProcessResult.NO_IDE_ROOT); } - if (!cmd.isProcessableOutput()) { + if (cmd.isProcessableOutput()) { + for (IdeLogLevel level : IdeLogLevel.values()) { + if (level != IdeLogLevel.INFO) { + this.logger.setLogLevel(level, false); + } + } + } else { if (cmd.isIdeHomeRequired()) { debug(getMessageIdeHomeFound()); } diff --git a/cli/src/main/java/com/devonfw/tools/ide/context/IdeContextConsole.java b/cli/src/main/java/com/devonfw/tools/ide/context/IdeContextConsole.java index 4f114459e..d1331c7bd 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/context/IdeContextConsole.java +++ b/cli/src/main/java/com/devonfw/tools/ide/context/IdeContextConsole.java @@ -5,6 +5,7 @@ import com.devonfw.tools.ide.io.IdeProgressBar; import com.devonfw.tools.ide.io.IdeProgressBarConsole; import com.devonfw.tools.ide.log.IdeLogLevel; +import com.devonfw.tools.ide.log.IdeLoggerImpl; import com.devonfw.tools.ide.log.IdeSubLoggerOut; import me.tongfei.progressbar.ProgressBarBuilder; @@ -26,7 +27,7 @@ public class IdeContextConsole extends AbstractIdeContext { */ public IdeContextConsole(IdeLogLevel minLogLevel, Appendable out, boolean colored) { - super(minLogLevel, level -> new IdeSubLoggerOut(level, out, colored, minLogLevel), null, null); + super(new IdeLoggerImpl(minLogLevel, level -> new IdeSubLoggerOut(level, out, colored, minLogLevel)), null, null); if (System.console() == null) { debug("System console not available - using System.in as fallback"); this.scanner = new Scanner(System.in); diff --git a/cli/src/main/java/com/devonfw/tools/ide/log/IdeLoggerImpl.java b/cli/src/main/java/com/devonfw/tools/ide/log/IdeLoggerImpl.java new file mode 100644 index 000000000..c2982380e --- /dev/null +++ b/cli/src/main/java/com/devonfw/tools/ide/log/IdeLoggerImpl.java @@ -0,0 +1,63 @@ +package com.devonfw.tools.ide.log; + +import java.util.Objects; +import java.util.function.Function; + +/** + * Implementation of {@link IdeLogger}. + */ +public class IdeLoggerImpl implements IdeLogger { + + private final Function loggerFactory; + + private final IdeSubLogger[] loggers; + + /** + * @param minLogLevel the minimum enabled {@link IdeLogLevel}. + * @param factory the factory to create active {@link IdeSubLogger} instances. + */ + public IdeLoggerImpl(IdeLogLevel minLogLevel, Function factory) { + + super(); + this.loggerFactory = factory; + this.loggers = new IdeSubLogger[IdeLogLevel.values().length]; + setLogLevel(minLogLevel); + } + + @Override + public IdeSubLogger level(IdeLogLevel level) { + + IdeSubLogger logger = this.loggers[level.ordinal()]; + Objects.requireNonNull(logger); + return logger; + } + + /** + * Sets the log level. + * + * @param logLevel {@link IdeLogLevel} + */ + public void setLogLevel(IdeLogLevel logLevel) { + + for (IdeLogLevel level : IdeLogLevel.values()) { + boolean enabled = level.ordinal() >= logLevel.ordinal(); + setLogLevel(level, enabled); + } + } + + /** + * @param logLevel the {@link IdeLogLevel} to modify. + * @param enabled - {@code true} to enable, {@code false} to disable. + */ + public void setLogLevel(IdeLogLevel logLevel, boolean enabled) { + + IdeSubLogger logger; + if (enabled) { + logger = this.loggerFactory.apply(logLevel); + } else { + logger = IdeSubLoggerNone.of(logLevel); + } + this.loggers[logLevel.ordinal()] = logger; + } + +} diff --git a/cli/src/main/java/com/devonfw/tools/ide/log/IdeSubLoggerNone.java b/cli/src/main/java/com/devonfw/tools/ide/log/IdeSubLoggerNone.java index 1154f7a4d..3b08c0c66 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/log/IdeSubLoggerNone.java +++ b/cli/src/main/java/com/devonfw/tools/ide/log/IdeSubLoggerNone.java @@ -5,12 +5,22 @@ */ public final class IdeSubLoggerNone extends AbstractIdeSubLogger { + private static final IdeSubLoggerNone[] LOGGERS; + + static { + IdeLogLevel[] levels = IdeLogLevel.values(); + LOGGERS = new IdeSubLoggerNone[levels.length]; + for (int i = 0; i < levels.length; i++) { + LOGGERS[i] = new IdeSubLoggerNone(levels[i]); + } + } + /** * The constructor. * * @param level the {@link #getLevel() log-level}. */ - public IdeSubLoggerNone(IdeLogLevel level) { + private IdeSubLoggerNone(IdeLogLevel level) { super(level); } @@ -27,4 +37,13 @@ public boolean isEnabled() { return false; } + /** + * @param level the {@link IdeLogLevel}. + * @return the {@link IdeSubLoggerNone} instance. + */ + public static IdeSubLoggerNone of(IdeLogLevel level) { + + return LOGGERS[level.ordinal()]; + } + } diff --git a/cli/src/test/java/com/devonfw/tools/ide/completion/IdeCompleterTest.java b/cli/src/test/java/com/devonfw/tools/ide/completion/IdeCompleterTest.java index d04efa2b5..1211830c7 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/completion/IdeCompleterTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/completion/IdeCompleterTest.java @@ -128,6 +128,6 @@ private IdeCompleter newCompleter() { private IdeTestContext newTestContext() { - return new IdeTestContext(Path.of(""), ""); + return new IdeTestContext(Path.of("")); } } diff --git a/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeContextTest.java b/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeContextTest.java index 84ee34356..704d70d76 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeContextTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeContextTest.java @@ -34,8 +34,8 @@ public abstract class AbstractIdeContextTest extends Assertions { private static final int CHUNK_SIZE = 1024; /** - * @param testProject the (folder)name of the project test case, in this folder a 'project' folder represents the test project in {@link #TEST_PROJECTS}. E.g. - * "basic". + * @param testProject the (folder)name of the project test case, in this folder a 'project' folder represents the test project in {@link #TEST_PROJECTS}. + * E.g. "basic". * @return the {@link IdeTestContext} pointing to that project. */ protected IdeTestContext newContext(String testProject) { @@ -44,8 +44,8 @@ protected IdeTestContext newContext(String testProject) { } /** - * @param testProject the (folder)name of the project test case, in this folder a 'project' folder represents the test project in {@link #TEST_PROJECTS}. E.g. - * "basic". + * @param testProject the (folder)name of the project test case, in this folder a 'project' folder represents the test project in {@link #TEST_PROJECTS}. + * E.g. "basic". * @param projectPath the relative path inside the test project where to create the context. * @return the {@link IdeTestContext} pointing to that project. */ @@ -55,11 +55,11 @@ protected static IdeTestContext newContext(String testProject, String projectPat } /** - * @param testProject the (folder)name of the project test case, in this folder a 'project' folder represents the test project in {@link #TEST_PROJECTS}. E.g. - * "basic". + * @param testProject the (folder)name of the project test case, in this folder a 'project' folder represents the test project in {@link #TEST_PROJECTS}. + * E.g. "basic". * @param projectPath the relative path inside the test project where to create the context. - * @param copyForMutation - {@code true} to create a copy of the project that can be modified by the test, {@code false} otherwise (only to save resources if - * you are 100% sure that your test never modifies anything in that project.) + * @param copyForMutation - {@code true} to create a copy of the project that can be modified by the test, {@code false} otherwise (only to save resources + * if you are 100% sure that your test never modifies anything in that project.) * @return the {@link IdeTestContext} pointing to that project. */ protected static IdeTestContext newContext(String testProject, String projectPath, boolean copyForMutation) { @@ -68,11 +68,11 @@ protected static IdeTestContext newContext(String testProject, String projectPat } /** - * @param testProject the (folder)name of the project test case, in this folder a 'project' folder represents the test project in {@link #TEST_PROJECTS}. E.g. - * "basic". + * @param testProject the (folder)name of the project test case, in this folder a 'project' folder represents the test project in {@link #TEST_PROJECTS}. + * E.g. "basic". * @param projectPath the relative path inside the test project where to create the context. - * @param copyForMutation - {@code true} to create a copy of the project that can be modified by the test, {@code false} otherwise (only to save resources if - * you are 100% sure that your test never modifies anything in that project.) + * @param copyForMutation - {@code true} to create a copy of the project that can be modified by the test, {@code false} otherwise (only to save resources + * if you are 100% sure that your test never modifies anything in that project.) * @param logLevel the {@link IdeLogLevel} used as threshold for logging. * @return the {@link IdeTestContext} pointing to that project. */ @@ -112,24 +112,6 @@ protected static IdeTestContext newContext(Path projectPath) { return new IdeTestContext(projectPath); } - /** - * @param projectPath the relative path inside the test project where to create the context. - * @param errors list of error messages. - * @param outs list of out messages. - * @param exitCode the exit code. - * @param isOnline boolean if it should be run in online mode. - * @return the {@link GitContextTestContext} pointing to that project. - */ - protected static GitContextTestContext newGitContext(Path projectPath, List errors, List outs, int exitCode, boolean isOnline) { - - GitContextTestContext context; - context = new GitContextTestContext(isOnline, projectPath); - context.setErrors(errors); - context.setOuts(outs); - context.setExitCode(exitCode); - return context; - } - protected static IdeTestContextAssertion assertThat(IdeTestContext context) { return new IdeTestContextAssertion(context); diff --git a/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeTestContext.java b/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeTestContext.java index 8d55b32ab..11addceb7 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeTestContext.java +++ b/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeTestContext.java @@ -4,19 +4,18 @@ import java.nio.file.Path; import java.util.HashMap; import java.util.Map; -import java.util.function.Function; import com.devonfw.tools.ide.common.SystemPath; import com.devonfw.tools.ide.environment.AbstractEnvironmentVariables; import com.devonfw.tools.ide.environment.EnvironmentVariables; import com.devonfw.tools.ide.environment.EnvironmentVariablesPropertiesFile; import com.devonfw.tools.ide.environment.EnvironmentVariablesType; -import com.devonfw.tools.ide.io.FileAccess; import com.devonfw.tools.ide.io.IdeProgressBar; import com.devonfw.tools.ide.io.IdeProgressBarTestImpl; -import com.devonfw.tools.ide.log.IdeLogLevel; -import com.devonfw.tools.ide.log.IdeSubLogger; +import com.devonfw.tools.ide.log.IdeLogger; +import com.devonfw.tools.ide.log.IdeLoggerImpl; import com.devonfw.tools.ide.os.SystemInfo; +import com.devonfw.tools.ide.process.ProcessContext; import com.devonfw.tools.ide.repo.DefaultToolRepository; import com.devonfw.tools.ide.repo.ToolRepository; import com.devonfw.tools.ide.variable.IdeVariables; @@ -26,7 +25,7 @@ */ public class AbstractIdeTestContext extends AbstractIdeContext { - private final String[] answers; + private String[] answers; private int answerIndex; @@ -34,24 +33,25 @@ public class AbstractIdeTestContext extends AbstractIdeContext { private SystemInfo systemInfo; - private FileAccess mockFileAccess; - private Path dummyUserHome; + private Boolean online; + + private ProcessContext mockContext; + /** * The constructor. * - * @param factory the {@link Function} to create {@link IdeSubLogger} per {@link IdeLogLevel}. + * @param logger the {@link IdeLogger}. * @param userDir the optional {@link Path} to current working directory. - * @param toolRepository @param toolRepository the {@link ToolRepository} of the context. If it is set to {@code null} {@link DefaultToolRepository} will be - * used. - * @param answers the automatic answers simulating a user in test. + * @param toolRepository @param toolRepository the {@link ToolRepository} of the context. If it is set to {@code null} {@link DefaultToolRepository} will + * be used. */ - public AbstractIdeTestContext(Function factory, Path userDir, - ToolRepository toolRepository, String... answers) { + public AbstractIdeTestContext(IdeLoggerImpl logger, Path userDir, + ToolRepository toolRepository) { - super(IdeLogLevel.TRACE, factory, userDir, toolRepository); - this.answers = answers; + super(logger, userDir, toolRepository); + this.answers = new String[0]; this.progressBarMap = new HashMap<>(); this.systemInfo = super.getSystemInfo(); } @@ -71,6 +71,11 @@ protected String readLine() { return this.answers[this.answerIndex++]; } + public void setAnswers(String... answers) { + this.answers = answers; + this.answerIndex = 0; + } + /** * @return Map of progress bars with task name and actual implementation. */ @@ -113,6 +118,40 @@ protected SystemPath computeSystemPath() { return new SystemPath(this, envPath); } + @Override + public boolean isOnline() { + + if (this.online != null) { + return this.online.booleanValue(); + } + return super.isOnline(); + } + + /** + * @param online the mocked {@link #isOnline()} result. + */ + public void setOnline(Boolean online) { + + this.online = online; + } + + @Override + public ProcessContext newProcess() { + + if (this.mockContext != null) { + return this.mockContext; + } + return super.newProcess(); + } + + /** + * @param mockContext the instance to mock {@link #newProcess()}. + */ + public void setProcessContext(ProcessContext mockContext) { + + this.mockContext = mockContext; + } + @Override public SystemInfo getSystemInfo() { @@ -128,14 +167,6 @@ public void setSystemInfo(SystemInfo systemInfo) { this.systemInfo = systemInfo; } - /** - * @param fileAccess the {@link FileAccess} to use for testing. - */ - public void setMockFileAccess(FileAccess fileAccess) { - - this.mockFileAccess = fileAccess; - } - /** * @param dummyUserHome mock path which will be used in {@link #getUserHome()} */ @@ -146,7 +177,7 @@ public void setUserHome(Path dummyUserHome) { /** * @return a dummy UserHome path to avoid global path access in a commandlet test. The defined {@link #dummyUserHome} will be returned if it is not - * {@code null}, else see implementation {@link #AbstractIdeContext}. + * {@code null}, else see implementation {@link #AbstractIdeContext}. */ @Override public Path getUserHome() { @@ -154,7 +185,6 @@ public Path getUserHome() { if (this.dummyUserHome != null) { return this.dummyUserHome; } - return super.getUserHome(); } } diff --git a/cli/src/test/java/com/devonfw/tools/ide/context/GitContextTest.java b/cli/src/test/java/com/devonfw/tools/ide/context/GitContextTest.java index f6cf6003b..b79c5624e 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/context/GitContextTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/context/GitContextTest.java @@ -5,9 +5,6 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -21,6 +18,18 @@ */ public class GitContextTest extends AbstractIdeContextTest { + private ProcessContextGitMock processContext; + + private IdeTestContext newGitContext(Path dir) { + + IdeTestContext context = newContext(dir); + context.setOnline(Boolean.TRUE); + this.processContext = new ProcessContextGitMock(dir); + context.setProcessContext(processContext); + context.setGitContext(new GitContextImpl(context)); + return context; + } + /** * Runs a git clone in offline mode and expects an exception to be thrown with a message. * @@ -31,19 +40,18 @@ public void testRunGitCloneInOfflineModeThrowsException(@TempDir Path tempDir) { // arrange String gitRepoUrl = "https://github.com/test"; - List errors = new ArrayList<>(); - List outs = new ArrayList<>(); - outs.add("test-remote"); - IdeContext context = newGitContext(tempDir, errors, outs, 0, false); - GitContext gitContext = new GitContextImpl(context); + IdeTestContext context = newGitContext(tempDir); + this.processContext.getOuts().add("test-remote"); + context.setOnline(Boolean.FALSE); + + //IdeContext context = newGitContext(tempDir, errors, outs, 0, false); // act CliException e1 = assertThrows(CliException.class, () -> { - gitContext.pullOrClone(gitRepoUrl, "", tempDir); + context.getGitContext().pullOrClone(gitRepoUrl, "", tempDir); }); // assert assertThat(e1).hasMessageContaining(gitRepoUrl).hasMessageContaining(tempDir.toString()) .hasMessageContaining("offline"); - } /** @@ -56,13 +64,10 @@ public void testRunGitClone(@TempDir Path tempDir) { // arrange String gitRepoUrl = "https://github.com/test"; - List errors = new ArrayList<>(); - List outs = new ArrayList<>(); - outs.add("test-remote"); - IdeContext context = newGitContext(tempDir, errors, outs, 0, true); - GitContext gitContext = new GitContextImpl(context); + IdeTestContext context = newGitContext(tempDir); + this.processContext.getOuts().add("test-remote"); // act - gitContext.pullOrClone(gitRepoUrl, tempDir); + context.getGitContext().pullOrClone(gitRepoUrl, tempDir); // assert assertThat(tempDir.resolve(".git").resolve("url")).hasContent(gitRepoUrl); } @@ -77,19 +82,15 @@ public void testRunGitPullWithoutForce(@TempDir Path tempDir) { // arrange String gitRepoUrl = "https://github.com/test"; - List errors = new ArrayList<>(); - List outs = new ArrayList<>(); - outs.add("test-remote"); - IdeContext context = newGitContext(tempDir, errors, outs, 0, true); - GitContext gitContext = new GitContextImpl(context); - Date currentDate = new Date(); + IdeTestContext context = newGitContext(tempDir); + this.processContext.getOuts().add("test-remote"); FileAccess fileAccess = new FileAccessImpl(context); Path gitFolderPath = tempDir.resolve(".git"); fileAccess.mkdirs(gitFolderPath); // act - gitContext.pullOrClone(gitRepoUrl, tempDir); + context.getGitContext().pullOrClone(gitRepoUrl, tempDir); // assert - assertThat(tempDir.resolve(".git").resolve("update")).hasContent(currentDate.toString()); + assertThat(tempDir.resolve(".git").resolve("update")).hasContent(this.processContext.getNow().toString()); } /** @@ -102,9 +103,7 @@ public void testRunGitPullWithForceStartsReset(@TempDir Path tempDir) { // arrange String gitRepoUrl = "https://github.com/test"; - List errors = new ArrayList<>(); - List outs = new ArrayList<>(); - outs.add("test-remote"); + Path gitFolderPath = tempDir.resolve(".git"); try { Files.createDirectory(gitFolderPath); @@ -123,10 +122,10 @@ public void testRunGitPullWithForceStartsReset(@TempDir Path tempDir) { } catch (IOException e) { throw new RuntimeException(e); } - IdeContext context = newGitContext(tempDir, errors, outs, 0, true); - GitContext gitContext = new GitContextImpl(context); + IdeTestContext context = newGitContext(tempDir); + this.processContext.getOuts().add("test-remote"); // act - gitContext.pullOrCloneAndResetIfNeeded(gitRepoUrl, tempDir, "master", "origin"); + context.getGitContext().pullOrCloneAndResetIfNeeded(gitRepoUrl, tempDir, "master", "origin"); // assert assertThat(modifiedFile).hasContent("original"); } @@ -141,12 +140,10 @@ public void testRunGitPullWithForceStartsCleanup(@TempDir Path tempDir) { // arrange String gitRepoUrl = "https://github.com/test"; - List errors = new ArrayList<>(); - List outs = new ArrayList<>(); - outs.add("test-remote"); - IdeContext context = newGitContext(tempDir, errors, outs, 0, true); - GitContext gitContext = new GitContextImpl(context); - FileAccess fileAccess = new FileAccessImpl(context); + IdeTestContext context = newGitContext(tempDir); + this.processContext.getOuts().add("test-remote"); + GitContext gitContext = context.getGitContext(); + FileAccess fileAccess = context.getFileAccess(); Path gitFolderPath = tempDir.resolve(".git"); fileAccess.mkdirs(gitFolderPath); fileAccess.mkdirs(tempDir.resolve("new-folder")); diff --git a/cli/src/test/java/com/devonfw/tools/ide/context/GitContextTestContext.java b/cli/src/test/java/com/devonfw/tools/ide/context/GitContextTestContext.java deleted file mode 100644 index 578f39e46..000000000 --- a/cli/src/test/java/com/devonfw/tools/ide/context/GitContextTestContext.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.devonfw.tools.ide.context; - -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; - -import com.devonfw.tools.ide.log.IdeLogLevel; -import com.devonfw.tools.ide.log.IdeTestLogger; -import com.devonfw.tools.ide.log.IdeTestLoggerFactory; -import com.devonfw.tools.ide.process.ProcessContext; - -/** - * Implementation of {@link IdeContext} for testing {@link GitContext}. - */ -public class GitContextTestContext extends AbstractIdeTestContext { - - private List errors; - - private List outs; - - private int exitCode; - - private static boolean testOnlineMode; - - /** - * The constructor. - * - * @param isOnline boolean if it should be run in online mode. - * @param userDir the optional {@link Path} to current working directory. - * @param answers the automatic answers simulating a user in test. - */ - public GitContextTestContext(boolean isOnline, Path userDir, String... answers) { - - super(new IdeTestLoggerFactory(), userDir, null, answers); - testOnlineMode = isOnline; - this.errors = new ArrayList<>(); - this.outs = new ArrayList<>(); - this.exitCode = 0; - } - - @Override - public boolean isOnline() { - - return testOnlineMode; - } - - @Override - public IdeTestLogger level(IdeLogLevel level) { - - return (IdeTestLogger) super.level(level); - } - - /** - * @return a dummy {@link GitContextTestContext}. - */ - public static GitContextTestContext of() { - - return new GitContextTestContext(testOnlineMode, Paths.get("/")); - } - - @Override - public ProcessContext newProcess() { - - return new GitContextProcessContextMock(this.errors, this.outs, this.exitCode, getCwd()); - } - - /** - * @param errors the {@link List} of errors (stderr lines) of the mocked git process. - */ - public void setErrors(List errors) { - - this.errors = errors; - } - - /** - * @param outs the {@link List} of outputs (stdout lines) of the mocked git process. - */ - public void setOuts(List outs) { - - this.outs = outs; - } - - /** - * @param exitCode the return code of the mocked git process. - */ - public void setExitCode(int exitCode) { - - this.exitCode = exitCode; - } - -} diff --git a/cli/src/test/java/com/devonfw/tools/ide/context/IdeSlf4jContext.java b/cli/src/test/java/com/devonfw/tools/ide/context/IdeSlf4jContext.java index f3e515d74..8151f86e9 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/context/IdeSlf4jContext.java +++ b/cli/src/test/java/com/devonfw/tools/ide/context/IdeSlf4jContext.java @@ -2,7 +2,9 @@ import java.nio.file.Path; -import com.devonfw.tools.ide.log.IdeSlf4jLogger; +import com.devonfw.tools.ide.log.IdeLogLevel; +import com.devonfw.tools.ide.log.IdeLoggerImpl; +import com.devonfw.tools.ide.log.IdeSubLoggerSlf4j; /** * Implementation of {@link IdeContext} for testing. @@ -13,11 +15,10 @@ public class IdeSlf4jContext extends AbstractIdeTestContext { * The constructor. * * @param userDir the optional {@link Path} to current working directory. - * @param answers the automatic answers simulating a user in test. */ - public IdeSlf4jContext(Path userDir, String... answers) { + public IdeSlf4jContext(Path userDir) { - super(level -> new IdeSlf4jLogger(level), userDir, null, answers); + super(new IdeLoggerImpl(IdeLogLevel.TRACE, level -> new IdeSubLoggerSlf4j(level)), userDir, null); } } diff --git a/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContext.java b/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContext.java index 1bc9b8742..888d5e7d3 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContext.java +++ b/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContext.java @@ -1,11 +1,9 @@ package com.devonfw.tools.ide.context; import java.nio.file.Path; -import java.util.LinkedList; -import java.util.List; import com.devonfw.tools.ide.log.IdeLogLevel; -import com.devonfw.tools.ide.log.IdeTestLoggerFactory; +import com.devonfw.tools.ide.log.IdeTestLogger; import com.devonfw.tools.ide.process.ProcessContext; import com.devonfw.tools.ide.repo.ToolRepository; @@ -14,58 +12,63 @@ */ public class IdeTestContext extends AbstractIdeTestContext { - private final IdeTestLoggerFactory loggerFactory; + private final IdeTestLogger logger; - private LinkedList inputValues; + private GitContext gitContext; /** * The constructor. * * @param userDir the optional {@link Path} to current working directory. - * @param answers the automatic answers simulating a user in test. */ - public IdeTestContext(Path userDir, String... answers) { + public IdeTestContext(Path userDir) { - this(userDir, null, answers); + this(userDir, null); } /** * The constructor. * * @param userDir the optional {@link Path} to current working directory. - * @param toolRepository the {@link ToolRepository} of the context. If it is set to {@code null} * {@link com.devonfw.tools.ide.repo.DefaultToolRepository} - * will be used. - * @param answers the automatic answers simulating a user in test. + * @param toolRepository the {@link ToolRepository} of the context. If it is set to {@code null} * + * {@link com.devonfw.tools.ide.repo.DefaultToolRepository} will be used. */ - public IdeTestContext(Path userDir, ToolRepository toolRepository, String... answers) { + public IdeTestContext(Path userDir, ToolRepository toolRepository) { - this(userDir, toolRepository, IdeLogLevel.TRACE, answers); + this(userDir, toolRepository, IdeLogLevel.TRACE); } /** * The constructor. * * @param userDir the optional {@link Path} to current working directory. - * @param toolRepository the {@link ToolRepository} of the context. If it is set to {@code null} * {@link com.devonfw.tools.ide.repo.DefaultToolRepository} - * will be used. + * @param toolRepository the {@link ToolRepository} of the context. If it is set to {@code null} * + * {@link com.devonfw.tools.ide.repo.DefaultToolRepository} will be used. * @param logLevel the {@link IdeLogLevel} used as threshold for logging. - * @param answers the automatic answers simulating a user in test. */ - public IdeTestContext(Path userDir, ToolRepository toolRepository, IdeLogLevel logLevel, String... answers) { + public IdeTestContext(Path userDir, ToolRepository toolRepository, IdeLogLevel logLevel) { - this(new IdeTestLoggerFactory(logLevel), userDir, toolRepository, answers); + this(new IdeTestLogger(logLevel), userDir, toolRepository); } - private IdeTestContext(IdeTestLoggerFactory loggerFactory, Path userDir, ToolRepository toolRepository, String... answers) { + private IdeTestContext(IdeTestLogger logger, Path userDir, ToolRepository toolRepository) { - super(loggerFactory, userDir, toolRepository, answers); - this.loggerFactory = loggerFactory; + super(logger, userDir, toolRepository); + this.logger = logger; + this.gitContext = new GitContextMock(); } @Override public GitContext getGitContext() { + return this.gitContext; + } - return new GitContextMock(); + /** + * @param gitContext the instance to mock {@link GitContext}. + */ + public void setGitContext(GitContext gitContext) { + + this.gitContext = gitContext; } @Override @@ -82,27 +85,18 @@ public static IdeTestContext of() { return new IdeTestContext(Path.of("/")); } - /** - * Set a mocked value to be returned by the {@link IdeContext#askForInput(String)} method - * - * @param values a {@link LinkedList} with the mocked input value - */ - public void setInputValues(List values) { - - this.inputValues = new LinkedList<>(values); - } - @Override public String askForInput(String message) { - return this.inputValues.isEmpty() ? null : this.inputValues.poll(); + return super.askForInput(message); + // return this.inputValues.isEmpty() ? null : this.inputValues.poll(); } /** - * @return the {@link IdeTestLoggerFactory}. + * @return the {@link IdeTestLogger}. */ - public IdeTestLoggerFactory getLoggerFactory() { + public IdeTestLogger getLogger() { - return loggerFactory; + return logger; } } diff --git a/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContextAssertion.java b/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContextAssertion.java index 635e8ee0b..af4457f5e 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContextAssertion.java +++ b/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContextAssertion.java @@ -26,7 +26,7 @@ public IdeTestContextAssertion(IdeTestContext context) { */ public IdeTestLoggerAssertion log(IdeLogLevel level) { - return new IdeTestLoggerAssertion(context.getLoggerFactory().getEntries(), level); + return new IdeTestLoggerAssertion(context.getLogger().getEntries(), level); } /** diff --git a/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContextMock.java b/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContextMock.java index 7393acc40..994a40a74 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContextMock.java +++ b/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContextMock.java @@ -16,12 +16,6 @@ private IdeTestContextMock() { super(Path.of("/")); } - @Override - public boolean isMock() { - - return true; - } - /** * @return the singleton mock instance of {@link com.devonfw.tools.ide.context.IdeContext}. Does NOT have {@link #getIdeHome() IDE_HOME}. */ diff --git a/cli/src/test/java/com/devonfw/tools/ide/context/GitContextProcessContextMock.java b/cli/src/test/java/com/devonfw/tools/ide/context/ProcessContextGitMock.java similarity index 78% rename from cli/src/test/java/com/devonfw/tools/ide/context/GitContextProcessContextMock.java rename to cli/src/test/java/com/devonfw/tools/ide/context/ProcessContextGitMock.java index 8c1e78ba5..d9deee317 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/context/GitContextProcessContextMock.java +++ b/cli/src/test/java/com/devonfw/tools/ide/context/ProcessContextGitMock.java @@ -4,8 +4,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import java.time.LocalDateTime; import java.util.ArrayList; -import java.util.Date; import java.util.List; import com.devonfw.tools.ide.process.ProcessContext; @@ -17,7 +17,7 @@ /** * Mocks the {@link ProcessContext}. */ -public class GitContextProcessContextMock implements ProcessContext { +public class ProcessContextGitMock implements ProcessContext { private final List arguments; @@ -25,23 +25,55 @@ public class GitContextProcessContextMock implements ProcessContext { private final List outs; + private final LocalDateTime now; + private int exitCode; private final Path directory; /** - * @param errors List of errors. - * @param outs List of out texts. - * @param exitCode the exit code. * @param directory the {@link Path} to the git repository. */ - public GitContextProcessContextMock(List errors, List outs, int exitCode, Path directory) { + public ProcessContextGitMock(Path directory) { this.arguments = new ArrayList<>(); - this.errors = errors; - this.outs = outs; - this.exitCode = exitCode; + this.errors = new ArrayList<>(); + this.outs = new ArrayList<>(); + this.exitCode = ProcessResult.SUCCESS; this.directory = directory; + this.now = LocalDateTime.now(); + } + + /** + * @return the mocked {@link ProcessResult#getExitCode() exit code}. + */ + public int getExitCode() { + + return this.exitCode; + } + + /** + * @param exitCode the {@link #getExitCode() exit code}. + */ + public void setExitCode(int exitCode) { + + this.exitCode = exitCode; + } + + /** + * @return the {@link List} of mocked error messages. + */ + public List getErrors() { + + return errors; + } + + /** + * @return the {@link List} of mocked out messages. + */ + public List getOuts() { + + return outs; } @Override @@ -69,6 +101,11 @@ public ProcessContext addArg(String arg) { return this; } + public LocalDateTime getNow() { + + return this.now; + } + @Override public ProcessContext withEnvVar(String key, String value) { @@ -126,8 +163,7 @@ public ProcessResult run(ProcessMode processMode) { try { Files.createDirectories(gitFolderPath); Path newFile = Files.createFile(gitFolderPath.resolve("update")); - Date currentDate = new Date(); - Files.writeString(newFile, currentDate.toString()); + Files.writeString(newFile, this.now.toString()); this.exitCode = 0; } catch (IOException e) { throw new RuntimeException(e); diff --git a/cli/src/test/java/com/devonfw/tools/ide/log/IdeLogEntry.java b/cli/src/test/java/com/devonfw/tools/ide/log/IdeLogEntry.java index fb495ca88..c2a840a00 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/log/IdeLogEntry.java +++ b/cli/src/test/java/com/devonfw/tools/ide/log/IdeLogEntry.java @@ -1,7 +1,7 @@ package com.devonfw.tools.ide.log; /** - * Single entry that was logged by {@link IdeTestLogger}. + * Single entry that was logged by {@link IdeSubLoggerTest}. * * @param level the {@link IdeLogLevel}. * @param message the message that has been logged. diff --git a/cli/src/test/java/com/devonfw/tools/ide/log/IdeSlf4jRootLogger.java b/cli/src/test/java/com/devonfw/tools/ide/log/IdeSlf4jRootLogger.java index 845817c27..20dfe3609 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/log/IdeSlf4jRootLogger.java +++ b/cli/src/test/java/com/devonfw/tools/ide/log/IdeSlf4jRootLogger.java @@ -20,7 +20,7 @@ public IdeSlf4jRootLogger() { super(); this.loggers = new HashMap<>(); for (IdeLogLevel level : IdeLogLevel.values()) { - this.loggers.put(level, new IdeSlf4jLogger(level)); + this.loggers.put(level, new IdeSubLoggerSlf4j(level)); } } diff --git a/cli/src/test/java/com/devonfw/tools/ide/log/IdeSlf4jLogger.java b/cli/src/test/java/com/devonfw/tools/ide/log/IdeSubLoggerSlf4j.java similarity index 93% rename from cli/src/test/java/com/devonfw/tools/ide/log/IdeSlf4jLogger.java rename to cli/src/test/java/com/devonfw/tools/ide/log/IdeSubLoggerSlf4j.java index a2ff8c937..671d59cc2 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/log/IdeSlf4jLogger.java +++ b/cli/src/test/java/com/devonfw/tools/ide/log/IdeSubLoggerSlf4j.java @@ -8,9 +8,9 @@ /** * Implementation of {@link IdeSubLogger} for testing that delegates to slf4j. */ -public class IdeSlf4jLogger extends AbstractIdeSubLogger { +public class IdeSubLoggerSlf4j extends AbstractIdeSubLogger { - private static final Logger LOG = LoggerFactory.getLogger(IdeSlf4jLogger.class); + private static final Logger LOG = LoggerFactory.getLogger(IdeSubLoggerSlf4j.class); private final Level logLevel; @@ -19,7 +19,7 @@ public class IdeSlf4jLogger extends AbstractIdeSubLogger { * * @param level the {@link #getLevel() log-level}. */ - public IdeSlf4jLogger(IdeLogLevel level) { + public IdeSubLoggerSlf4j(IdeLogLevel level) { super(level); this.logLevel = switch (level) { diff --git a/cli/src/test/java/com/devonfw/tools/ide/log/IdeSubLoggerTest.java b/cli/src/test/java/com/devonfw/tools/ide/log/IdeSubLoggerTest.java new file mode 100644 index 000000000..0b7fafa06 --- /dev/null +++ b/cli/src/test/java/com/devonfw/tools/ide/log/IdeSubLoggerTest.java @@ -0,0 +1,45 @@ +package com.devonfw.tools.ide.log; + +import java.util.List; + +/** + * Implementation of {@link IdeSubLogger} for testing that collects all messages and allows to check if an expected message was logged. + */ +public class IdeSubLoggerTest extends IdeSubLoggerSlf4j { + + private final List entries; + + /** + * The constructor. + * + * @param level the {@link #getLevel() log-level}. + */ + public IdeSubLoggerTest(IdeLogLevel level, List entries) { + + super(level); + this.entries = entries; + } + + @Override + public String log(Throwable error, String message, Object... args) { + + String result = super.log(error, message, args); + this.entries.add(new IdeLogEntry(level, result)); + return result; + } + + /** + * @return the {@link List} of {@link IdeLogEntry} that have been logged for test assertions. + */ + public List getEntries() { + + return this.entries; + } + + @Override + public boolean isEnabled() { + + return true; + } + +} diff --git a/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestLogger.java b/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestLogger.java index 581df8d34..8480bf556 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestLogger.java +++ b/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestLogger.java @@ -1,31 +1,29 @@ package com.devonfw.tools.ide.log; +import java.util.ArrayList; import java.util.List; /** - * Implementation of {@link IdeSubLogger} for testing that collects all messages and allows to check if an expected message was logged. + * Extends {@link IdeLoggerImpl} for testing. */ -public class IdeTestLogger extends IdeSlf4jLogger { +public class IdeTestLogger extends IdeLoggerImpl { private final List entries; - /** - * The constructor. - * - * @param level the {@link #getLevel() log-level}. - */ - public IdeTestLogger(IdeLogLevel level, List entries) { + public IdeTestLogger() { - super(level); - this.entries = entries; + this(IdeLogLevel.DEBUG); } - @Override - public String log(Throwable error, String message, Object... args) { + public IdeTestLogger(IdeLogLevel minLogLevel) { - String result = super.log(error, message, args); - this.entries.add(new IdeLogEntry(level, result)); - return result; + this(new ArrayList<>(), minLogLevel); + } + + private IdeTestLogger(List entries, IdeLogLevel minLogLevel) { + + super(minLogLevel, level -> new IdeSubLoggerTest(level, entries)); + this.entries = entries; } /** @@ -35,11 +33,4 @@ public List getEntries() { return this.entries; } - - @Override - public boolean isEnabled() { - - return true; - } - } diff --git a/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestLoggerFactory.java b/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestLoggerFactory.java deleted file mode 100644 index 02589c4a5..000000000 --- a/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestLoggerFactory.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.devonfw.tools.ide.log; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -/** - * Factory for {@link IdeTestLogger}. - */ -public class IdeTestLoggerFactory implements Function { - - private final IdeLogLevel logLevel; - - private final List entries; - - /** - * The constructor. - */ - public IdeTestLoggerFactory() { - this(IdeLogLevel.TRACE); - } - - /** - * The constructor. - * - * @param logLevel the {@link IdeLogLevel} used as threshold for logging. - */ - public IdeTestLoggerFactory(IdeLogLevel logLevel) { - super(); - this.logLevel = logLevel; - this.entries = new ArrayList<>(512); - } - - @Override - public IdeSubLogger apply(IdeLogLevel ideLogLevel) { - - if (ideLogLevel.ordinal() < this.logLevel.ordinal()) { - return new IdeSubLoggerNone(ideLogLevel); - } - return new IdeTestLogger(ideLogLevel, this.entries); - } - - /** - * @return the {@link List} of {@link IdeLogEntry} that have been logged for test assertions. - */ - public List getEntries() { - - return this.entries; - } - -} diff --git a/cli/src/test/java/com/devonfw/tools/ide/tool/mvn/MvnTest.java b/cli/src/test/java/com/devonfw/tools/ide/tool/mvn/MvnTest.java index 3591f11c1..cb8c802dc 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/tool/mvn/MvnTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/tool/mvn/MvnTest.java @@ -35,7 +35,7 @@ public void testMvnInstall() throws IOException { // arrange IdeTestContext context = newContext(PROJECT_MVN); - context.setInputValues(List.of("testLogin", "testPassword")); + context.setAnswers("testLogin", "testPassword"); InstallCommandlet install = context.getCommandletManager().getCommandlet(InstallCommandlet.class); install.tool.setValueAsString("mvn", context); @@ -55,7 +55,7 @@ public void testMvnInstall() throws IOException { public void testMvnRun() throws IOException { // arrange IdeTestContext context = newContext(PROJECT_MVN); - context.setInputValues(List.of("testLogin", "testPassword")); + context.setAnswers("testLogin", "testPassword"); InstallCommandlet install = context.getCommandletManager().getCommandlet(InstallCommandlet.class); install.tool.setValueAsString("mvn", context); Mvn commandlet = (Mvn) install.tool.getValue();