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.After; 26 import org.junit.Before; 27 import org.junit.Ignore; 28 import org.junit.Test; 29 import org.junit.runner.RunWith; 30 31 @LargeTest 32 @RunWith(AndroidJUnit4.class) 33 public class RaceConditionReproducerTest { 34 private final static String SOME_VALID_SEQUENCE_3_3 = "B1|A1|A2|B2|A3|B3"; 35 factorial(int n)36 private static int factorial(int n) { 37 int res = 1; 38 for (int i = 2; i <= n; ++i) res *= i; 39 return res; 40 } 41 42 RaceConditionReproducer eventProcessor; 43 44 @Before setup()45 public void setup() { 46 eventProcessor = new RaceConditionReproducer(); 47 } 48 49 @After tearDown()50 public void tearDown() { 51 TraceHelperForTest.cleanup(); 52 } 53 run3_3_TestAction()54 private void run3_3_TestAction() throws InterruptedException { 55 Thread tb = new Thread(() -> { 56 eventProcessor.onEvent("B1"); 57 eventProcessor.onEvent("B2"); 58 eventProcessor.onEvent("B3"); 59 }); 60 tb.start(); 61 62 eventProcessor.onEvent("A1"); 63 eventProcessor.onEvent("A2"); 64 eventProcessor.onEvent("A3"); 65 66 tb.join(); 67 } 68 69 @Test 70 @Ignore // The test is too long for continuous testing. 71 // 2 threads, 3 events each. test3_3()72 public void test3_3() throws Exception { 73 boolean sawTheValidSequence = false; 74 75 for (; ; ) { 76 eventProcessor.startIteration(); 77 run3_3_TestAction(); 78 final boolean needMoreIterations = eventProcessor.finishIteration(); 79 80 sawTheValidSequence = sawTheValidSequence || 81 SOME_VALID_SEQUENCE_3_3.equals(eventProcessor.getCurrentSequenceString()); 82 83 if (!needMoreIterations) break; 84 } 85 86 assertEquals("Wrong number of leaf nodes", 87 factorial(3 + 3) / (factorial(3) * factorial(3)), 88 eventProcessor.numberOfLeafNodes()); 89 assertTrue(sawTheValidSequence); 90 } 91 92 @Test 93 @Ignore // The test is too long for continuous testing. 94 // 2 threads, 3 events, including enter-exit pairs each. test3_3_enter_exit()95 public void test3_3_enter_exit() throws Exception { 96 boolean sawTheValidSequence = false; 97 98 for (; ; ) { 99 eventProcessor.startIteration(); 100 Thread tb = new Thread(() -> { 101 eventProcessor.onEvent("B1:enter"); 102 eventProcessor.onEvent("B1:exit"); 103 eventProcessor.onEvent("B2"); 104 eventProcessor.onEvent("B3:enter"); 105 eventProcessor.onEvent("B3:exit"); 106 }); 107 tb.start(); 108 109 eventProcessor.onEvent("A1"); 110 eventProcessor.onEvent("A2:enter"); 111 eventProcessor.onEvent("A2:exit"); 112 eventProcessor.onEvent("A3:enter"); 113 eventProcessor.onEvent("A3:exit"); 114 115 tb.join(); 116 final boolean needMoreIterations = eventProcessor.finishIteration(); 117 118 sawTheValidSequence = sawTheValidSequence || 119 "B1:enter|B1:exit|A1|A2:enter|A2:exit|B2|A3:enter|A3:exit|B3:enter|B3:exit". 120 equals(eventProcessor.getCurrentSequenceString()); 121 122 if (!needMoreIterations) break; 123 } 124 125 assertEquals("Wrong number of leaf nodes", 126 factorial(3 + 3) / (factorial(3) * factorial(3)), 127 eventProcessor.numberOfLeafNodes()); 128 assertTrue(sawTheValidSequence); 129 } 130 131 @Test 132 // 2 threads, 3 events each; reproducing a particular event sequence. test3_3_ReproMode()133 public void test3_3_ReproMode() throws Exception { 134 eventProcessor = new RaceConditionReproducer(SOME_VALID_SEQUENCE_3_3); 135 eventProcessor.startIteration(); 136 run3_3_TestAction(); 137 assertTrue(!eventProcessor.finishIteration()); 138 assertEquals(SOME_VALID_SEQUENCE_3_3, eventProcessor.getCurrentSequenceString()); 139 140 assertEquals("Wrong number of leaf nodes", 1, eventProcessor.numberOfLeafNodes()); 141 } 142 143 @Test 144 @Ignore // The test is too long for continuous testing. 145 // 2 threads with 2 events; 1 thread with 1 event. test2_1_2()146 public void test2_1_2() throws Exception { 147 for (; ; ) { 148 eventProcessor.startIteration(); 149 Thread tb = new Thread(() -> { 150 eventProcessor.onEvent("B1"); 151 eventProcessor.onEvent("B2"); 152 }); 153 tb.start(); 154 155 Thread tc = new Thread(() -> { 156 eventProcessor.onEvent("C1"); 157 }); 158 tc.start(); 159 160 eventProcessor.onEvent("A1"); 161 eventProcessor.onEvent("A2"); 162 163 tb.join(); 164 tc.join(); 165 166 if (!eventProcessor.finishIteration()) break; 167 } 168 169 assertEquals("Wrong number of leaf nodes", 170 factorial(2 + 2 + 1) / (factorial(2) * factorial(2) * factorial(1)), 171 eventProcessor.numberOfLeafNodes()); 172 } 173 174 @Test 175 @Ignore // The test is too long for continuous testing. 176 // 2 threads with 2 events; 1 thread with 1 event. Includes enter-exit pairs. test2_1_2_enter_exit()177 public void test2_1_2_enter_exit() throws Exception { 178 for (; ; ) { 179 eventProcessor.startIteration(); 180 Thread tb = new Thread(() -> { 181 eventProcessor.onEvent("B1:enter"); 182 eventProcessor.onEvent("B1:exit"); 183 eventProcessor.onEvent("B2:enter"); 184 eventProcessor.onEvent("B2:exit"); 185 }); 186 tb.start(); 187 188 Thread tc = new Thread(() -> { 189 eventProcessor.onEvent("C1:enter"); 190 eventProcessor.onEvent("C1:exit"); 191 }); 192 tc.start(); 193 194 eventProcessor.onEvent("A1:enter"); 195 eventProcessor.onEvent("A1:exit"); 196 eventProcessor.onEvent("A2:enter"); 197 eventProcessor.onEvent("A2:exit"); 198 199 tb.join(); 200 tc.join(); 201 202 if (!eventProcessor.finishIteration()) break; 203 } 204 205 assertEquals("Wrong number of leaf nodes", 206 factorial(2 + 2 + 1) / (factorial(2) * factorial(2) * factorial(1)), 207 eventProcessor.numberOfLeafNodes()); 208 } 209 } 210