Skip to content

Commit 14e887f

Browse files
committed
test(common): Add testing classes previously taken from core package
1 parent d3a1d57 commit 14e887f

File tree

7 files changed

+597
-0
lines changed

7 files changed

+597
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
package com.ibm.watson.common;
22

33
public interface WatsonHttpHeaders {
4+
/** Allow Watson to collect the payload. */
5+
String X_WATSON_LEARNING_OPT_OUT = "X-Watson-Learning-Opt-Out";
6+
47
/** Header containing analytics info. */
58
String X_IBMCLOUD_SDK_ANALYTICS = "X-IBMCloud-SDK-Analytics";
9+
10+
/** Mark API calls as tests. */
11+
String X_WATSON_TEST = "X-Watson-Test";
612
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package com.ibm.watson.common;
2+
3+
import com.ibm.cloud.sdk.core.service.exception.TooManyRequestsException;
4+
import com.ibm.cloud.sdk.core.service.exception.UnauthorizedException;
5+
import org.junit.Ignore;
6+
import org.junit.internal.AssumptionViolatedException;
7+
import org.junit.internal.runners.model.EachTestNotifier;
8+
import org.junit.runner.Description;
9+
import org.junit.runner.notification.RunNotifier;
10+
import org.junit.runner.notification.StoppedByUserException;
11+
import org.junit.runners.BlockJUnit4ClassRunner;
12+
import org.junit.runners.model.FrameworkMethod;
13+
import org.junit.runners.model.InitializationError;
14+
import org.junit.runners.model.Statement;
15+
16+
import java.util.logging.Level;
17+
import java.util.logging.Logger;
18+
19+
/**
20+
* Junit Runner that retry tests. Useful when tests could fail due to network issues.
21+
*/
22+
public class RetryRunner extends BlockJUnit4ClassRunner {
23+
private static final Logger LOG = Logger.getLogger(RetryRunner.class.getName());
24+
25+
private static final int RETRY_COUNT = 3;
26+
27+
/**
28+
* Delay factor when tests are failing.
29+
*/
30+
private static final int RETRY_DELAY_FACTOR = 2000;
31+
32+
/**
33+
* Instantiates a new retry runner.
34+
*
35+
* @param clazz the class
36+
* @throws InitializationError the initialization error
37+
*/
38+
public RetryRunner(Class<?> clazz) throws InitializationError {
39+
super(clazz);
40+
}
41+
42+
/*
43+
* (non-Javadoc)
44+
*
45+
* @see org.junit.runners.ParentRunner#run(org.junit.runner.notification.RunNotifier)
46+
*/
47+
@Override
48+
public void run(final RunNotifier notifier) {
49+
EachTestNotifier testNotifier = new EachTestNotifier(notifier, getDescription());
50+
Statement statement = classBlock(notifier);
51+
try {
52+
statement.evaluate();
53+
} catch (AssumptionViolatedException ave) {
54+
testNotifier.fireTestIgnored();
55+
} catch (StoppedByUserException sbue) {
56+
throw sbue;
57+
} catch (Throwable t) {
58+
LOG.warning("Retry class: " + getDescription().getDisplayName());
59+
retry(testNotifier, statement, t, getDescription());
60+
}
61+
}
62+
63+
/*
64+
* (non-Javadoc)
65+
*
66+
* @see org.junit.runners.BlockJUnit4ClassRunner#runChild(org.junit.runners.model.FrameworkMethod,
67+
* org.junit.runner.notification.RunNotifier)
68+
*/
69+
@Override
70+
protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
71+
Description description = describeChild(method);
72+
if (method.getAnnotation(Ignore.class) != null) {
73+
notifier.fireTestIgnored(description);
74+
} else {
75+
runTest(methodBlock(method), description, notifier);
76+
}
77+
}
78+
79+
private void runTest(Statement statement, Description description, RunNotifier notifier) {
80+
EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);
81+
eachNotifier.fireTestStarted();
82+
try {
83+
statement.evaluate();
84+
} catch (AssumptionViolatedException e) {
85+
eachNotifier.addFailedAssumption(e);
86+
} catch (Throwable e) {
87+
LOG.warning("Retry test: " + description.getDisplayName());
88+
retry(eachNotifier, statement, e, description);
89+
} finally {
90+
eachNotifier.fireTestFinished();
91+
}
92+
}
93+
94+
private void retry(EachTestNotifier notifier, Statement statement, Throwable currentThrowable, Description info) {
95+
int failedAttempts = 0;
96+
Throwable caughtThrowable = currentThrowable;
97+
while (RETRY_COUNT > failedAttempts) {
98+
try {
99+
LOG.warning("Retry attempt " + (failedAttempts + 1) + " for " + info.getDisplayName());
100+
statement.evaluate();
101+
return;
102+
} catch (UnauthorizedException ue) {
103+
LOG.log(Level.WARNING, "Do not retry test failures due to UnauthorizedException", ue);
104+
failedAttempts = RETRY_COUNT;
105+
} catch (TooManyRequestsException e) {
106+
LOG.log(Level.WARNING, "Ignoring test failures due to rate limitation", e);
107+
return;
108+
} catch (Throwable t) {
109+
failedAttempts++;
110+
try {
111+
// GERMAN: Delay test failures to prevent network/service hiccups
112+
Thread.sleep(RETRY_DELAY_FACTOR * failedAttempts);
113+
} catch (InterruptedException e) {
114+
LOG.log(Level.WARNING, "The thread used by JUnit was interrupted", e);
115+
}
116+
caughtThrowable = t;
117+
}
118+
}
119+
notifier.addFailure(caughtThrowable);
120+
}
121+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package com.ibm.watson.common;
2+
3+
import junit.framework.AssertionFailedError;
4+
import org.junit.Ignore;
5+
6+
import java.beans.BeanInfo;
7+
import java.beans.Introspector;
8+
import java.beans.PropertyDescriptor;
9+
import java.io.IOException;
10+
import java.io.InputStream;
11+
import java.lang.reflect.InvocationTargetException;
12+
import java.lang.reflect.Method;
13+
import java.util.Collection;
14+
15+
/**
16+
* The Class TestUtils.
17+
*/
18+
@Ignore
19+
public final class TestUtils {
20+
/**
21+
* Private constructor.
22+
*/
23+
private TestUtils() { }
24+
25+
/**
26+
* Test that a collection is not null or empty.
27+
*
28+
* @param objs the collection of objects
29+
* @throws Exception any exception
30+
*/
31+
@SuppressWarnings("rawtypes")
32+
public static void assertIsEmpty(final Collection objs) throws Exception {
33+
if ((objs != null) && !objs.isEmpty()) {
34+
throw new AssertionFailedError("Collection is empty");
35+
}
36+
}
37+
38+
/**
39+
* Test that collection iteration does not generate exceptions.
40+
*
41+
* @param objs the collection of objects
42+
* @throws Exception any exception
43+
*/
44+
@SuppressWarnings("rawtypes")
45+
public static void assertNoExceptionsOnCollectionIteration(final Collection objs) throws Exception {
46+
for (final Object obj : objs) {
47+
assertNoExceptionsOnGetters(obj);
48+
}
49+
}
50+
51+
/**
52+
* Test access to the properties of an object through its accessors.
53+
*
54+
* @param obj the object to test
55+
* @throws Exception any exception
56+
*/
57+
public static void assertNoExceptionsOnGetters(final Object obj) throws Exception {
58+
59+
final Class<?> clazz = obj.getClass();
60+
final BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
61+
final PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
62+
63+
for (final PropertyDescriptor propertyDescriptor : propertyDescriptors) {
64+
final Method readMethod = propertyDescriptor.getReadMethod();
65+
66+
if (readMethod != null) {
67+
try {
68+
readMethod.invoke(obj, new Object[] { });
69+
} catch (final InvocationTargetException e) {
70+
final StringBuffer msg = new StringBuffer();
71+
msg.append("Failure: " + propertyDescriptor.getName());
72+
msg.append(" Exception: " + e.getCause().getClass());
73+
msg.append(" Msg: " + e.getCause().getMessage());
74+
throw new AssertionFailedError(msg.toString());
75+
}
76+
}
77+
}
78+
79+
}
80+
81+
/**
82+
* Test that a collection is not null or empty.
83+
*
84+
* @param objs the collection of objects
85+
* @throws Exception any exception
86+
*/
87+
@SuppressWarnings({ "rawtypes" })
88+
public static void assertNotEmpty(final Collection objs) throws Exception {
89+
if (objs == null) {
90+
throw new AssertionFailedError("Collection is null");
91+
}
92+
if (objs.isEmpty()) {
93+
throw new AssertionFailedError("Collection is empty");
94+
}
95+
}
96+
97+
/**
98+
* Checks if both InputStreams have the same content and length. The streams are closed after reading.
99+
*
100+
* @param s1 the s1
101+
* @param s2 the s2
102+
* @return true, if the InputStreams are equal
103+
* @throws IOException Signals that an I/O exception has occurred.
104+
*/
105+
public static boolean streamContentEquals(InputStream s1, InputStream s2) throws IOException {
106+
try {
107+
int b1;
108+
int b2;
109+
110+
do { // read while both stream contents are equal and s1 still has more bytes
111+
b1 = s1.read();
112+
b2 = s2.read();
113+
} while ((b1 == b2) && (b1 != -1));
114+
115+
// this is true iff both streams are equally long and have the same content
116+
return b1 == b2;
117+
} finally {
118+
try {
119+
s1.close();
120+
s2.close();
121+
} catch (Exception e) {
122+
// Exceptions during closing seem to be ok!
123+
}
124+
}
125+
}
126+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.ibm.watson.common;
2+
3+
import java.util.concurrent.TimeUnit;
4+
5+
/**
6+
* Wait for a certain condition to be true or for a timeout to expire.
7+
*
8+
*/
9+
10+
public class WaitFor {
11+
12+
private WaitFor() {
13+
14+
}
15+
16+
/**
17+
* Static method used to wait for a specific condition to be satisfied.
18+
*
19+
* @param condition The condition to check
20+
* @param time The maximum time to wait for the condition to become true
21+
* @param unit The time unit of the {@code time} argument
22+
* @param sleepMs The time to wait between checks
23+
*
24+
* @return true if the condition was true before the timeout, false if it wasn't.
25+
*/
26+
public static boolean waitFor(Condition condition, long time, TimeUnit unit, long sleepMs) {
27+
long waitMs = unit.toMillis(time);
28+
long startMs = System.currentTimeMillis();
29+
while (System.currentTimeMillis() - startMs < waitMs) {
30+
if (condition.isSatisfied()) {
31+
return true;
32+
}
33+
try {
34+
Thread.sleep(sleepMs);
35+
} catch (InterruptedException e) {
36+
throw new RuntimeException("WaitFor aborted", e);
37+
}
38+
}
39+
return false;
40+
}
41+
42+
/**
43+
* The Interface Condition.
44+
*/
45+
public interface Condition {
46+
/**
47+
* @return true/false indicating whether or not the condition has been met.
48+
*/
49+
boolean isSatisfied();
50+
}
51+
}

0 commit comments

Comments
 (0)