blob: 7dde5cc767c16055d029c2b03eee25b143ab49bb [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@LargeTest
@RunWith(AndroidJUnit4.class)
public class RaceConditionReproducerTest {
private final static String SOME_VALID_SEQUENCE_3_3 = "B1|A1|A2|B2|A3|B3";
private static int factorial(int n) {
int res = 1;
for (int i = 2; i <= n; ++i) res *= i;
return res;
}
private static void run3_3_TestAction() throws InterruptedException {
Thread tb = new Thread(() -> {
RaceConditionTracker.onEvent("B1");
RaceConditionTracker.onEvent("B2");
RaceConditionTracker.onEvent("B3");
});
tb.start();
RaceConditionTracker.onEvent("A1");
RaceConditionTracker.onEvent("A2");
RaceConditionTracker.onEvent("A3");
tb.join();
}
@Test
@Ignore // The test is too long for continuous testing.
// 2 threads, 3 events each.
public void test3_3() throws Exception {
final RaceConditionReproducer eventProcessor = new RaceConditionReproducer();
boolean sawTheValidSequence = false;
for (; ; ) {
eventProcessor.startIteration();
run3_3_TestAction();
final boolean needMoreIterations = eventProcessor.finishIteration();
sawTheValidSequence = sawTheValidSequence ||
SOME_VALID_SEQUENCE_3_3.equals(eventProcessor.getCurrentSequenceString());
if (!needMoreIterations) break;
}
assertEquals("Wrong number of leaf nodes",
factorial(3 + 3) / (factorial(3) * factorial(3)),
eventProcessor.numberOfLeafNodes());
assertTrue(sawTheValidSequence);
}
@Test
// 2 threads, 3 events each; reproducing a particular event sequence.
public void test3_3_ReproMode() throws Exception {
final RaceConditionReproducer eventProcessor = new RaceConditionReproducer(
SOME_VALID_SEQUENCE_3_3);
eventProcessor.startIteration();
run3_3_TestAction();
assertTrue(!eventProcessor.finishIteration());
assertEquals(SOME_VALID_SEQUENCE_3_3, eventProcessor.getCurrentSequenceString());
assertEquals("Wrong number of leaf nodes", 1, eventProcessor.numberOfLeafNodes());
}
@Test
@Ignore // The test is too long for continuous testing.
// 2 threads with 2 events; 1 thread with 1 event.
public void test2_1_2() throws Exception {
final RaceConditionReproducer eventProcessor = new RaceConditionReproducer();
for (; ; ) {
eventProcessor.startIteration();
Thread tb = new Thread(() -> {
RaceConditionTracker.onEvent("B1");
RaceConditionTracker.onEvent("B2");
});
tb.start();
Thread tc = new Thread(() -> {
RaceConditionTracker.onEvent("C1");
});
tc.start();
RaceConditionTracker.onEvent("A1");
RaceConditionTracker.onEvent("A2");
tb.join();
tc.join();
if (!eventProcessor.finishIteration()) break;
}
assertEquals("Wrong number of leaf nodes",
factorial(2 + 2 + 1) / (factorial(2) * factorial(2) * factorial(1)),
eventProcessor.numberOfLeafNodes());
}
}