View Javadoc
1   package mockit;
2   
3   import static org.junit.jupiter.api.Assertions.assertEquals;
4   import static org.junit.jupiter.api.Assertions.assertFalse;
5   import static org.junit.jupiter.api.Assertions.assertNotNull;
6   import static org.junit.jupiter.api.Assertions.assertNull;
7   import static org.junit.jupiter.api.Assertions.assertThrows;
8   import static org.junit.jupiter.api.Assertions.assertTrue;
9   
10  import java.util.Collections;
11  import java.util.Map;
12  
13  import javax.security.auth.Subject;
14  import javax.security.auth.callback.CallbackHandler;
15  import javax.security.auth.login.AppConfigurationEntry;
16  import javax.security.auth.login.Configuration;
17  import javax.security.auth.login.LoginContext;
18  import javax.security.auth.login.LoginException;
19  import javax.security.auth.spi.LoginModule;
20  
21  import org.junit.jupiter.api.Test;
22  
23  /**
24   * The Class FakeLoginContextTest.
25   */
26  final class FakeLoginContextTest {
27  
28      /**
29       * Fake JRE method and constructor using fake class.
30       *
31       * @throws Exception
32       *             the exception
33       */
34      @Test
35      void fakeJREMethodAndConstructorUsingFakeClass() throws Exception {
36          new FakeLoginContext();
37  
38          new LoginContext("test", (CallbackHandler) null).login();
39      }
40  
41      /**
42       * The Class FakeLoginContext.
43       */
44      public static class FakeLoginContext extends MockUp<LoginContext> {
45  
46          /**
47           * $init.
48           *
49           * @param name
50           *            the name
51           * @param callbackHandler
52           *            the callback handler
53           */
54          @Mock
55          public void $init(String name, CallbackHandler callbackHandler) {
56              assertEquals("test", name);
57              assertNull(callbackHandler);
58          }
59  
60          /**
61           * Login.
62           */
63          @Mock
64          public void login() {
65          }
66  
67          /**
68           * Gets the subject.
69           *
70           * @return the subject
71           */
72          @Mock
73          public Subject getSubject() {
74              return null;
75          }
76      }
77  
78      /**
79       * Fake JRE method and constructor with fake class.
80       *
81       * @throws Exception
82       *             the exception
83       */
84      @Test
85      void fakeJREMethodAndConstructorWithFakeClass() throws Exception {
86          new MockUp<LoginContext>() {
87              @Mock
88              void $init(String name) {
89                  assertEquals("test", name);
90              }
91  
92              @Mock
93              void login() throws LoginException {
94                  throw new LoginException();
95              }
96          };
97  
98          assertThrows(LoginException.class, () -> {
99              new LoginContext("test").login();
100         });
101     }
102 
103     /**
104      * Fake JRE class with stubs.
105      *
106      * @throws Exception
107      *             the exception
108      */
109     @Test
110     void fakeJREClassWithStubs() throws Exception {
111         new FakeLoginContextWithStubs();
112 
113         LoginContext context = new LoginContext("");
114         context.login();
115         context.logout();
116     }
117 
118     /**
119      * The Class FakeLoginContextWithStubs.
120      */
121     static final class FakeLoginContextWithStubs extends MockUp<LoginContext> {
122 
123         /**
124          * $init.
125          *
126          * @param s
127          *            the s
128          */
129         @Mock
130         void $init(String s) {
131         }
132 
133         /**
134          * Logout.
135          */
136         @Mock
137         void logout() {
138         }
139 
140         /**
141          * Login.
142          */
143         @Mock
144         void login() {
145         }
146     }
147 
148     /**
149      * Access faked instance.
150      *
151      * @throws Exception
152      *             the exception
153      */
154     @Test
155     void accessFakedInstance() throws Exception {
156         new MockUp<LoginContext>() {
157             Subject testSubject;
158 
159             @Mock
160             void $init(Invocation inv, String name, Subject subject) {
161                 assertNotNull(name);
162                 assertNotNull(subject);
163                 LoginContext it = inv.getInvokedInstance();
164                 assertNotNull(it);
165                 assertEquals(1, inv.getInvocationCount());
166             }
167 
168             @Mock
169             void login(Invocation inv) {
170                 LoginContext it = inv.getInvokedInstance();
171                 assertNull(it.getSubject()); // returns null until the subject is authenticated
172                 testSubject = new Subject();
173             }
174 
175             @Mock
176             void logout() {
177                 testSubject = null;
178             }
179 
180             @Mock
181             Subject getSubject() {
182                 return testSubject;
183             }
184         };
185 
186         LoginContext fakedInstance = new LoginContext("test", new Subject());
187         assertNull(fakedInstance.getSubject());
188         fakedInstance.login();
189         assertNotNull(fakedInstance.getSubject());
190         fakedInstance.logout();
191         assertNull(fakedInstance.getSubject());
192     }
193 
194     /**
195      * Proceed into real implementations of faked methods.
196      *
197      * @throws Exception
198      *             the exception
199      */
200     @Test
201     void proceedIntoRealImplementationsOfFakedMethods() throws Exception {
202         // Create objects to be exercised by the code under test:
203         Configuration configuration = new Configuration() {
204             @Override
205             public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
206                 Map<String, ?> options = Collections.emptyMap();
207 
208                 return new AppConfigurationEntry[] { new AppConfigurationEntry(TestLoginModule.class.getName(),
209                         AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT, options) };
210             }
211         };
212 
213         LoginContext loginContext = new LoginContext("test", null, null, configuration);
214 
215         // Apply fakes:
216         ProceedingFakeLoginContext fakeInstance = new ProceedingFakeLoginContext();
217 
218         // Exercise the code under test:
219         assertNull(loginContext.getSubject());
220         loginContext.login();
221         assertNotNull(loginContext.getSubject());
222         assertTrue(fakeInstance.loggedIn);
223 
224         fakeInstance.ignoreLogout = true;
225         loginContext.logout();
226         assertTrue(fakeInstance.loggedIn);
227 
228         fakeInstance.ignoreLogout = false;
229         loginContext.logout();
230         assertFalse(fakeInstance.loggedIn);
231     }
232 
233     /**
234      * The Class ProceedingFakeLoginContext.
235      */
236     static final class ProceedingFakeLoginContext extends MockUp<LoginContext> {
237 
238         /** The ignore logout. */
239         boolean ignoreLogout;
240 
241         /** The logged in. */
242         boolean loggedIn;
243 
244         /**
245          * Login.
246          *
247          * @param inv
248          *            the inv
249          */
250         @Mock
251         void login(Invocation inv) {
252             LoginContext it = inv.getInvokedInstance();
253 
254             try {
255                 inv.proceed();
256                 loggedIn = true;
257             } finally {
258                 it.getSubject();
259             }
260         }
261 
262         /**
263          * Logout.
264          *
265          * @param inv
266          *            the inv
267          */
268         @Mock
269         void logout(Invocation inv) {
270             if (!ignoreLogout) {
271                 inv.proceed();
272                 loggedIn = false;
273             }
274         }
275     }
276 
277     /**
278      * The Class TestLoginModule.
279      */
280     public static class TestLoginModule implements LoginModule {
281         @Override
282         public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
283                 Map<String, ?> options) {
284         }
285 
286         @Override
287         public boolean login() {
288             return true;
289         }
290 
291         @Override
292         public boolean commit() {
293             return true;
294         }
295 
296         @Override
297         public boolean abort() {
298             return false;
299         }
300 
301         @Override
302         public boolean logout() {
303             return true;
304         }
305     }
306 }