Skip to content

Commit

Permalink
Added some classes from units4j to prepare archiving that project
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-schnell committed Feb 11, 2024
1 parent 268c554 commit a241a52
Show file tree
Hide file tree
Showing 6 changed files with 375 additions and 0 deletions.
118 changes: 118 additions & 0 deletions src/main/java/org/fuin/utils4j/MultipleCommands.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/**
* Copyright (C) 2015 Michael Schnell. All rights reserved.
* http://www.fuin.org/
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option) any
* later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see http://www.gnu.org/licenses/.
*/
package org.fuin.utils4j;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* Combines multiple test commands into one.
*
* @param <CONTEXT>
* Type of the test context.
*/
public final class MultipleCommands<CONTEXT> implements TestCommand<CONTEXT> {

private final List<TestCommand<CONTEXT>> commands;

/**
* Default constructor.
*/
public MultipleCommands() {
super();
this.commands = new ArrayList<>();
}

/**
* Constructor with command array.
*
* @param commands
* One or more commands to execute. Not {@literal null}.
*/
@SafeVarargs
public MultipleCommands(final TestCommand<CONTEXT>... commands) {
this(Arrays.asList(commands));
}

/**
* Constructor with command list.
*
* @param commands
* List of commands to execute. Not {@literal null}.
*/
public MultipleCommands(final List<? extends TestCommand<CONTEXT>> commands) {
super();
Utils4J.checkNotNull("commands", commands);
this.commands = new ArrayList<>(commands);
}

/**
* Adds a new command.
*
* @param command
* Command to add. Not {@literal null}.
*/
public void add(final TestCommand<CONTEXT> command) {
this.commands.add(command);
}

@Override
public void init(final CONTEXT context) {
for (final TestCommand<CONTEXT> command : commands) {
command.init(context);
}
}

@Override
public final void execute() {
for (final TestCommand<CONTEXT> command : commands) {
command.execute();
}
}

@Override
public final boolean isSuccessful() {
for (final TestCommand<CONTEXT> command : commands) {
if (!command.isSuccessful()) {
return false;
}
}
return true;
}

@Override
public final String getFailureDescription() {
final StringBuilder sb = new StringBuilder();
for (final TestCommand<CONTEXT> command : commands) {
if (!command.isSuccessful()) {
sb.append(command.getFailureDescription());
sb.append("\n");
}
}
return sb.toString();
}

@Override
public final void verify() {
if (!isSuccessful()) {
throw new RuntimeException("There was at least one failure:\n" + getFailureDescription());
}
}

}
61 changes: 61 additions & 0 deletions src/main/java/org/fuin/utils4j/TestCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* Copyright (C) 2015 Michael Schnell. All rights reserved.
* http://www.fuin.org/
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option) any
* later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see http://www.gnu.org/licenses/.
*/
package org.fuin.utils4j;

/**
* A command used in a test scenario.
*
* @param <CONTEXT>
* Type of the context.
*/
public interface TestCommand<CONTEXT> {

/**
* Initializes the command before executing it.
*
* @param context
* Context with specific information that may be used by the command. Not {@literal null}.
*/
public void init(CONTEXT context);

/**
* Executes the command. Exceptions will be catched used for creating a nice failure description. They are also logged.
*/
public void execute();

/**
* Returns if the command execution was successful. If this method is called before {@link #execute()} was executed, an illegal state
* exception will be thrown.
*
* @return TRUE if it was successful, else FALSE if it was a failure.
*/
public boolean isSuccessful();

/**
* Returns a description of the failure condition.
*
* @return Expected and current result.
*/
public String getFailureDescription();

/**
* Verifies that the command was successful and throws a runtime exception otherwise.
*/
public void verify();

}
42 changes: 42 additions & 0 deletions src/main/java/org/fuin/utils4j/TestOmitted.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Copyright (C) 2015 Michael Schnell. All rights reserved.
* http://www.fuin.org/
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option) any
* later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see http://www.gnu.org/licenses/.
*/
package org.fuin.utils4j;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* States that the annotated test class contains no tests by intention.
* This avoids test failures when test coverage checks are done.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestOmitted {

/**
* Short description why the test class was not implemented.
*
* @return Explanation why the test was skipped
*/
String value();

}
20 changes: 20 additions & 0 deletions src/main/java/org/fuin/utils4j/Utils4J.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
Expand Down Expand Up @@ -1638,5 +1639,24 @@ public static Class<?> loadClass(String name) {
}
}

/**
* Sets a private field in an object by using reflection.
*
* @param obj
* Object with the attribute to set.
* @param name
* Name of the attribute to set.
* @param value
* Value to set for the attribute.
*/
public static void setPrivateField(final Object obj, final String name, final Object value) {
try {
final Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
} catch (final Exception ex) {
throw new RuntimeException("Couldn't set field '" + name + "' in class '" + obj.getClass() + "'", ex);
}
}

}
106 changes: 106 additions & 0 deletions src/test/java/org/fuin/utils4j/MultipleCommandsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/**
* Copyright (C) 2015 Michael Schnell. All rights reserved.
* http://www.fuin.org/
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option) any
* later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see http://www.gnu.org/licenses/.
*/
package org.fuin.utils4j;

import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

//CHECKSTYLE:OFF Test code
public class MultipleCommandsTest {

@Test
public void testCreate() {

final MyCmd cmd1 = new MyCmd(true, null);
final MultipleCommands<String> testee1 = new MultipleCommands<>(cmd1);
testee1.init("Hello1");
testee1.execute();

assertThat(testee1.getFailureDescription()).isEmpty();
assertThat(testee1.isSuccessful()).isTrue();
assertThat(cmd1.getContext()).isEqualTo("Hello1");
assertThat(cmd1.isExecuted()).isTrue();;

final MyCmd cmd2 = new MyCmd(false, "Oops");
final MultipleCommands<String> testee2 = new MultipleCommands<>(cmd1, cmd2);
testee2.init("Hello2");
testee2.execute();

assertThat(testee2.isSuccessful()).isFalse();
assertThat(testee2.getFailureDescription()).isEqualTo("Oops\n");
assertThat(cmd1.getContext()).isEqualTo("Hello2");
assertThat(cmd1.isExecuted()).isTrue();;
assertThat(cmd2.getContext()).isEqualTo("Hello2");
assertThat(cmd2.isExecuted()).isTrue();;

}

public static final class MyCmd implements TestCommand<String> {

private String context;

private boolean executed;

private boolean successful;

private String failureDescription;

public MyCmd(boolean successful, String failureDescription) {
super();
this.successful = successful;
this.failureDescription = failureDescription;
}

@Override
public void init(String context) {
this.context = context;
}

@Override
public void execute() {
executed = true;
}

@Override
public boolean isSuccessful() {
return successful;
}

@Override
public String getFailureDescription() {
return failureDescription;
}

public String getContext() {
return context;
}

public boolean isExecuted() {
return executed;
}

@Override
public void verify() {
// DO nothing
}

}

}
// CHECKSTYLE:ON
28 changes: 28 additions & 0 deletions src/test/java/org/fuin/utils4j/Utils4JTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,34 @@ public final void loadClassFailure() {
.hasMessageContaining("Failed to load class");
}

@Test
public final void testSetPrivateField() {

// PREPARE
final MyTestClass original = new MyTestClass("Test");
final String name = "Changed";

// TEST
Utils4J.setPrivateField(original, "name", name);

// VERIFY
assertThat(original.getName()).isEqualTo(name);

}

private static class MyTestClass {

private String name;

public MyTestClass(String name) {
this.name = name;
}

public String getName() {
return name;
}
}


}
// CHECKSTYLE:ON

0 comments on commit a241a52

Please sign in to comment.