• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.launcher3.util;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertTrue;
21 
22 import androidx.test.filters.LargeTest;
23 import androidx.test.runner.AndroidJUnit4;
24 
25 import org.junit.Ignore;
26 import org.junit.Test;
27 import org.junit.runner.RunWith;
28 
29 @LargeTest
30 @RunWith(AndroidJUnit4.class)
31 public class RaceConditionReproducerTest {
32     private final static String SOME_VALID_SEQUENCE_3_3 = "B1|A1|A2|B2|A3|B3";
33 
factorial(int n)34     private static int factorial(int n) {
35         int res = 1;
36         for (int i = 2; i <= n; ++i) res *= i;
37         return res;
38     }
39 
run3_3_TestAction()40     private static void run3_3_TestAction() throws InterruptedException {
41         Thread tb = new Thread(() -> {
42             RaceConditionTracker.onEvent("B1");
43             RaceConditionTracker.onEvent("B2");
44             RaceConditionTracker.onEvent("B3");
45         });
46         tb.start();
47 
48         RaceConditionTracker.onEvent("A1");
49         RaceConditionTracker.onEvent("A2");
50         RaceConditionTracker.onEvent("A3");
51 
52         tb.join();
53     }
54 
55     @Test
56     @Ignore // The test is too long for continuous testing.
57     // 2 threads, 3 events each.
test3_3()58     public void test3_3() throws Exception {
59         final RaceConditionReproducer eventProcessor = new RaceConditionReproducer();
60         boolean sawTheValidSequence = false;
61 
62         for (; ; ) {
63             eventProcessor.startIteration();
64             run3_3_TestAction();
65             final boolean needMoreIterations = eventProcessor.finishIteration();
66 
67             sawTheValidSequence = sawTheValidSequence ||
68                     SOME_VALID_SEQUENCE_3_3.equals(eventProcessor.getCurrentSequenceString());
69 
70             if (!needMoreIterations) break;
71         }
72 
73         assertEquals("Wrong number of leaf nodes",
74                 factorial(3 + 3) / (factorial(3) * factorial(3)),
75                 eventProcessor.numberOfLeafNodes());
76         assertTrue(sawTheValidSequence);
77     }
78 
79     @Test
80     @Ignore // The test is too long for continuous testing.
81     // 2 threads, 3 events, including enter-exit pairs each.
test3_3_enter_exit()82     public void test3_3_enter_exit() throws Exception {
83         final RaceConditionReproducer eventProcessor = new RaceConditionReproducer();
84         boolean sawTheValidSequence = false;
85 
86         for (; ; ) {
87             eventProcessor.startIteration();
88             Thread tb = new Thread(() -> {
89                 RaceConditionTracker.onEvent("B1:enter");
90                 RaceConditionTracker.onEvent("B1:exit");
91                 RaceConditionTracker.onEvent("B2");
92                 RaceConditionTracker.onEvent("B3:enter");
93                 RaceConditionTracker.onEvent("B3:exit");
94             });
95             tb.start();
96 
97             RaceConditionTracker.onEvent("A1");
98             RaceConditionTracker.onEvent("A2:enter");
99             RaceConditionTracker.onEvent("A2:exit");
100             RaceConditionTracker.onEvent("A3:enter");
101             RaceConditionTracker.onEvent("A3:exit");
102 
103             tb.join();
104             final boolean needMoreIterations = eventProcessor.finishIteration();
105 
106             sawTheValidSequence = sawTheValidSequence ||
107                     "B1:enter|B1:exit|A1|A2:enter|A2:exit|B2|A3:enter|A3:exit|B3:enter|B3:exit".
108                             equals(eventProcessor.getCurrentSequenceString());
109 
110             if (!needMoreIterations) break;
111         }
112 
113         assertEquals("Wrong number of leaf nodes",
114                 factorial(3 + 3) / (factorial(3) * factorial(3)),
115                 eventProcessor.numberOfLeafNodes());
116         assertTrue(sawTheValidSequence);
117     }
118 
119     @Test
120     // 2 threads, 3 events each; reproducing a particular event sequence.
test3_3_ReproMode()121     public void test3_3_ReproMode() throws Exception {
122         final RaceConditionReproducer eventProcessor = new RaceConditionReproducer(
123                 SOME_VALID_SEQUENCE_3_3);
124 
125         eventProcessor.startIteration();
126         run3_3_TestAction();
127         assertTrue(!eventProcessor.finishIteration());
128         assertEquals(SOME_VALID_SEQUENCE_3_3, eventProcessor.getCurrentSequenceString());
129 
130         assertEquals("Wrong number of leaf nodes", 1, eventProcessor.numberOfLeafNodes());
131     }
132 
133     @Test
134     @Ignore // The test is too long for continuous testing.
135     // 2 threads with 2 events; 1 thread with 1 event.
test2_1_2()136     public void test2_1_2() throws Exception {
137         final RaceConditionReproducer eventProcessor = new RaceConditionReproducer();
138 
139         for (; ; ) {
140             eventProcessor.startIteration();
141             Thread tb = new Thread(() -> {
142                 RaceConditionTracker.onEvent("B1");
143                 RaceConditionTracker.onEvent("B2");
144             });
145             tb.start();
146 
147             Thread tc = new Thread(() -> {
148                 RaceConditionTracker.onEvent("C1");
149             });
150             tc.start();
151 
152             RaceConditionTracker.onEvent("A1");
153             RaceConditionTracker.onEvent("A2");
154 
155             tb.join();
156             tc.join();
157 
158             if (!eventProcessor.finishIteration()) break;
159         }
160 
161         assertEquals("Wrong number of leaf nodes",
162                 factorial(2 + 2 + 1) / (factorial(2) * factorial(2) * factorial(1)),
163                 eventProcessor.numberOfLeafNodes());
164     }
165 
166     @Test
167     @Ignore // The test is too long for continuous testing.
168     // 2 threads with 2 events; 1 thread with 1 event. Includes enter-exit pairs.
test2_1_2_enter_exit()169     public void test2_1_2_enter_exit() throws Exception {
170         final RaceConditionReproducer eventProcessor = new RaceConditionReproducer();
171 
172         for (; ; ) {
173             eventProcessor.startIteration();
174             Thread tb = new Thread(() -> {
175                 RaceConditionTracker.onEvent("B1:enter");
176                 RaceConditionTracker.onEvent("B1:exit");
177                 RaceConditionTracker.onEvent("B2:enter");
178                 RaceConditionTracker.onEvent("B2:exit");
179             });
180             tb.start();
181 
182             Thread tc = new Thread(() -> {
183                 RaceConditionTracker.onEvent("C1:enter");
184                 RaceConditionTracker.onEvent("C1:exit");
185             });
186             tc.start();
187 
188             RaceConditionTracker.onEvent("A1:enter");
189             RaceConditionTracker.onEvent("A1:exit");
190             RaceConditionTracker.onEvent("A2:enter");
191             RaceConditionTracker.onEvent("A2:exit");
192 
193             tb.join();
194             tc.join();
195 
196             if (!eventProcessor.finishIteration()) break;
197         }
198 
199         assertEquals("Wrong number of leaf nodes",
200                 factorial(2 + 2 + 1) / (factorial(2) * factorial(2) * factorial(1)),
201                 eventProcessor.numberOfLeafNodes());
202     }
203 }
204