1 package net.secodo.jcircuitbreaker.breakhandler;
2
3 import static org.hamcrest.CoreMatchers.equalTo;
4
5 import static org.junit.Assert.assertThat;
6
7 import static org.mockito.Mockito.mock;
8
9 import java.lang.reflect.Field;
10 import java.util.Map;
11 import java.util.concurrent.ConcurrentHashMap;
12 import java.util.concurrent.atomic.AtomicInteger;
13
14 import net.secodo.jcircuitbreaker.breaker.ContextAwareCircuitBreaker;
15 import net.secodo.jcircuitbreaker.breaker.execution.ExecutionContext;
16 import net.secodo.jcircuitbreaker.breaker.execution.impl.DefaultExecutionContextImpl;
17 import net.secodo.jcircuitbreaker.breakhandler.impl.ReturnStaticValueHandler;
18 import net.secodo.jcircuitbreaker.breakstrategy.BreakStrategy;
19
20 import net.secodo.jcircuitbreaker.exception.TaskExecutionException;
21 import net.secodo.jcircuitbreaker.task.Task;
22 import org.junit.Test;
23
24
25 public class OnePerExecutionHandlerFactoryTest {
26 @Test
27 public void shouldCreateAnUseOnlyOnInstanceOfBreakHandlerPerExecutionContext() throws Exception {
28
29 ExecutionContext<Long> executionContext = new DefaultExecutionContextImpl<>(new ConcurrentHashMap<>(), null);
30
31 AtomicInteger counter = new AtomicInteger();
32
33 OnePerExecutionHandlerFactory<Long> breakHandler = ((task, context) -> {
34 counter.incrementAndGet();
35 return new ReturnStaticValueHandler<>(counter.longValue());
36 });
37
38
39 final Long value1 = breakHandler.onBreak(mock(ContextAwareCircuitBreaker.class),
40 mock(Task.class),
41 mock(BreakStrategy.class),
42 executionContext);
43
44 final Long value2 = breakHandler.onBreak(mock(ContextAwareCircuitBreaker.class),
45 mock(Task.class),
46 mock(BreakStrategy.class),
47 executionContext);
48
49 final Long value3 = breakHandler.onBreak(mock(ContextAwareCircuitBreaker.class),
50 mock(Task.class),
51 mock(BreakStrategy.class),
52 executionContext);
53
54
55
56
57
58 assertThat(value1, equalTo(1L));
59 assertThat(value2, equalTo(1L));
60 assertThat(value3, equalTo(1L));
61
62
63
64
65
66
67 executionContext = new DefaultExecutionContextImpl<>(new ConcurrentHashMap<>(), null);
68
69
70 final Long value4 = breakHandler.onBreak(mock(ContextAwareCircuitBreaker.class),
71 mock(Task.class),
72 mock(BreakStrategy.class),
73 executionContext);
74
75 final Long value5 = breakHandler.onBreak(mock(ContextAwareCircuitBreaker.class),
76 mock(Task.class),
77 mock(BreakStrategy.class),
78 executionContext);
79
80 final Long value6 = breakHandler.onBreak(mock(ContextAwareCircuitBreaker.class),
81 mock(Task.class),
82 mock(BreakStrategy.class),
83 executionContext);
84
85
86
87
88
89
90 assertThat(value4, equalTo(2L));
91 assertThat(value5, equalTo(2L));
92 assertThat(value6, equalTo(2L));
93 }
94
95 @Test
96 public void shouldUseDifferentContextNamesForEachImplementationOfOnePerExecutionHandlerFactory()
97 throws TaskExecutionException, NoSuchFieldException, IllegalAccessException {
98
99 class Factory1 implements OnePerExecutionHandlerFactory<String> {
100 @Override
101 public BreakHandler<String> createNewHandler(Task<String> task, ExecutionContext<String> executionContext) {
102 return (circuitBreaker, task1, breakStrategy, executionContext1) -> "ABC";
103 }
104 }
105
106 class Factory2 implements OnePerExecutionHandlerFactory<String> {
107 @Override
108 public BreakHandler<String> createNewHandler(Task<String> task, ExecutionContext<String> executionContext) {
109 return (circuitBreaker, task1, breakStrategy, executionContext1) -> "XYZ";
110 }
111 }
112
113 Factory1 breakHandlerFactory1 = new Factory1();
114 Factory2 breakHandlerFactory2 = new Factory2();
115
116 DefaultExecutionContextImpl<String> executionContext = new DefaultExecutionContextImpl<>(new ConcurrentHashMap<>(), null);
117
118
119 breakHandlerFactory1.onBreak(mock(ContextAwareCircuitBreaker.class), mock(Task.class), mock(BreakStrategy.class),
120 executionContext);
121
122 assertThat(getContextAttributes(executionContext).size(), equalTo(1));
123
124
125 breakHandlerFactory1.onBreak(mock(ContextAwareCircuitBreaker.class), mock(Task.class), mock(BreakStrategy.class),
126 executionContext);
127
128 assertThat(getContextAttributes(executionContext).size(), equalTo(1));
129
130
131
132
133 breakHandlerFactory2.onBreak(mock(ContextAwareCircuitBreaker.class), mock(Task.class), mock(BreakStrategy.class),
134 executionContext);
135
136 assertThat(getContextAttributes(executionContext).size(), equalTo(2));
137
138
139 breakHandlerFactory2.onBreak(mock(ContextAwareCircuitBreaker.class), mock(Task.class), mock(BreakStrategy.class),
140 executionContext);
141
142 assertThat(getContextAttributes(executionContext).size(), equalTo(2));
143
144
145 }
146
147 private Map<String, Object> getContextAttributes(DefaultExecutionContextImpl defaultExecutionContext)
148 throws NoSuchFieldException, IllegalAccessException {
149
150 Field contextAttributesField = DefaultExecutionContextImpl.class.getDeclaredField("contextAttributes");
151 contextAttributesField.setAccessible(true);
152 return (Map<String, Object>) contextAttributesField.get(defaultExecutionContext);
153 }
154
155
156
157 }
158