1 package com.atlassian.plugin.manager;
2
3 import com.atlassian.plugin.event.PluginEventManager;
4 import com.atlassian.plugin.event.events.PluginTransactionStartEvent;
5 import com.atlassian.plugin.event.events.PluginTransactionEndEvent;
6 import com.atlassian.plugin.event.impl.DefaultPluginEventManager;
7 import com.atlassian.plugin.event.listeners.RecordingListener;
8 import com.google.common.base.Predicates;
9 import org.junit.Before;
10 import org.junit.Test;
11
12 import java.util.concurrent.atomic.AtomicBoolean;
13 import java.util.concurrent.atomic.AtomicInteger;
14
15 import static junit.framework.TestCase.assertTrue;
16 import static org.hamcrest.MatcherAssert.assertThat;
17 import static org.hamcrest.Matchers.contains;
18 import static org.hamcrest.Matchers.equalTo;
19 import static org.hamcrest.Matchers.is;
20
21
22 public class TestPluginTransactionContext {
23
24 private PluginTransactionContext pluginTransactionContext;
25 private RecordingListener listener;
26
27 @Before
28 public void setUp() throws Exception {
29 listener = new RecordingListener(
30 PluginTransactionStartEvent.class,
31 PluginTransactionEndEvent.class
32 );
33 final PluginEventManager pluginEventManager = new DefaultPluginEventManager();
34 pluginEventManager.register(listener);
35 this.pluginTransactionContext = new PluginTransactionContext(pluginEventManager);
36 }
37
38 private static class SomeEventFoo {}
39
40 private static class SomeEventBar {}
41
42 private static class SomeEventBaz {}
43
44 @Test
45 public void testStartStopLevelAndEvents() {
46 final SomeEventBaz beforeTransaction = new SomeEventBaz();
47 final SomeEventBar inTransaction1 = new SomeEventBar();
48 final SomeEventFoo inTransaction2 = new SomeEventFoo();
49 final SomeEventFoo inTransaction3 = new SomeEventFoo();
50 final SomeEventBaz afterTransaction = new SomeEventBaz();
51
52 pluginTransactionContext.addEvent(beforeTransaction);
53 assertThat(pluginTransactionContext.getLevel(), equalTo(0));
54 pluginTransactionContext.start();
55 assertThat(pluginTransactionContext.getLevel(), equalTo(1));
56 pluginTransactionContext.addEvent(inTransaction1);
57 pluginTransactionContext.start();
58 assertThat(pluginTransactionContext.getLevel(), equalTo(2));
59 pluginTransactionContext.addEvent(inTransaction2);
60 pluginTransactionContext.stop();
61 assertThat(pluginTransactionContext.getLevel(), equalTo(1));
62 pluginTransactionContext.addEvent(inTransaction3);
63 pluginTransactionContext.stop();
64 assertThat(pluginTransactionContext.getLevel(), equalTo(0));
65 pluginTransactionContext.addEvent(afterTransaction);
66
67 assertThat(listener.getEventClasses(), contains(
68 PluginTransactionStartEvent.class,
69 PluginTransactionEndEvent.class));
70
71 final PluginTransactionEndEvent pluginTransactionStopEvent = (PluginTransactionEndEvent)listener.getEvents().get(1);
72 assertThat(pluginTransactionStopEvent.numberOfEvents(), equalTo(3));
73 assertTrue(pluginTransactionStopEvent.hasAnyEventOfTypeMatching(SomeEventBar.class, someEventBar -> someEventBar.equals(inTransaction1)));
74 assertTrue(pluginTransactionStopEvent.hasAnyEventOfTypeMatching(SomeEventFoo.class, someEventFoo -> someEventFoo.equals(inTransaction2)));
75 assertTrue(pluginTransactionStopEvent.hasAnyEventOfTypeMatching(SomeEventFoo.class, someEventFoo -> someEventFoo.equals(inTransaction3)));
76 }
77
78 @Test
79 public void testNestedWrap() {
80 final AtomicInteger callbackRuns = new AtomicInteger(0);
81 assertThat(pluginTransactionContext.getLevel(), equalTo(0));
82 pluginTransactionContext.wrap(() -> {
83 assertThat(pluginTransactionContext.getLevel(), equalTo(1));
84 pluginTransactionContext.wrap(() -> {
85 assertThat(pluginTransactionContext.getLevel(), equalTo(2));
86 callbackRuns.incrementAndGet();
87 });
88 assertThat(pluginTransactionContext.getLevel(), equalTo(1));
89 callbackRuns.incrementAndGet();
90 });
91 assertThat(callbackRuns.get(), equalTo(2));
92 }
93
94 @Test
95 public void testTransactionsInThreadContext() throws Exception {
96 assertThat(pluginTransactionContext.getLevel(), equalTo(0));
97 pluginTransactionContext.start();
98 assertThat(pluginTransactionContext.getLevel(), equalTo(1));
99 pluginTransactionContext.addEvent(new SomeEventFoo());
100 pluginTransactionContext.addEvent(new SomeEventFoo());
101 pluginTransactionContext.start();
102 assertThat(pluginTransactionContext.getLevel(), equalTo(2));
103 final AtomicBoolean threadRunWithNoException = new AtomicBoolean(false);
104 final Thread t = new Thread(() -> {
105 assertThat(pluginTransactionContext.getLevel(), equalTo(0));
106 pluginTransactionContext.start();
107 assertThat(pluginTransactionContext.getLevel(), equalTo(1));
108 pluginTransactionContext.addEvent(new SomeEventBar());
109 pluginTransactionContext.addEvent(new SomeEventBar());
110 pluginTransactionContext.stop();
111 assertThat(pluginTransactionContext.getLevel(), equalTo(0));
112 threadRunWithNoException.set(true);
113 });
114 t.start();
115 t.join();
116 assertThat(threadRunWithNoException.get(), is(true));
117 pluginTransactionContext.stop();
118 pluginTransactionContext.stop();
119
120 assertThat(listener.getEventClasses(), contains(
121 PluginTransactionStartEvent.class,
122 PluginTransactionStartEvent.class,
123 PluginTransactionEndEvent.class,
124 PluginTransactionEndEvent.class));
125
126 final PluginTransactionEndEvent pluginTransactionStopEventOtherThread = (PluginTransactionEndEvent) listener.getEvents().get(2);
127 final PluginTransactionEndEvent pluginTransactionStopEventCurrentThread = (PluginTransactionEndEvent) listener.getEvents().get(3);
128
129 assertThat(pluginTransactionStopEventOtherThread.threadId(), equalTo(t.getId()));
130 assertThat(pluginTransactionStopEventCurrentThread.threadId(), equalTo(Thread.currentThread().getId()));
131
132 assertThat(pluginTransactionStopEventOtherThread.hasAnyEventOfTypeMatching(SomeEventBar.class, Predicates.alwaysTrue()), equalTo(true));
133 assertThat(pluginTransactionStopEventOtherThread.hasAnyEventOfTypeMatching(SomeEventFoo.class, Predicates.alwaysTrue()), equalTo(false));
134 assertThat(pluginTransactionStopEventCurrentThread.hasAnyEventOfTypeMatching(SomeEventFoo.class, Predicates.alwaysTrue()), equalTo(true));
135 assertThat(pluginTransactionStopEventCurrentThread.hasAnyEventOfTypeMatching(SomeEventBar.class, Predicates.alwaysTrue()), equalTo(false));
136 }
137 }