• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric;
2 
3 import static com.google.common.truth.Truth.assertThat;
4 
5 import java.lang.reflect.Field;
6 import org.junit.Test;
7 import org.junit.runner.RunWith;
8 import org.robolectric.annotation.Implementation;
9 import org.robolectric.annotation.Implements;
10 import org.robolectric.annotation.RealObject;
11 import org.robolectric.annotation.internal.Instrument;
12 import org.robolectric.internal.SandboxTestRunner;
13 import org.robolectric.internal.bytecode.SandboxConfig;
14 import org.robolectric.shadow.api.Shadow;
15 
16 @RunWith(SandboxTestRunner.class)
17 public class ThreadSafetyTest {
18   @Test
19   @SandboxConfig(shadows = {InstrumentedThreadShadow.class})
shadowCreationShouldBeThreadsafe()20   public void shadowCreationShouldBeThreadsafe() throws Exception {
21     Field field = InstrumentedThread.class.getDeclaredField("shadowFromOtherThread");
22     field.setAccessible(true);
23 
24     for (int i = 0; i < 100; i++) { // :-(
25       InstrumentedThread instrumentedThread = new InstrumentedThread();
26       instrumentedThread.start();
27       Object shadowFromThisThread = Shadow.extract(instrumentedThread);
28 
29       instrumentedThread.join();
30       Object shadowFromOtherThread = field.get(instrumentedThread);
31       assertThat(shadowFromThisThread).isSameInstanceAs(shadowFromOtherThread);
32     }
33   }
34 
35   @Instrument
36   public static class InstrumentedThread extends Thread {
37     InstrumentedThreadShadow shadowFromOtherThread;
38 
39     @Override
run()40     public void run() {
41       shadowFromOtherThread = Shadow.extract(this);
42     }
43   }
44 
45   @Implements(InstrumentedThread.class)
46   public static class InstrumentedThreadShadow {
47     @RealObject InstrumentedThread realObject;
48     @Implementation
run()49     protected void run() {
50       Shadow.directlyOn(realObject, InstrumentedThread.class, "run");
51     }
52   }
53 }
54