• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.base;
6 
7 import static org.mockito.Mockito.times;
8 import static org.mockito.Mockito.verify;
9 import static org.mockito.Mockito.verifyNoMoreInteractions;
10 
11 import org.junit.Test;
12 import org.junit.runner.RunWith;
13 import org.mockito.Mockito;
14 import org.robolectric.annotation.Config;
15 
16 import org.chromium.base.test.BaseRobolectricTestRunner;
17 
18 /** Test class for {@link CallbackController}, which also describes typical usage. */
19 @RunWith(BaseRobolectricTestRunner.class)
20 @Config(manifest = Config.NONE)
21 public class CallbackControllerTest {
22     /** Callbacks in this test act on {@code CallbackTarget}. */
23     private static class CallbackTarget {
runnableTarget()24         public void runnableTarget() {}
25 
callbackTarget(boolean arg)26         public void callbackTarget(boolean arg) {}
27     }
28 
29     @Test
testInstanceCallback()30     public void testInstanceCallback() {
31         CallbackController callbackController = new CallbackController();
32         CallbackTarget target = Mockito.mock(CallbackTarget.class);
33         Callback<Boolean> wrapped = callbackController.makeCancelable(target::callbackTarget);
34 
35         wrapped.onResult(true);
36         verify(target).callbackTarget(true);
37 
38         // Execution possible multiple times.
39         wrapped.onResult(true);
40         verify(target, times(2)).callbackTarget(true);
41 
42         // Won't trigger after CallbackController is destroyed.
43         callbackController.destroy();
44         wrapped.onResult(true);
45         verifyNoMoreInteractions(target);
46     }
47 
48     @Test
testInstanceRunnable()49     public void testInstanceRunnable() {
50         CallbackController callbackController = new CallbackController();
51         CallbackTarget target = Mockito.mock(CallbackTarget.class);
52         Runnable wrapped = callbackController.makeCancelable(target::runnableTarget);
53 
54         wrapped.run();
55         verify(target).runnableTarget();
56 
57         // Execution possible multiple times.
58         wrapped.run();
59         verify(target, times(2)).runnableTarget();
60 
61         // Won't trigger after CallbackController is destroyed.
62         callbackController.destroy();
63         wrapped.run();
64         verifyNoMoreInteractions(target);
65     }
66 
67     @Test
testLambdaCallback()68     public void testLambdaCallback() {
69         CallbackController callbackController = new CallbackController();
70         CallbackTarget target = Mockito.mock(CallbackTarget.class);
71         Callback<Boolean> wrapped =
72                 callbackController.makeCancelable(value -> target.callbackTarget(value));
73 
74         wrapped.onResult(true);
75         verify(target).callbackTarget(true);
76 
77         // Execution possible multiple times.
78         wrapped.onResult(true);
79         verify(target, times(2)).callbackTarget(true);
80 
81         // Won't trigger after CallbackController is destroyed.
82         callbackController.destroy();
83         wrapped.onResult(true);
84         verifyNoMoreInteractions(target);
85     }
86 
87     @Test
testLambdaRunnable()88     public void testLambdaRunnable() {
89         CallbackController callbackController = new CallbackController();
90         CallbackTarget target = Mockito.mock(CallbackTarget.class);
91         Runnable wrapped = callbackController.makeCancelable(() -> target.runnableTarget());
92 
93         wrapped.run();
94         verify(target).runnableTarget();
95 
96         // Execution possible multiple times.
97         wrapped.run();
98         verify(target, times(2)).runnableTarget();
99 
100         // Won't trigger after CallbackController is destroyed.
101         callbackController.destroy();
102         wrapped.run();
103         verifyNoMoreInteractions(target);
104     }
105 
106     @Test
testNestedRunnable()107     public void testNestedRunnable() {
108         CallbackController callbackController = new CallbackController();
109         CallbackTarget target = Mockito.mock(CallbackTarget.class);
110         Runnable makeCancelableAndRun =
111                 () -> callbackController.makeCancelable(target::runnableTarget).run();
112         Runnable wrapped = callbackController.makeCancelable(makeCancelableAndRun);
113 
114         // Inside of the wrapping CancelableRunnable#run(), the inner make/run is performed. This
115         // verifies the lock is reentrant.
116         wrapped.run();
117         verify(target).runnableTarget();
118 
119         wrapped.run();
120         verify(target, times(2)).runnableTarget();
121 
122         callbackController.destroy();
123         wrapped.run();
124         verifyNoMoreInteractions(target);
125     }
126 
127     @Test
testNestedDestroy()128     public void testNestedDestroy() {
129         // Destroying from within a callback should work fine.
130         CallbackController callbackController = new CallbackController();
131         CallbackTarget target = Mockito.mock(CallbackTarget.class);
132         Runnable wrapped = callbackController.makeCancelable(callbackController::destroy);
133 
134         wrapped.run();
135     }
136 }
137