Skip to content

Commit b3f9a0c

Browse files
committed
Prepare for more unit tests
1 parent 6575973 commit b3f9a0c

File tree

7 files changed

+328
-25
lines changed

7 files changed

+328
-25
lines changed

operator/src/test/java/oracle/kubernetes/TestUtils.java

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,25 @@
33

44
package oracle.kubernetes;
55

6-
import com.meterware.simplestub.Memento;
7-
import oracle.kubernetes.operator.logging.LoggingFactory;
8-
import org.apache.commons.exec.CommandLine;
9-
import org.apache.commons.exec.DefaultExecutor;
10-
116
import java.io.ByteArrayOutputStream;
127
import java.io.IOException;
138
import java.io.PrintStream;
149
import java.util.ArrayList;
1510
import java.util.List;
1611
import java.util.logging.ConsoleHandler;
1712
import java.util.logging.Handler;
13+
import java.util.logging.LogRecord;
1814
import java.util.logging.Logger;
1915

16+
import com.meterware.simplestub.Memento;
17+
18+
import oracle.kubernetes.operator.logging.LoggingFactory;
19+
20+
import org.apache.commons.exec.CommandLine;
21+
import org.apache.commons.exec.DefaultExecutor;
22+
23+
import static com.meterware.simplestub.Stub.createStub;
24+
2025
public class TestUtils {
2126
private static Boolean kubernetesStatus;
2227

@@ -57,7 +62,7 @@ public static boolean isLinux() {
5762
*
5863
* @return a collection of the removed handlers
5964
*/
60-
public static Memento silenceOperatorLogger() {
65+
public static ExceptionFilteringMemento silenceOperatorLogger() {
6166
Logger logger = LoggingFactory.getLogger("Operator", "Operator").getUnderlyingLogger();
6267
List<Handler> savedHandlers = new ArrayList<>();
6368
for (Handler handler : logger.getHandlers()) {
@@ -69,7 +74,33 @@ public static Memento silenceOperatorLogger() {
6974
for (Handler handler : savedHandlers)
7075
logger.removeHandler(handler);
7176

72-
return new ConsoleHandlerMemento(logger, savedHandlers);
77+
TestLogHandler testHandler = createStub(TestLogHandler.class);
78+
logger.addHandler(testHandler);
79+
80+
return new ConsoleHandlerMemento(logger, testHandler, savedHandlers);
81+
}
82+
83+
abstract static class TestLogHandler extends Handler {
84+
private Throwable throwable;
85+
private List<Throwable> ignoredExceptions = new ArrayList<>();
86+
87+
@Override
88+
public void publish(LogRecord record) {
89+
if (record.getThrown() != null && !ignoredExceptions.contains(record.getThrown()))
90+
throwable = record.getThrown();
91+
}
92+
93+
void throwLoggedThrowable() {
94+
if (throwable == null) return;
95+
96+
if (throwable instanceof Error) throw (Error) throwable;
97+
if (throwable instanceof RuntimeException) throw (RuntimeException) throwable;
98+
throw new RuntimeException(throwable);
99+
}
100+
101+
void ignoreLoggedException(Throwable t) {
102+
ignoredExceptions.add(t);
103+
}
73104
}
74105

75106
/**
@@ -102,18 +133,34 @@ public static void restoreConsoleHandlers(Logger logger, List<Handler> savedHand
102133
}
103134
}
104135

105-
private static class ConsoleHandlerMemento implements Memento {
136+
public interface ExceptionFilteringMemento extends Memento {
137+
ExceptionFilteringMemento ignoringLoggedExceptions(Throwable... throwables);
138+
}
139+
140+
private static class ConsoleHandlerMemento implements ExceptionFilteringMemento {
106141
private Logger logger;
142+
private TestLogHandler testHandler;
107143
private List<Handler> savedHandlers;
108144

109-
ConsoleHandlerMemento(Logger logger, List<Handler> savedHandlers) {
145+
ConsoleHandlerMemento(Logger logger, TestLogHandler testHandler, List<Handler> savedHandlers) {
110146
this.logger = logger;
147+
this.testHandler = testHandler;
111148
this.savedHandlers = savedHandlers;
112149
}
113150

151+
@Override
152+
public ExceptionFilteringMemento ignoringLoggedExceptions(Throwable... throwables) {
153+
for (Throwable throwable : throwables)
154+
testHandler.ignoreLoggedException(throwable);
155+
return this;
156+
}
157+
114158
@Override
115159
public void revert() {
160+
logger.removeHandler(testHandler);
116161
restoreConsoleHandlers(logger, savedHandlers);
162+
163+
testHandler.throwLoggedThrowable();
117164
}
118165

119166
@Override

operator/src/test/java/oracle/kubernetes/operator/WatcherTestBase.java

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@
33

44
package oracle.kubernetes.operator;
55

6+
import java.util.ArrayList;
7+
import java.util.List;
8+
import java.util.concurrent.atomic.AtomicBoolean;
9+
10+
import com.meterware.simplestub.Memento;
11+
612
import io.kubernetes.client.models.V1ObjectMeta;
713
import io.kubernetes.client.util.Watch;
814
import oracle.kubernetes.TestUtils;
915
import oracle.kubernetes.operator.builders.StubWatchFactory;
1016
import oracle.kubernetes.operator.builders.WatchEvent;
1117

12-
import com.meterware.simplestub.Memento;
13-
14-
import java.util.ArrayList;
15-
import java.util.List;
16-
import java.util.concurrent.atomic.AtomicBoolean;
17-
1818
import org.junit.After;
1919
import org.junit.Before;
2020
import org.junit.Test;
@@ -34,6 +34,7 @@ public abstract class WatcherTestBase implements StubWatchFactory.AllWatchesClos
3434
private static final int NEXT_RESOURCE_VERSION = 123456;
3535
private static final int INITIAL_RESOURCE_VERSION = 123;
3636
private static final String NAMESPACE = "testspace";
37+
private final RuntimeException hasNextException = new RuntimeException(Watcher.HAS_NEXT_EXCEPTION_MESSAGE);
3738

3839
private List<Memento> mementos = new ArrayList<>();
3940
private List<Watch.Response<?>> callBacks = new ArrayList<>();
@@ -57,7 +58,7 @@ void recordCallBack(Watch.Response<?> response) {
5758

5859
@Before
5960
public void setUp() throws Exception {
60-
mementos.add(TestUtils.silenceOperatorLogger());
61+
mementos.add(TestUtils.silenceOperatorLogger().ignoringLoggedExceptions(hasNextException));
6162
mementos.add(StubWatchFactory.install());
6263
StubWatchFactory.setListener(this);
6364
}
@@ -107,7 +108,7 @@ private Watch.Response<?> createHttpGoneErrorResponse(int nextResourceVersion) {
107108
@Test
108109
public void receivedEvents_areSentToListeners() throws Exception {
109110
Object object = createObjectWithMetaData();
110-
StubWatchFactory.addCallResponses((Watch.Response) createAddResponse(object), (Watch.Response) createModifyResponse(object));
111+
StubWatchFactory.addCallResponses(createAddResponse(object), (Watch.Response) createModifyResponse(object));
111112

112113
createAndRunWatcher(NAMESPACE, stopping, INITIAL_RESOURCE_VERSION);
113114

@@ -158,14 +159,15 @@ public void afterDelete_nextRequestSendsIncrementedResourceVersion() throws Exce
158159
@SuppressWarnings("unchecked")
159160
@Test
160161
public void afterExceptionDuringNext_closeWatchAndTryAgain() throws Exception {
161-
StubWatchFactory.throwExceptionOnNext(new RuntimeException(Watcher.HAS_NEXT_EXCEPTION_MESSAGE));
162+
StubWatchFactory.throwExceptionOnNext(hasNextException);
162163
StubWatchFactory.addCallResponses(createAddResponse(createObjectWithMetaData()));
163164

164165
createAndRunWatcher(NAMESPACE, stopping, INITIAL_RESOURCE_VERSION);
165166

166167
assertThat(StubWatchFactory.getNumCloseCalls(), equalTo(2));
167168
}
168169

170+
@SuppressWarnings("SameParameterValue")
169171
private V1ObjectMeta createMetaData(String name, String namespace) {
170172
return new V1ObjectMeta().name(name).namespace(namespace).resourceVersion(getNextResourceVersion());
171173
}

operator/src/test/java/oracle/kubernetes/operator/steps/DeleteIngressListStepTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import io.kubernetes.client.models.V1Status;
1414
import io.kubernetes.client.models.V1beta1Ingress;
1515
import oracle.kubernetes.TestUtils;
16-
import oracle.kubernetes.operator.helpers.AsyncCallTestSupport;
16+
import oracle.kubernetes.operator.work.AsyncCallTestSupport;
1717
import oracle.kubernetes.operator.work.TerminalStep;
1818

1919
import org.junit.After;

operator/src/test/java/oracle/kubernetes/operator/helpers/AsyncCallTestSupport.java renamed to operator/src/test/java/oracle/kubernetes/operator/work/AsyncCallTestSupport.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2018, Oracle Corporation and/or its affiliates. All rights reserved.
22
// Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl.
33

4-
package oracle.kubernetes.operator.helpers;
4+
package oracle.kubernetes.operator.work;
55

66
import java.net.HttpURLConnection;
77
import java.util.ArrayList;
@@ -19,11 +19,10 @@
1919
import oracle.kubernetes.operator.calls.CallFactory;
2020
import oracle.kubernetes.operator.calls.CallResponse;
2121
import oracle.kubernetes.operator.calls.RequestParams;
22-
import oracle.kubernetes.operator.work.Component;
23-
import oracle.kubernetes.operator.work.FiberTestSupport;
24-
import oracle.kubernetes.operator.work.NextAction;
25-
import oracle.kubernetes.operator.work.Packet;
26-
import oracle.kubernetes.operator.work.Step;
22+
import oracle.kubernetes.operator.helpers.AsyncRequestStepFactory;
23+
import oracle.kubernetes.operator.helpers.CallBuilder;
24+
import oracle.kubernetes.operator.helpers.ClientPool;
25+
import oracle.kubernetes.operator.helpers.ResponseStep;
2726

2827
import javax.annotation.Nonnull;
2928

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright 2018, Oracle Corporation and/or its affiliates. All rights reserved.
2+
// Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl.
3+
4+
package oracle.kubernetes.operator.work;
5+
6+
import java.lang.reflect.InvocationTargetException;
7+
import java.net.HttpURLConnection;
8+
import java.util.ArrayList;
9+
import java.util.HashMap;
10+
import java.util.List;
11+
import java.util.Map;
12+
import java.util.Objects;
13+
14+
import io.kubernetes.client.models.V1ObjectMeta;
15+
16+
import javax.annotation.Nonnull;
17+
18+
public abstract class InMemoryDatabase<T, L> {
19+
20+
private Map<DatabaseKey, T> contents = new HashMap<>();
21+
22+
public void create(T item, Map<String, String> keys) {
23+
T t = contents.get(new DatabaseKey(keys, item));
24+
if (t != null) throw new InMemoryDatabaseException(HttpURLConnection.HTTP_CONFLICT, "Item already exists");
25+
26+
contents.put(new DatabaseKey(keys, item), item);
27+
}
28+
29+
void delete(Map<String, String> keys) {
30+
T removed = contents.remove(new DatabaseKey(keys));
31+
if (removed == null) throw new InMemoryDatabaseException(HttpURLConnection.HTTP_NOT_FOUND, "No such item");
32+
}
33+
34+
@SuppressWarnings("unchecked")
35+
L list(Map<String, String> searchKeys) {
36+
List<T> foundItems = new ArrayList<>();
37+
for (DatabaseKey key : contents.keySet())
38+
if (key.matches(searchKeys)) foundItems.add(contents.get(key));
39+
40+
return createList(foundItems);
41+
}
42+
43+
T read(Map<String, String> keys) {
44+
T t = contents.get(new DatabaseKey(keys));
45+
if (t == null) throw new InMemoryDatabaseException(HttpURLConnection.HTTP_NOT_FOUND, "No such item");
46+
return t;
47+
}
48+
49+
@SuppressWarnings("unchecked")
50+
abstract L createList(List<T> items);
51+
52+
void replace(T item, Map<String, String> keys) {
53+
DatabaseKey databaseKey = new DatabaseKey(keys, item);
54+
T t = contents.get(databaseKey);
55+
if (t == null) throw new InMemoryDatabaseException(HttpURLConnection.HTTP_NOT_FOUND, "No such item");
56+
57+
contents.put(databaseKey, item);
58+
}
59+
60+
61+
private static class DatabaseKey {
62+
private Map<String, String> keys;
63+
64+
DatabaseKey(@Nonnull Map<String, String> keys) {
65+
this.keys = new HashMap<>(keys);
66+
}
67+
68+
DatabaseKey(@Nonnull Map<String, String> keys, Object o) {
69+
this(keys);
70+
String name = getName(o);
71+
if (name != null) this.keys.put("name", name);
72+
}
73+
74+
private String getName(Object o) {
75+
try {
76+
V1ObjectMeta meta = (V1ObjectMeta) o.getClass().getMethod("getMetadata").invoke(o);
77+
return meta.getName();
78+
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
79+
return null;
80+
}
81+
}
82+
83+
boolean matches(Map<String, String> searchKeys) {
84+
for (String key : searchKeys.keySet())
85+
if (!Objects.equals(searchKeys.get(key), keys.get(key))) return false;
86+
return true;
87+
}
88+
89+
@Override
90+
public boolean equals(Object o) {
91+
return o == this || ((o instanceof DatabaseKey) && keys.equals(((DatabaseKey) o).keys));
92+
}
93+
94+
@Override
95+
public int hashCode() {
96+
return Objects.hash(keys);
97+
}
98+
}
99+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package oracle.kubernetes.operator.work;
2+
3+
public class InMemoryDatabaseException extends RuntimeException {
4+
private int code;
5+
6+
InMemoryDatabaseException(int code, String message) {
7+
super(message);
8+
this.code = code;
9+
}
10+
11+
public int getCode() {
12+
return code;
13+
}
14+
}

0 commit comments

Comments
 (0)