1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18/**
19* @author Alexander V. Astapchuk
20*/
21
22package org.apache.harmony.auth.tests.javax.security.auth.login;
23
24import java.io.IOException;
25import java.net.URL;
26import java.security.AccessControlContext;
27import java.security.AccessController;
28import java.security.BasicPermission;
29import java.security.CodeSource;
30import java.security.DomainCombiner;
31import java.security.Permission;
32import java.security.Permissions;
33import java.security.PrivilegedAction;
34import java.security.PrivilegedExceptionAction;
35import java.security.ProtectionDomain;
36import java.security.Security;
37import java.util.ArrayList;
38import java.util.HashMap;
39import java.util.Map;
40
41import javax.security.auth.AuthPermission;
42import javax.security.auth.Subject;
43import javax.security.auth.SubjectDomainCombiner;
44import javax.security.auth.callback.Callback;
45import javax.security.auth.callback.CallbackHandler;
46import javax.security.auth.callback.UnsupportedCallbackException;
47import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
48import javax.security.auth.login.AppConfigurationEntry;
49import javax.security.auth.login.Configuration;
50import javax.security.auth.login.LoginContext;
51import javax.security.auth.login.LoginException;
52import javax.security.auth.spi.LoginModule;
53
54import junit.framework.TestCase;
55
56
57/**
58 * Unit tests for LoginContext
59 */
60public class LoginContext1Test extends TestCase {
61
62    private static final String CONFIG_NAME = "testConfiguration";
63
64    private static final String DEFAULT_CBHANDLER_PROPERTY = "auth.login.defaultCallbackHandler";
65
66    private static final int OPTIONAL = 0;
67
68    private static final int REQUIRED = 1;
69
70    private static final int REQUISITE = 2;
71
72    private static final int SUFFICIENT = 3;
73
74    /**
75     * Converts short (local) class names (like TestLoginModule) into the
76     * global (fully qualified) ones.<br>
77     * For example:<br>
78     * TestLoginModule => javax.security.auth.login.LoginContextTest$TestLoginModule
79     * @param shortName
80     * @return fully qualified name
81     */
82    private static String getGlobalClassName(String shortName) {
83        return LoginContext1Test.class.getName() + "$" + shortName;
84    }
85
86    /**
87     * Maps an integer value into appropriate LoginModuleControlFlag.
88     * @param flag
89     * @return
90     */
91    private static LoginModuleControlFlag mapControlFlag(int flag) {
92        switch (flag) {
93        case OPTIONAL:
94            return LoginModuleControlFlag.OPTIONAL;
95        case REQUIRED:
96            return LoginModuleControlFlag.REQUIRED;
97        case REQUISITE:
98            return LoginModuleControlFlag.REQUISITE;
99        case SUFFICIENT:
100            return LoginModuleControlFlag.SUFFICIENT;
101        }
102        throw new Error("Unknown flag:" + flag);
103    }
104
105    /**
106     * A special purpose Configuration.<br>
107     * Special functions are:<br>
108     * <il>
109     * <li>it keeps track of the configuration names requested via
110     * getAppConfigurationEntry - see {@link #wasTheNameQueried(String)}
111     * <li>can dynamically add modules - see
112     * add{Optional|Required|Requisite|Sufficient}
113     * <li>with a presumption that the statically installed Configuration
114     * is also of type TestConfig, allows to dynamically add modules to that
115     * installed Configuration - see addInstalled{*}.
116     * <li>can handle several Configurations with a different names for the
117     * {@link #getAppConfigurationEntry(String)} - see
118     * {@link #addConfig(String, Configuration)} (again, with a presumption that
119     * the Configuration.getConfiguration() is instanceof TestConfig )
120     * </il>
121     */
122    private static final class TestConfig extends Configuration {
123        private String name;
124
125        private final ArrayList<AppConfigurationEntry> entries = new ArrayList<AppConfigurationEntry>();
126
127        // A map 'name'=>'some specific configuration'
128        private final HashMap<String, Configuration> configs = new HashMap<String, Configuration>();
129
130        // An array which keeps track of the configuration names requested.
131        private final ArrayList<String> requests = new ArrayList<String>();
132
133        public TestConfig() {
134        }
135
136        public TestConfig(String name) {
137            this.name = name;
138        }
139
140        @Override
141        public AppConfigurationEntry[] getAppConfigurationEntry(String appName) {
142
143            if (!requests.contains(appName)) {
144                requests.add(appName);
145            }
146
147            if (name == null || !name.equals(appName)) {
148
149                Configuration conf = configs.get(appName);
150                if (conf != null) {
151                    return conf.getAppConfigurationEntry(appName);
152                }
153
154                if (!CONFIG_NAME.equals(appName)) {
155                    return null;
156                }
157            }
158
159            AppConfigurationEntry ret[] = new AppConfigurationEntry[entries
160                    .size()];
161            entries.toArray(ret);
162            return ret;
163        }
164
165        @Override
166        public void refresh() {
167            // do nothing
168        }
169
170        public boolean wasTheNameQueried(String name) {
171            return requests.contains(name);
172        }
173
174        String addRequired(String name) {
175            return add(name,
176                    AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
177                    new HashMap<String, Object>());
178        }
179
180        String addOptional(String name) {
181            return add(name,
182                    AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL,
183                    new HashMap<String, Object>());
184        }
185
186        String addSufficient(String name) {
187            return add(name,
188                    AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT,
189                    new HashMap<String, Object>());
190        }
191
192        String addRequisite(String name) {
193            return add(name, LoginModuleControlFlag.REQUISITE, new HashMap<String, Object>());
194        }
195
196        String add(int type, String name, Map<String, ?> options) {
197            return add(name, mapControlFlag(type), options);
198        }
199
200        String add(String name,
201                AppConfigurationEntry.LoginModuleControlFlag flag, Map<String, ?> options) {
202            String fullName = getGlobalClassName(name);
203            AppConfigurationEntry entry = new AppConfigurationEntry(fullName,
204                    flag, options);
205            entries.add(entry);
206            return fullName;
207        }
208
209        public static String addInstalledRequired(String name) {
210            return ((TestConfig) Configuration.getConfiguration())
211                    .addRequired(name);
212        }
213
214        public static String addInstalledOptional(String name) {
215            return ((TestConfig) Configuration.getConfiguration())
216                    .addOptional(name);
217        }
218
219        public static String addInstalledRequisite(String name) {
220            return ((TestConfig) Configuration.getConfiguration())
221                    .addRequisite(name);
222        }
223
224        public static String addInstalledSufficient(String name) {
225            return ((TestConfig) Configuration.getConfiguration())
226                    .addSufficient(name);
227        }
228
229        public static String addInstalled(int type, String name) {
230            return ((TestConfig) Configuration.getConfiguration()).add(type,
231                    name, new HashMap<String, Object>());
232        }
233
234        public static void clear() {
235            ((TestConfig) Configuration.getConfiguration()).entries.clear();
236            ((TestConfig) Configuration.getConfiguration()).configs.clear();
237        }
238
239        public static void addConfig(String name, Configuration conf) {
240            ((TestConfig) Configuration.getConfiguration()).configs.put(name,
241                    conf);
242        }
243
244        public static TestConfig get() {
245            return (TestConfig) Configuration.getConfiguration();
246        }
247    }
248
249    /**
250     * A special-purpose LoginModule.<br>
251     * It has the following features:<br>
252     * <il>
253     * <li>its behaviour is managed - either on by-instance level (via a flags
254     * passed to its ctor) ar on a global level - through the static mask
255     *
256     * <li>the behaviour managed includes: returning a specified value
257     * (true/false) from defined methods/ctor, or throwing an
258     * Error/RuntimeException/LoginException -either specified by user or
259     * created dynamically - from defined methods
260     *
261     * <li>it keeps track of instances created
262     *
263     * <li>each instance keeps track of which method was called
264     * </il>
265     *
266     * The behaviour can be managed either for each particular instance - by
267     * passing an appropriate mask into ctor, or can be managed globally - via
268     * static field {@link #staticMask}.<br>
269     * By default, all the methods return <code>true</code> (success) and do not
270     * throw anything.<br>
271     * The constants <b>FAIL_AT_*</b> shows where to fail. Then if
272     * {@link staticRE} field is set, then this RuntimeException will be thrown,
273     * otherwise if {@link #staticErr} is set, then this Error will be thrown,
274     * otherwise, if {@link #staticLE} is set, then this LoginException will be
275     * thrown, otherwise, finally, a new LoginException will be constructed and
276     * thrown.<br>
277     * The constants <b>FALSE_AT_*</b> shows which method must return
278     * <code>false</code>.
279     * The <b><code>FAIL_AT_*</code></b> constants have priority before
280     * <b><code>FALSE_AT_*</code></b><br>
281     * Note: if an instance executes <code>FAIL_AT_CTOR</code>, then this
282     * instance do <b>not</b> get tracked.
283     */
284
285    public static class TestLoginModule implements LoginModule {
286        public static final int FAIL_AT_CTOR = 0x001;
287
288        public static final int FAIL_AT_INIT = 0x002;
289
290        public static final int FAIL_AT_LOGIN = 0x004;
291
292        public static final int FAIL_AT_COMMIT = 0x008;
293
294        public static final int FAIL_AT_LOGOUT = 0x010;
295
296        public static final int FAIL_AT_ABORT = 0x020;
297
298        //
299        public static final int FALSE_AT_LOGIN = 0x040;
300
301        public static final int FALSE_AT_COMMIT = 0x080;
302
303        public static final int FALSE_AT_LOGOUT = 0x100;
304
305        public static final int FALSE_AT_ABORT = 0x200;
306
307        // A message used to construct LoginException
308        private static final String msg = "Managed test exception. Nothing serious.";
309
310        public static int staticMask = 0;
311
312        public static RuntimeException staticRE;
313
314        public static Error staticERR;
315
316        public static LoginException staticLE;
317
318        //
319        protected static ArrayList<TestLoginModule> instances = new ArrayList<TestLoginModule>();
320
321        private boolean initCalled;
322
323        private boolean loginCalled;
324
325        private boolean abortCalled;
326
327        private boolean commitCalled;
328
329        private boolean logoutCalled;
330
331        public CallbackHandler cbHandler;
332
333        //
334        private int mask;
335
336        private RuntimeException re;
337
338        private Error err;
339
340        private LoginException le;
341
342        /**
343         * returns <code>i</code> item from the list of tracked items.
344         */
345        static TestLoginModule get(int i) {
346            return instances.get(i);
347        }
348
349        /**
350         * Clears the list of tracked instances.
351         */
352        static void clear() {
353            instances.clear();
354        }
355
356        /**
357         * Returns the number of items tracked.
358         */
359        static int size() {
360            return instances.size();
361        }
362
363        public TestLoginModule() {
364            this(-1, staticRE, staticERR, staticLE);
365        }
366
367        protected TestLoginModule(int mask) {
368            this(mask, null, null, null);
369        }
370
371        protected TestLoginModule(int mask, RuntimeException re) {
372            this(mask, re, null, null);
373        }
374
375        protected TestLoginModule(int mask, Error err) {
376            this(mask, null, err, null);
377        }
378
379        protected TestLoginModule(int mask, LoginException le) {
380            this(mask, null, null, le);
381        }
382
383        /**
384         * Constructs and initializes instance of the TestLoginModule.<br>
385         * If you want the instance to use {@link #staticMask} then pass
386         * <code>-1</code> as <code>mask</code>. To fail at nowhere, pass
387         * <code>0</code> as <code>mask</code>.<br>
388         * The appropriate <code>re</code>, <code>err</code> and
389         * <code>le</code> will be used to throw appropriate Throwable (if any).
390         *
391         * @param mask
392         * @param re
393         * @param err
394         * @param le
395         */
396        protected TestLoginModule(int mask, RuntimeException re, Error err,
397                LoginException le) {
398            this.mask = mask;
399            this.re = re;
400            this.err = err;
401            this.le = le;
402            boolean doit = ((mask == -1) && (staticMask & FAIL_AT_CTOR) != 0)
403                    || ((mask != -1) && (mask & FAIL_AT_CTOR) != 0);
404            if (doit) {
405                check();
406                throw new RuntimeException(msg);
407            }
408            instances.add(this);
409        }
410
411        /**
412         * Checks whether the instance variables are set and throw either
413         * RuntimeException (checked first) or Error (checked next).<br>
414         * If none of them specified, then the method returns silently.
415         * @throws RuntimeException
416         * @throws Error
417         */
418        private final void check() {
419            if (re != null) {
420                throw re;
421            }
422            if (err != null) {
423                throw err;
424            }
425        }
426
427        /**
428         * This method calls {@link #check()} first to check for possible
429         * RuntimeException or Error.<br>
430         * Then, it checks whether an instance variable specifying
431         * LoginException to throw is set. If the variable is set, then this
432         * LoginException is thrown. Otherwise new LoginException is created
433         * and thrown.
434         *
435         * @throws LoginException
436         */
437        private final void throw_le() throws LoginException {
438            check();
439            throw le == null ? new LoginException(msg) : le;
440        }
441
442        /**
443         * Checks whether the passed <code>msk</code> is set - either at
444         * instance level or on the global level and returns appropriate
445         * value.<br>
446         * If this instance's <code>mask</mask> is not set, then
447         * {@link #staticMask} is checked. If the <code>staticMask</code> is
448         * also not set, then the method returns <code>true</code>. If either
449         * the static mask or the instance mask is set and match the
450         * <code>msk</code> passed, then the method returns false.
451         * @param msk
452         * @return
453         */
454        private final boolean ret(int msk) {
455
456            if (mask == -1 && (staticMask & msk) != 0) {
457                return false;
458            }
459            if (mask != -1 && (mask & msk) != 0) {
460                return false;
461            }
462            return true;
463        }
464
465        public void initialize(Subject subject,
466                CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
467
468            this.cbHandler = callbackHandler;
469            initCalled = true;
470
471            boolean doit = ((mask == -1) && (staticMask & FAIL_AT_INIT) != 0)
472                    || ((mask != -1) && (mask & FAIL_AT_INIT) != 0);
473            if (doit) {
474                check();
475                throw new RuntimeException(msg);
476            }
477        }
478
479        /**
480         * See javax.security.auth.spi.LoginModule.login()
481         */
482        public boolean login() throws LoginException {
483            loginCalled = true;
484            boolean doit = ((mask == -1) && (staticMask & FAIL_AT_LOGIN) != 0)
485                    || ((mask != -1) && (mask & FAIL_AT_LOGIN) != 0);
486            if (doit) {
487                throw_le();
488            }
489            return ret(FALSE_AT_LOGIN);
490        }
491
492        /**
493         * See javax.security.auth.spi.LoginModule.commit()
494         */
495        public boolean commit() throws LoginException {
496            commitCalled = true;
497            boolean doit = ((mask == -1) && (staticMask & FAIL_AT_COMMIT) != 0)
498                    || ((mask != -1) && (mask & FAIL_AT_COMMIT) != 0);
499            if (doit) {
500                throw_le();
501            }
502            return ret(FALSE_AT_COMMIT);
503        }
504
505        /**
506         * See javax.security.auth.spi.LoginModule.logout()
507         */
508        public boolean logout() throws LoginException {
509            logoutCalled = true;
510            boolean doit = ((mask == -1) && (staticMask & FAIL_AT_LOGOUT) != 0)
511                    || ((mask != -1) && (mask & FAIL_AT_LOGOUT) != 0);
512            if (doit) {
513                throw_le();
514            }
515            return ret(FALSE_AT_LOGOUT);
516        }
517
518        /**
519         * See javax.security.auth.spi.LoginModule.abort()
520         */
521        public boolean abort() throws LoginException {
522            abortCalled = true;
523            boolean doit = ((mask == -1) && (staticMask & FAIL_AT_ABORT) != 0)
524                    || ((mask != -1) && (mask & FAIL_AT_ABORT) != 0);
525            if (doit) {
526                throw_le();
527            }
528            return ret(FALSE_AT_ABORT);
529        }
530    }
531
532    /**
533     * A special-purpose LoginModule whose operations are always successful.
534     */
535    public static final class TestLoginModule_Success extends TestLoginModule {
536        public TestLoginModule_Success() {
537            // '0' here means 'the mask is set, fail at nowhere'
538            super(0);
539        }
540    }
541
542    /**
543     * A special-purpose LoginModule whose initialize() method throws
544     * RuntimeException.
545     */
546    public static final class TestLoginModule_InitFails extends TestLoginModule {
547        public TestLoginModule_InitFails() {
548            super(FAIL_AT_INIT, new RuntimeException(
549                    "init: test runtime exception."
550                            + " don't worry about it too much."));
551        }
552    }
553
554    /**
555     * A special-purpose LoginModule whose ctor() throws RuntimeException.
556     */
557    public static final class TestLoginModule_CtorFails extends TestLoginModule {
558        public TestLoginModule_CtorFails() {
559            super(FAIL_AT_CTOR, new RuntimeException(
560                    "ctor: test runtime exception."
561                            + " don't worry about it too much."));
562        }
563    }
564
565    /**
566     * A special-purpose LoginModule whose commit() method throws
567     * RuntimeException.
568     */
569    public static final class TestLoginModule_CommitFails extends
570            TestLoginModule {
571        public TestLoginModule_CommitFails() {
572            super(FAIL_AT_COMMIT, new RuntimeException(
573                    "commit: test runtime exception."
574                            + " don't worry about it too much."));
575        }
576    }
577
578    /**
579     * A special-purpose LoginModule whose methods (but ctor) throw
580     * LoginException.
581     */
582    public static final class TestLoginModule_Fail extends TestLoginModule {
583        public TestLoginModule_Fail() {
584            super(FAIL_AT_INIT | FAIL_AT_LOGIN | FAIL_AT_COMMIT
585                    | FAIL_AT_LOGOUT | FAIL_AT_ABORT);
586        }
587    }
588
589    /**
590     * A special-purpose LoginModule whose methods (where applicable) return
591     * <code>false</code>.
592     */
593    public static final class TestLoginModule_Ignore extends TestLoginModule {
594        public TestLoginModule_Ignore() {
595            super(FALSE_AT_LOGIN | FALSE_AT_COMMIT | FALSE_AT_LOGOUT
596                    | FALSE_AT_ABORT);
597        }
598    }
599
600    /**
601     * A special-purpose CallbackHandler which keeps track of instances
602     * created.<br>
603     */
604    public static class TestCallbackHandler implements CallbackHandler {
605        protected static ArrayList<TestCallbackHandler> instances = new ArrayList<TestCallbackHandler>();
606
607        /**
608         * Returns number of the instances tracked.
609         */
610        public static int size() {
611            return instances.size();
612        }
613
614        /**
615         * Clears the stored items.
616         */
617        public static void clear() {
618            instances.clear();
619        }
620
621        /**
622         * ctor.
623         */
624        public TestCallbackHandler() {
625            instances.add(this);
626        }
627
628        /**
629         * Does nothing.
630         */
631        public void handle(Callback[] callbacks) throws IOException,
632                UnsupportedCallbackException {
633
634        }
635    }
636
637    @Override
638    protected void setUp() throws Exception {
639        super.setUp();
640        Configuration.setConfiguration(new TestConfig());
641        clear();
642    }
643
644    private void clear() {
645        TestConfig.clear();
646        TestLoginModule.clear();
647        TestCallbackHandler.clear();
648        TestLoginModule.staticRE = null;
649        TestLoginModule.staticERR = null;
650        TestLoginModule.staticLE = null;
651        TestLoginModule.staticMask = 0;
652        //
653        Security.setProperty(DEFAULT_CBHANDLER_PROPERTY, "");
654    }
655
656    /**
657     * Tests LoginContext(String)
658     */
659    public void testLoginContextString() throws Exception {
660        // Must not accept nulls
661        try {
662            new LoginContext(null);
663            fail("must not pass here");
664        } catch (LoginException _) {
665            // gut
666        }
667        // Invalid names (which are not presented in Config) must not
668        // be accepted - of no 'other' configuration exists
669        String name = "some strange and non existing name";
670        try {
671            new LoginContext(name);
672            fail("must not pass here");
673        } catch (LoginException _) {
674            // gut
675        }
676
677        assertTrue(TestConfig.get().wasTheNameQueried(name));
678
679        // Invalid names must be processed as 'other' if such Configuration
680        // exists
681        TestConfig conf = new TestConfig("other");
682        conf.addRequired("TestLoginModule_Success");
683        TestConfig.addConfig("other", conf);
684        name = "this strange and non existing name will be treated as 'other'";
685        new LoginContext(name);
686
687        //1st, static installed Config must be queried
688        assertTrue(TestConfig.get().wasTheNameQueried(name));
689        //2d, the another config must be queried for other
690        assertTrue(TestConfig.get().wasTheNameQueried("other"));
691
692        // Valid names which exist but does not have any entries must
693        // also be accepted. Empty set will be considered as a problem
694        // much later - at login() phase
695        new LoginContext(CONFIG_NAME);
696        //
697        Security.setProperty(DEFAULT_CBHANDLER_PROPERTY, "no such class");
698        try {
699            new LoginContext(CONFIG_NAME);
700            fail("must not pass here");
701        } catch (LoginException ex) {
702            // gut
703        }
704        String klassName = getGlobalClassName("TestCallbackHandler");
705
706        Security.setProperty(DEFAULT_CBHANDLER_PROPERTY, klassName);
707        // This also shows that the cbHandler is instantiated at the ctor
708        new LoginContext(CONFIG_NAME);
709        assertEquals(1, TestCallbackHandler.size());
710        // ugh... cant set 'null' here...
711        Security.setProperty(DEFAULT_CBHANDLER_PROPERTY, "");
712        // additional cleanup to make it PerfTests compatible
713        clear();
714    }
715
716    /**
717     * Tests LoginContext(String, CallbackHandler)
718     */
719    public void testLoginContextStringCallbackHandler() {
720        // Must not accept nulls as CallbackHandler, name
721        // The exception to be thrown is LoginException and not NPE
722        try {
723            new LoginContext(CONFIG_NAME, (CallbackHandler) null);
724            fail("must not pass here");
725        } catch (LoginException _) {
726            // gut
727        }
728        try {
729            new LoginContext(null, new TestCallbackHandler());
730            fail("must not pass here");
731        } catch (LoginException _) {
732            // gut
733        }
734        // additional cleanup to make it PerfTests compatible
735        clear();
736    }
737
738    /**
739     * Tests LoginContext(String, Subject)
740     */
741    public void testLoginContextStringSubject() {
742        // Must not accept nulls as Subject, name
743        // The exception to be thrown is LoginException and not NPE
744        try {
745            new LoginContext(CONFIG_NAME, (Subject) null);
746            fail("must not pass here");
747        } catch (LoginException _) {
748            // gut
749        }
750
751        try {
752            new LoginContext(null, new Subject());
753            fail("must not pass here");
754        } catch (LoginException _) {
755            // gut
756        }
757        // additional cleanup to make it PerfTests compatible
758        clear();
759    }
760
761    /**
762     * Tests LoginContext(String, Subject, CallbackHandler)
763     */
764    public void testLoginContextStringSubjectCallbackHandler() {
765        // The exceptions to be thrown are LoginExceptions and not NPEs
766
767        // Must not accept null as Subject, CallbackHandler, name
768        try {
769            new LoginContext(CONFIG_NAME, (Subject) null,
770                    new TestCallbackHandler());
771            fail("must not pass here");
772        } catch (LoginException _) {
773            // gut
774        }
775
776        try {
777            new LoginContext(CONFIG_NAME, new Subject(), null);
778            fail("must not pass here");
779        } catch (LoginException _) {
780            // gut
781        }
782
783        try {
784            new LoginContext(null, new Subject(), new TestCallbackHandler());
785            fail("must not pass here");
786        } catch (LoginException _) {
787            // gut
788        }
789        // additional cleanup to make it PerfTests compatible
790        clear();
791    }
792
793    /**
794     * Tests LoginContext(String, Subject, CallbackHandler, Configuration)
795     */
796    public void testLoginContextStringSubjectCallbackHandlerConfiguration()
797            throws Exception {
798        // Must accept null everywhere, but at name
799        try {
800            new LoginContext(null, new Subject(), new TestCallbackHandler(),
801                    new TestConfig());
802            fail("must not pass here");
803        } catch (LoginException _) {
804            // gut
805        }
806        new LoginContext(CONFIG_NAME, null, null, null);
807        // additional cleanup to make it PerfTests compatible
808        clear();
809    }
810
811    /**
812     * Tests LoginContext.login()<br>
813     * Make sure that the proper (context) class loader is used.
814     */
815    public void testLogin_minus1() throws Exception {
816        final ArrayList<String> requests = new ArrayList<String>();
817        ClassLoader saveCCL = Thread.currentThread().getContextClassLoader();
818
819        ClassLoader testClassLoader = new ClassLoader() {
820            @Override
821            protected synchronized Class<?> loadClass(String klassName,
822                    boolean resolve) throws ClassNotFoundException {
823                requests.add(klassName);
824                return super.loadClass(klassName, resolve);
825            }
826        };
827        Thread.currentThread().setContextClassLoader(testClassLoader);
828        String klassName = TestConfig
829                .addInstalledRequired("NoSuchClassHere");
830        try {
831            LoginContext lc = new LoginContext(CONFIG_NAME);
832            lc.login();
833            fail("must not pass here");
834        } catch (LoginException ex) {
835            // gut
836        } finally {
837            Thread.currentThread().setContextClassLoader(saveCCL);
838        }
839        // If failed, then it seems, that wrong (not context) class loader was
840        // used - the class was not requested to load
841        assertTrue(requests.contains(klassName));
842        // additional cleanup to make it PerfTests compatible
843        clear();
844    }
845
846    /**
847     * Tests LoginContext.login()<br>
848     * Second attempt to login() on context already logged, must be successful.<br>
849     * This is how the RI works.
850     */
851    public void testLogin_00() throws Exception {
852        TestConfig.addInstalledSufficient("TestLoginModule_Success");
853        LoginContext lc = new LoginContext(CONFIG_NAME);
854        lc.login();
855        lc.login();
856        // additional cleanup to make it PerfTests compatible
857        clear();
858    }
859
860    /**
861     * Tests LoginContext.login()<br>
862     * If no Subject provided, then new Subject created and this subject is
863     * used for all subsequent operations.
864     */
865    public void testLogin_01() throws Exception {
866        TestConfig.addInstalledSufficient("TestLoginModule_Success");
867        LoginContext lc = new LoginContext(CONFIG_NAME);
868        lc.login();
869        Subject subj0 = lc.getSubject();
870        assertNotNull(subj0);
871        lc.logout();
872        //
873        lc.login();
874        Subject subj1 = lc.getSubject();
875        assertSame(subj0, subj1);
876        // additional cleanup to make it PerfTests compatible
877        clear();
878    }
879
880    /**
881     * Tests LoginContext.login()<br>
882     * init() must be called only once.
883     */
884    public void testLogin_02_0() throws Exception {
885        TestConfig.addInstalledSufficient("TestLoginModule_Success");
886        LoginContext lc = new LoginContext(CONFIG_NAME);
887        lc.login();
888        assertEquals(1, TestLoginModule.size());
889        assertTrue(TestLoginModule.get(0).initCalled);
890        assertTrue(TestLoginModule.get(0).loginCalled);
891
892        lc.logout();
893        assertTrue(TestLoginModule.get(0).logoutCalled);
894        //
895        TestLoginModule.get(0).loginCalled = false;
896        TestLoginModule.get(0).initCalled = false;
897
898        lc.login();
899
900        assertEquals(1, TestLoginModule.size());
901        assertTrue(TestLoginModule.get(0).loginCalled);
902        assertFalse(TestLoginModule.get(0).initCalled);
903        // additional cleanup to make it PerfTests compatible
904        clear();
905    }
906
907    /**
908     * Tests LoginContext.login()<br>
909     * init() must be called only once - even if it fails first time.
910     */
911    public void testLogin_02_1() throws Exception {
912        TestConfig.addInstalledSufficient("TestLoginModule");
913        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_INIT;
914
915        LoginContext lc = new LoginContext(CONFIG_NAME);
916        try {
917            lc.login();
918            fail("must not pass here");
919        } catch (LoginException _) {
920            //ok
921        }
922
923        assertEquals(1, TestLoginModule.size());
924        assertTrue(TestLoginModule.get(0).initCalled);
925        assertFalse(TestLoginModule.get(0).loginCalled);
926        assertFalse(TestLoginModule.get(0).commitCalled);
927        assertTrue(TestLoginModule.get(0).abortCalled);
928        assertFalse(TestLoginModule.get(0).logoutCalled);
929
930        lc.logout();
931
932        TestLoginModule.get(0).initCalled = false;
933        TestLoginModule.get(0).loginCalled = false;
934        TestLoginModule.get(0).commitCalled = false;
935        TestLoginModule.get(0).abortCalled = false;
936        TestLoginModule.get(0).logoutCalled = false;
937
938        TestLoginModule.staticMask = 0;
939        lc.login();
940
941        assertEquals(1, TestLoginModule.size());
942        assertFalse(TestLoginModule.get(0).initCalled);
943        assertTrue(TestLoginModule.get(0).loginCalled);
944        assertTrue(TestLoginModule.get(0).commitCalled);
945        assertFalse(TestLoginModule.get(0).abortCalled);
946        assertFalse(TestLoginModule.get(0).logoutCalled);
947        // additional cleanup to make it PerfTests compatible
948        clear();
949    }
950
951    /**
952     * Tests LoginContext.login()<br>
953     * If any module not found, then overall attempt must fail.
954     * If a module fails during it's ctor/init/commit - it must be processed
955     * the same way as if it were failing during it's login().<br>
956     * Various combinations are checked.
957     */
958    public void testLogin_03() throws Exception {
959        // A little bit sophisticated structure
960        // if variant[i][0] == -1 then:
961        // 	- it starts a new variant
962        //	- variants[i][1] contains description for the variant started
963        //	- variants[i][2] contains expected result (true - success, false-failure) for the variant
964        Object[][] variants = new Object[][] {
965                //
966                { new Integer(-1), "[if no class found - overall failure]",
967                        Boolean.FALSE },
968                { new Integer(OPTIONAL), "no such class" },
969                { new Integer(SUFFICIENT), "TestLoginModule_Success" },
970
971                { new Integer(-1),
972                        "[ctor failure treated as failed login() - 0] ",
973                        Boolean.TRUE },
974                { new Integer(OPTIONAL), "TestLoginModule_CtorFails" },
975                { new Integer(SUFFICIENT), "TestLoginModule_Success" },
976
977                { new Integer(-1),
978                        "[ctor failure treated as failed login() - 1] ",
979                        Boolean.FALSE },
980                { new Integer(REQUISITE), "TestLoginModule_CtorFails" },
981                { new Integer(SUFFICIENT), "TestLoginModule_Success" },
982
983                { new Integer(-1),
984                        "[init failure treated as failed login() - 0]",
985                        Boolean.TRUE },
986                { new Integer(OPTIONAL), "TestLoginModule_InitFails" },
987                { new Integer(SUFFICIENT), "TestLoginModule_Success" },
988
989                { new Integer(-1),
990                        "[init failure treated as failed login() - 1]",
991                        Boolean.FALSE },
992                { new Integer(REQUIRED), "TestLoginModule_InitFails" },
993                { new Integer(SUFFICIENT), "TestLoginModule_Success" },
994
995                { new Integer(-1), "simple testcase 0", Boolean.TRUE },
996                { new Integer(OPTIONAL), "TestLoginModule_Fail" },
997                { new Integer(SUFFICIENT), "TestLoginModule_Success" },
998
999                { new Integer(-1), "simple testcase 1", Boolean.FALSE },
1000                { new Integer(REQUIRED), "no such class" },
1001                { new Integer(SUFFICIENT), "TestLoginModule_Success" },
1002                { new Integer(OPTIONAL), "TestLoginModule_Success" },
1003
1004                { new Integer(-1), "simple testcase 2", Boolean.FALSE },
1005                { new Integer(REQUISITE), "no such class" },
1006                { new Integer(SUFFICIENT), "TestLoginModule_Success" },
1007                { new Integer(OPTIONAL), "TestLoginModule_Success" },
1008
1009                { new Integer(-1), "simple testcase 3", Boolean.FALSE },
1010                { new Integer(SUFFICIENT), "no such class" },
1011                { new Integer(OPTIONAL), "TestLoginModule_Success" },
1012                { new Integer(OPTIONAL), "TestLoginModule_Success" },
1013
1014                { new Integer(-1), "simple testcase 4", Boolean.FALSE },
1015                { new Integer(REQUIRED), "TestLoginModule_InitFails" },
1016                { new Integer(SUFFICIENT), "TestLoginModule_Success" },
1017                { new Integer(OPTIONAL), "TestLoginModule_Success" },
1018
1019                { new Integer(-1), "simple testcase 5", Boolean.TRUE },
1020                { new Integer(OPTIONAL), "TestLoginModule_InitFails" },
1021                { new Integer(SUFFICIENT), "TestLoginModule_Success" },
1022                { new Integer(OPTIONAL), "TestLoginModule_Failing" },
1023
1024                { new Integer(-1), "simple testcase 6", Boolean.TRUE },
1025                { new Integer(REQUISITE), "TestLoginModule_Success" },
1026                { new Integer(SUFFICIENT), "TestLoginModule_Success" },
1027                { new Integer(OPTIONAL), "TestLoginModule_Failing" },
1028
1029                { new Integer(-1), "simple testcase 7", Boolean.FALSE },
1030                { new Integer(REQUIRED), "TestLoginModule_CtorFails" },
1031                { new Integer(SUFFICIENT), "TestLoginModule_Success" },
1032                { new Integer(OPTIONAL), "TestLoginModule_Success" },
1033
1034                { new Integer(-1), "simple testcase 8", Boolean.TRUE },
1035                { new Integer(OPTIONAL), "TestLoginModule_CtorFails" },
1036                { new Integer(SUFFICIENT), "TestLoginModule_Success" },
1037                { new Integer(OPTIONAL), "TestLoginModule_Failing" },
1038
1039                { new Integer(-1), "simple testcase 9", Boolean.TRUE },
1040                { new Integer(OPTIONAL), "TestLoginModule_Success" },
1041                { new Integer(SUFFICIENT), "TestLoginModule_CtorFails" },
1042                { new Integer(OPTIONAL), "TestLoginModule_Success" },
1043
1044                { new Integer(-1), "simple testcase A", Boolean.TRUE },
1045                { new Integer(OPTIONAL), "TestLoginModule_Success" },
1046                { new Integer(SUFFICIENT), "TestLoginModule_CommitFails" },
1047                { new Integer(OPTIONAL), "TestLoginModule_Success" },
1048
1049                { new Integer(-1), "simple testcase B", Boolean.TRUE },
1050                { new Integer(OPTIONAL), "TestLoginModule_Success" },
1051                { new Integer(OPTIONAL), "TestLoginModule_CommitFails" },
1052                { new Integer(OPTIONAL), "TestLoginModule_Success" }, };
1053
1054        TestConfig.clear();
1055        boolean expectedResult = ((Boolean) variants[0][2]).booleanValue();
1056        String caseName = variants[0][1].toString();
1057
1058        int startIndex = 0;
1059        for (int i = 0; i < variants.length; i++) {
1060            int flag = ((Integer) variants[i][0]).intValue();
1061            if (flag == -1 || (i == variants.length - 1)) {
1062                if (i != 0) {
1063                    LoginContext lc = new LoginContext(CONFIG_NAME);
1064                    try {
1065                        lc.login();
1066                        if (!expectedResult) {
1067                            fail("must not pass here: caseStart@" + startIndex
1068                                    + "; desc=" + caseName);
1069                        }
1070                    } catch (LoginException ex) {
1071                        if (expectedResult) {
1072                            fail("must not pass here: caseStart@" + startIndex
1073                                    + "; desc=" + caseName);
1074                        }
1075                    }
1076                }
1077                if (i != variants.length - 1) {
1078                    caseName = variants[i][1].toString();
1079                    expectedResult = ((Boolean) variants[i][2]).booleanValue();
1080                }
1081                TestConfig.clear();
1082            } else {
1083                TestConfig.addInstalled(flag, variants[i][1].toString());
1084            }
1085        }
1086        // additional cleanup to make it PerfTests compatible
1087        clear();
1088    }
1089
1090    /**
1091     * Tests LoginContext.login()<br>
1092     * If module fails during it's ctor, then it must be
1093     * created/initialized/logged next time.
1094     */
1095    public void testLogin_04() throws Exception {
1096        TestConfig.addInstalledRequired("TestLoginModule");
1097        assertEquals(0, TestLoginModule.size());
1098        LoginContext lc = new LoginContext(CONFIG_NAME);
1099        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_CTOR;
1100        try {
1101            lc.login();
1102            fail("must not pass here");
1103        } catch (LoginException ex) {
1104            // ok
1105        }
1106        assertEquals(0, TestLoginModule.size());
1107        // fail nowhere
1108        TestLoginModule.staticMask = 0;
1109        lc.login(); // must be successful now
1110        assertEquals(1, TestLoginModule.size());
1111        assertTrue(TestLoginModule.get(0).initCalled);
1112        assertTrue(TestLoginModule.get(0).loginCalled);
1113        assertTrue(TestLoginModule.get(0).commitCalled);
1114        // additional cleanup to make it PerfTests compatible
1115        clear();
1116    }
1117
1118    /**
1119     * Tests LoginContext.login()<br>
1120     * If module fails during init():
1121     * 		- its login() must NOT be called
1122     * 		- its abort() must be called anyway.
1123     */
1124    public void testLogin_05() throws Exception {
1125        TestConfig.addInstalledRequired("TestLoginModule_InitFails");
1126        LoginContext lc = new LoginContext(CONFIG_NAME);
1127        try {
1128            lc.login();
1129            fail("must not pass here");
1130        } catch (LoginException ex) {
1131        }
1132
1133        assertFalse(TestLoginModule.get(0).loginCalled);
1134        assertTrue(TestLoginModule.get(0).abortCalled);
1135        // additional cleanup to make it PerfTests compatible
1136        clear();
1137    }
1138
1139    /**
1140     * Tests LoginContext.login()<br>
1141     * If module fails during init():
1142     * 		- its login() must NOT be called
1143     * 		- its login() MUST be called on the next attempt
1144     */
1145    public void testLogin_06() throws Exception {
1146        TestConfig.addInstalledRequired("TestLoginModule");
1147        LoginContext lc = new LoginContext(CONFIG_NAME);
1148        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_INIT;
1149        try {
1150            lc.login();
1151            fail("must not pass here");
1152        } catch (LoginException ex) {
1153            // ok
1154        }
1155        assertEquals(1, TestLoginModule.size());
1156        assertFalse(TestLoginModule.get(0).loginCalled);
1157        assertFalse(TestLoginModule.get(0).commitCalled); // self check
1158        // fail nowhere
1159        TestLoginModule.staticMask = 0;
1160        lc.login(); // must be successful now
1161        // no new module must be created
1162        assertEquals(1, TestLoginModule.size());
1163        assertTrue(TestLoginModule.get(0).loginCalled);
1164        assertTrue(TestLoginModule.get(0).commitCalled);
1165        // additional cleanup to make it PerfTests compatible
1166        clear();
1167    }
1168
1169    /**
1170     * Tests LoginContext.login()<br>
1171     * If no class found, then following modules must not be instantiated
1172     */
1173    public void testLogin_07() throws Exception {
1174        TestConfig.addInstalledOptional("TestLoginModule_Success");
1175        TestConfig.addInstalledOptional("no such class");
1176        TestConfig.addInstalledOptional("TestLoginModule_Success");
1177        LoginContext lc = new LoginContext(CONFIG_NAME);
1178        try {
1179            lc.login();
1180            fail("must not pass here");
1181        } catch (LoginException ex) {
1182            //ok
1183        }
1184        assertEquals(1, TestLoginModule.size());
1185        assertTrue(TestLoginModule.get(0).loginCalled);
1186        assertTrue(TestLoginModule.get(0).abortCalled);
1187        assertFalse(TestLoginModule.get(0).commitCalled);
1188        // additional cleanup to make it PerfTests compatible
1189        clear();
1190    }
1191
1192    /**
1193     * Tests LoginContext.login()<br>
1194     * RuntimeException-s (if any) must be handled and then LoginException must
1195     * be thrown
1196     */
1197    public void testLogin_08_0() throws Exception {
1198        TestConfig.addInstalledOptional("TestLoginModule");
1199        TestLoginModule.staticRE = new RuntimeException("ctor");
1200        LoginContext lc = new LoginContext(CONFIG_NAME);
1201        //
1202        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_CTOR;
1203        try {
1204            lc.login();
1205            fail("must not pass here");
1206        } catch (LoginException ex) {
1207            // ok. the RI does not initCause() with a given RuntimeException
1208        }
1209        // additional cleanup to make it PerfTests compatible
1210        clear();
1211    }
1212
1213    /**
1214     * Tests LoginContext.login()<br>
1215     * RuntimeException-s (if any) must be handled and then LoginException must
1216     * be thrown
1217     */
1218    public void testLogin_08_1() throws Exception {
1219        TestConfig.addInstalledOptional("TestLoginModule");
1220        TestLoginModule.staticRE = new RuntimeException("init");
1221        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_INIT;
1222        LoginContext lc = new LoginContext(CONFIG_NAME);
1223        try {
1224            lc.login();
1225            fail("must not pass here");
1226        } catch (LoginException ex) {
1227            // ok. the RI does not initCause() with a given RuntimeException
1228        }
1229        // additional cleanup to make it PerfTests compatible
1230        clear();
1231    }
1232
1233    /**
1234     * Tests LoginContext.login()<br>
1235     * RuntimeException-s (if any) must be handled and then LoginException must be thrown
1236     */
1237    public void testLogin_08_2() throws Exception {
1238        TestConfig.addInstalledOptional("TestLoginModule");
1239        TestLoginModule.staticRE = new RuntimeException("login");
1240        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_LOGIN;
1241        LoginContext lc = new LoginContext(CONFIG_NAME);
1242        try {
1243            lc.login();
1244            fail("must not pass here");
1245        } catch (LoginException ex) {
1246            // ok. the RI does not initCause() with a given RuntimeException
1247        }
1248        // additional cleanup to make it PerfTests compatible
1249        clear();
1250    }
1251
1252    /**
1253     * Tests LoginContext.login()<br>
1254     * RuntimeException-s (if any) must be handled and then LoginException must be thrown
1255     */
1256    public void testLogin_08_3() throws Exception {
1257        TestConfig.addInstalledOptional("TestLoginModule");
1258        TestLoginModule.staticRE = new RuntimeException("commit");
1259        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_COMMIT;
1260        LoginContext lc = new LoginContext(CONFIG_NAME);
1261        try {
1262            lc.login();
1263            fail("must not pass here");
1264        } catch (LoginException ex) {
1265            // ok. the RI does not initCause() with a given RuntimeException
1266        }
1267        // additional cleanup to make it PerfTests compatible
1268        clear();
1269    }
1270
1271    /**
1272     * Tests LoginContext.login()<br>
1273     * Error-s (if any) must be handled and wrapped into LoginException
1274     */
1275    public void testLogin_09_0() throws Exception {
1276        TestConfig.addInstalledOptional("TestLoginModule");
1277        TestLoginModule.staticERR = new Error("ctor");
1278        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_CTOR;
1279        LoginContext lc = new LoginContext(CONFIG_NAME);
1280        //
1281        try {
1282            lc.login();
1283            fail("must not pass here");
1284        } catch (LoginException ex) {
1285            // ok. the RI does not initCause() with a given RuntimeException
1286        }
1287        // additional cleanup to make it PerfTests compatible
1288        clear();
1289    }
1290
1291    /**
1292     * Tests LoginContext.login()<br>
1293     * Error-s (if any) must be handled and wrapped into LoginException
1294     */
1295    public void testLogin_09_1() throws Exception {
1296        TestConfig.addInstalledOptional("TestLoginModule");
1297        TestLoginModule.staticERR = new Error("init");
1298        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_INIT;
1299        LoginContext lc = new LoginContext(CONFIG_NAME);
1300        try {
1301            lc.login();
1302            fail("must not pass here");
1303        } catch (LoginException ex) {
1304            // ok. the RI does not initCause() with a given RuntimeException
1305        }
1306        // additional cleanup to make it PerfTests compatible
1307        clear();
1308    }
1309
1310    /**
1311     * Tests LoginContext.login()<br>
1312     * Error-s (if any) must be handled and wrapped into LoginException
1313     */
1314    public void testLogin_09_2() throws Exception {
1315        TestConfig.addInstalledOptional("TestLoginModule");
1316        TestLoginModule.staticERR = new Error("login");
1317        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_LOGIN;
1318        LoginContext lc = new LoginContext(CONFIG_NAME);
1319        try {
1320            lc.login();
1321            fail("must not pass here");
1322        } catch (LoginException ex) {
1323            // ok. the RI does not initCause() with a given RuntimeException
1324        }
1325        // additional cleanup to make it PerfTests compatible
1326        clear();
1327    }
1328
1329    /**
1330     * Tests LoginContext.login()<br>
1331     * Error-s (if any) must be handled and wrapped into LoginException
1332     */
1333    public void testLogin_09_3() throws Exception {
1334        TestConfig.addInstalledOptional("TestLoginModule");
1335        TestLoginModule.staticERR = new Error("commit");
1336        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_COMMIT;
1337        LoginContext lc = new LoginContext(CONFIG_NAME);
1338        try {
1339            lc.login();
1340            fail("must not pass here");
1341        } catch (LoginException ex) {
1342            // ok. the RI does not initCause() with a given RuntimeException
1343        }
1344        // additional cleanup to make it PerfTests compatible
1345        clear();
1346    }
1347
1348    /**
1349     * Tests LoginContext.login()<br>
1350     * A failure during commit() must be treated exactly as a failure during
1351     * login()/whatever
1352     */
1353    public void testLogin_0A_0() throws Exception {
1354        TestConfig.addInstalledRequired("TestLoginModule_Success");
1355        TestConfig.addInstalledOptional("TestLoginModule");
1356        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_COMMIT;
1357        LoginContext lc = new LoginContext(CONFIG_NAME);
1358
1359        lc.login();
1360
1361        assertEquals(2, TestLoginModule.size());
1362        //
1363        assertTrue(TestLoginModule.get(0).loginCalled);
1364        assertTrue(TestLoginModule.get(0).commitCalled);
1365        assertFalse(TestLoginModule.get(0).abortCalled);
1366        //
1367        assertTrue(TestLoginModule.get(1).loginCalled);
1368        assertTrue(TestLoginModule.get(1).commitCalled);
1369        assertFalse(TestLoginModule.get(1).abortCalled);
1370        // additional cleanup to make it PerfTests compatible
1371        clear();
1372    }
1373
1374    /**
1375     * Tests LoginContext.login()<br>
1376     * see testLogin_0A_0().
1377     */
1378    public void testLogin_0A_1() throws Exception {
1379        TestConfig.addInstalledOptional("TestLoginModule_Success");
1380        TestConfig.addInstalledRequired("TestLoginModule");
1381        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_COMMIT;
1382        TestLoginModule.staticLE = new LoginException();
1383        LoginContext lc = new LoginContext(CONFIG_NAME);
1384        try {
1385            lc.login();
1386            fail("must not pass here");
1387        } catch (LoginException le) {
1388            assertSame(TestLoginModule.staticLE, le);
1389        }
1390
1391        assertEquals(2, TestLoginModule.size());
1392        //
1393        assertTrue(TestLoginModule.get(0).loginCalled);
1394        assertTrue(TestLoginModule.get(0).commitCalled);
1395        assertTrue(TestLoginModule.get(0).abortCalled);
1396        //
1397        assertTrue(TestLoginModule.get(1).loginCalled);
1398        assertTrue(TestLoginModule.get(1).commitCalled);
1399        assertTrue(TestLoginModule.get(1).abortCalled);
1400        // additional cleanup to make it PerfTests compatible
1401        clear();
1402    }
1403
1404    /**
1405     * Tests LoginContext.login()<br>
1406     * A failure during commit() must not stop further commit()s get called.
1407     */
1408    public void testLogin_0B() throws Exception {
1409        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_COMMIT;
1410        TestConfig.addInstalledRequired("TestLoginModule");
1411        TestConfig.addInstalledOptional("TestLoginModule_Success");
1412        TestConfig.addInstalledOptional("TestLoginModule_Success");
1413        LoginContext lc = new LoginContext(CONFIG_NAME);
1414
1415        try {
1416            lc.login();
1417            fail("must not pass here");
1418        } catch (LoginException _) {
1419            // gut
1420        }
1421
1422        assertEquals(3, TestLoginModule.size());
1423        //
1424        assertTrue(TestLoginModule.get(0).loginCalled);
1425        assertTrue(TestLoginModule.get(0).commitCalled);
1426        //
1427        assertTrue(TestLoginModule.get(1).loginCalled);
1428        assertTrue(TestLoginModule.get(1).commitCalled);
1429        //
1430        assertTrue(TestLoginModule.get(2).loginCalled);
1431        assertTrue(TestLoginModule.get(2).commitCalled);
1432        // additional cleanup to make it PerfTests compatible
1433        clear();
1434    }
1435
1436    /**
1437     * Tests LoginContext.login()<br>
1438     * A failure during abort() must not stop further abort()s get called.
1439     */
1440    public void testLogin_0C() throws Exception {
1441        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_ABORT
1442                | TestLoginModule.FAIL_AT_COMMIT;
1443        TestConfig.addInstalledRequired("TestLoginModule");
1444        TestConfig.addInstalledOptional("TestLoginModule_Success");
1445        TestConfig.addInstalledOptional("TestLoginModule_Success");
1446        LoginContext lc = new LoginContext(CONFIG_NAME);
1447
1448        try {
1449            lc.login();
1450            fail("must not pass here");
1451        } catch (LoginException _) {
1452            // gut
1453        }
1454
1455        assertEquals(3, TestLoginModule.size());
1456        //
1457        assertTrue(TestLoginModule.get(0).loginCalled);
1458        assertTrue(TestLoginModule.get(0).commitCalled);
1459        assertTrue(TestLoginModule.get(0).abortCalled);
1460        //
1461        assertTrue(TestLoginModule.get(1).loginCalled);
1462        assertTrue(TestLoginModule.get(1).commitCalled);
1463        assertTrue(TestLoginModule.get(1).abortCalled);
1464        //
1465        assertTrue(TestLoginModule.get(2).loginCalled);
1466        assertTrue(TestLoginModule.get(2).commitCalled);
1467        assertTrue(TestLoginModule.get(2).abortCalled);
1468        // additional cleanup to make it PerfTests compatible
1469        clear();
1470    }
1471
1472    /**
1473     * Tests LoginContext.login()<br>
1474     * If any a module returns false from commit() - then nothing happens.
1475     */
1476    public void testLogin_0D() throws Exception {
1477        TestConfig.addInstalledRequired("TestLoginModule_Success");
1478        TestLoginModule.staticMask = TestLoginModule.FALSE_AT_COMMIT;
1479        TestConfig.addInstalledRequired("TestLoginModule");
1480        LoginContext lc = new LoginContext(CONFIG_NAME);
1481
1482        lc.login();
1483
1484        assertEquals(2, TestLoginModule.size());
1485        //
1486        assertTrue(TestLoginModule.get(0).loginCalled);
1487        assertTrue(TestLoginModule.get(0).commitCalled);
1488        assertFalse(TestLoginModule.get(0).abortCalled);
1489        //
1490        assertTrue(TestLoginModule.get(1).loginCalled);
1491        assertTrue(TestLoginModule.get(1).commitCalled);
1492        assertFalse(TestLoginModule.get(1).abortCalled);
1493        // additional cleanup to make it PerfTests compatible
1494        clear();
1495    }
1496
1497    /**
1498     * Tests LoginContext.login()<br>
1499     * If any REQUIRED module returns false from login() - this does
1500     * not break the overall attempt.<br>
1501     * It sounds odd, but its commit() method will also be called.
1502     */
1503    public void testLogin_0E_0() throws Exception {
1504        TestConfig.addInstalledRequired("TestLoginModule_Success");
1505        TestLoginModule.staticMask = TestLoginModule.FALSE_AT_LOGIN;
1506        TestConfig.addInstalledRequired("TestLoginModule");
1507        LoginContext lc = new LoginContext(CONFIG_NAME);
1508
1509        lc.login();
1510
1511        assertEquals(2, TestLoginModule.size());
1512        //
1513        assertTrue(TestLoginModule.get(0).initCalled);
1514        assertTrue(TestLoginModule.get(0).loginCalled);
1515        assertTrue(TestLoginModule.get(0).commitCalled);
1516        assertFalse(TestLoginModule.get(0).abortCalled);
1517        //
1518        assertTrue(TestLoginModule.get(1).initCalled);
1519        assertTrue(TestLoginModule.get(1).loginCalled);
1520        assertTrue(TestLoginModule.get(1).commitCalled);
1521        assertFalse(TestLoginModule.get(1).abortCalled);
1522        // additional cleanup to make it PerfTests compatible
1523        clear();
1524    }
1525
1526    /**
1527     * Tests LoginContext.login()<br>
1528     * If any REQUISITE module returns false from login() - this does
1529     * not break the overall attempt.<br>
1530     * It sounds odd, but its commit() method will be called anyway.
1531     */
1532    public void testLogin_0E_1() throws Exception {
1533        TestConfig.addInstalledRequisite("TestLoginModule_Success");
1534        TestLoginModule.staticMask = TestLoginModule.FALSE_AT_LOGIN;
1535        TestConfig.addInstalledRequisite("TestLoginModule");
1536        LoginContext lc = new LoginContext(CONFIG_NAME);
1537
1538        lc.login();
1539
1540        assertEquals(2, TestLoginModule.size());
1541        //
1542        assertTrue(TestLoginModule.get(0).initCalled);
1543        assertTrue(TestLoginModule.get(0).loginCalled);
1544        assertTrue(TestLoginModule.get(0).commitCalled);
1545        assertFalse(TestLoginModule.get(0).abortCalled);
1546        //
1547        assertTrue(TestLoginModule.get(1).initCalled);
1548        assertTrue(TestLoginModule.get(1).loginCalled);
1549        assertTrue(TestLoginModule.get(1).commitCalled);
1550        assertFalse(TestLoginModule.get(1).abortCalled);
1551        // additional cleanup to make it PerfTests compatible
1552        clear();
1553    }
1554
1555    /**
1556     * Tests LoginContext.login()<br>
1557     * If any REQUIRED module fails during its login() -
1558     * then its abort() gets called anyway.
1559     */
1560    public void testLogin_0F() throws Exception {
1561        TestConfig.addInstalledRequired("TestLoginModule_Success");
1562        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_LOGIN;
1563        TestConfig.addInstalledRequired("TestLoginModule");
1564        LoginContext lc = new LoginContext(CONFIG_NAME);
1565
1566        try {
1567            lc.login();
1568            fail("must not pass here");
1569        } catch (LoginException ex) {
1570            // gut
1571        }
1572
1573        assertEquals(2, TestLoginModule.size());
1574        //
1575        assertTrue(TestLoginModule.get(0).initCalled);
1576        assertTrue(TestLoginModule.get(0).loginCalled);
1577        assertFalse(TestLoginModule.get(0).commitCalled);
1578        assertTrue(TestLoginModule.get(0).abortCalled);
1579        //
1580        assertTrue(TestLoginModule.get(1).initCalled);
1581        assertTrue(TestLoginModule.get(1).loginCalled);
1582        assertFalse(TestLoginModule.get(1).commitCalled);
1583        assertTrue(TestLoginModule.get(1).abortCalled);
1584        // additional cleanup to make it PerfTests compatible
1585        clear();
1586    }
1587
1588    /**
1589     * Tests LoginContext.login()<br>
1590     * RI investigation: check if an exception thrown from abort() method gets
1591     * rethrown, or a new LoginException is created.
1592     */
1593    public void testLogin_10() throws Exception {
1594        TestLoginModule.staticMask = TestLoginModule.FALSE_AT_LOGIN
1595                | TestLoginModule.FAIL_AT_ABORT;
1596
1597        TestLoginModule.staticLE = new LoginException();
1598
1599        TestConfig.addInstalledRequired("TestLoginModule");
1600        LoginContext lc = new LoginContext(CONFIG_NAME);
1601
1602        try {
1603            lc.login();
1604        } catch (LoginException ex) {
1605            // RI does not rethrow this exception, but I do.
1606            // Anyway, the login() failed - that is expected result
1607            // assertSame( ex, TestLoginModule.staticLE);
1608        }
1609
1610        assertEquals(1, TestLoginModule.size());
1611        //
1612        assertTrue(TestLoginModule.get(0).initCalled);
1613        assertTrue(TestLoginModule.get(0).loginCalled);
1614        assertFalse(TestLoginModule.get(0).commitCalled);
1615        assertTrue(TestLoginModule.get(0).abortCalled);
1616        // additional cleanup to make it PerfTests compatible
1617        clear();
1618    }
1619
1620    /**
1621     * Tests LoginContext.logout()<br>
1622     * Calling logout() simply invokes logout() to be called.
1623     */
1624    public void testLogout_00_0() throws Exception {
1625        // No modules configured - must fail in both login() and logout()
1626        LoginContext lc = new LoginContext(CONFIG_NAME);
1627        try {
1628            lc.login();
1629            fail("must not pass here");
1630        } catch (LoginException _) {
1631            // gut
1632        }
1633
1634        try {
1635            lc.logout();
1636            fail("must not pass here");
1637        } catch (LoginException _) {
1638            // gut
1639        }
1640        // additional cleanup to make it PerfTests compatible
1641        clear();
1642    }
1643
1644    /**
1645     * Tests LoginContext.logout()<br>
1646     * Calling logout() on a context that had login() called, but is still not
1647     * logged in must be successful - as it just invokes logout() for modules
1648     */
1649    public void testLogout_00_1() throws Exception {
1650        TestConfig.addInstalledRequired("TestLoginModule");
1651        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_LOGIN;
1652        LoginContext lc = new LoginContext(CONFIG_NAME);
1653        try {
1654            lc.login();
1655            fail("must not pass here");
1656        } catch (LoginException _) {
1657            // gut
1658        }
1659        lc.logout();
1660        // additional cleanup to make it PerfTests compatible
1661        clear();
1662    }
1663
1664    /**
1665     * Tests LoginContext.logout()<br>
1666     * Calling logout() on a context which had no login() called - must fail.
1667     */
1668    public void testLogout_00_2() throws Exception {
1669        TestConfig.addInstalledRequired("TestLoginModule_Success");
1670        LoginContext lc = new LoginContext(CONFIG_NAME);
1671        try {
1672            lc.logout();
1673            fail("must not pass here");
1674        } catch (LoginException _) {
1675            // gut
1676        }
1677        assertEquals(0, TestLoginModule.size());
1678        // additional cleanup to make it PerfTests compatible
1679        clear();
1680    }
1681
1682    /**
1683     * Tests LoginContext.logout()<br>
1684     * An exception thrown from inside logout() must not stop calls to other logout()s.
1685     */
1686    public void testLogout_01() throws Exception {
1687        TestConfig.addInstalledRequired("TestLoginModule");
1688        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_LOGOUT;
1689        TestConfig.addInstalledRequired("TestLoginModule_Success");
1690
1691        LoginContext lc = new LoginContext(CONFIG_NAME);
1692        lc.login();
1693        try {
1694            lc.logout();
1695            fail("must not pass here");
1696        } catch (LoginException _) {
1697            // gut
1698        }
1699        assertEquals(2, TestLoginModule.size());
1700        assertTrue(TestLoginModule.get(0).logoutCalled);
1701        assertTrue(TestLoginModule.get(1).logoutCalled);
1702        // additional cleanup to make it PerfTests compatible
1703        clear();
1704    }
1705
1706    /**
1707     * Tests LoginContext.logout()<br>
1708     * It must rethrow LoginException thrown from the logout()
1709     */
1710    public void testLogout_02() throws Exception {
1711        TestConfig.addInstalledRequired("TestLoginModule");
1712        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_LOGOUT;
1713        TestLoginModule.staticLE = new LoginException();
1714
1715        LoginContext lc = new LoginContext(CONFIG_NAME);
1716        lc.login();
1717        try {
1718            lc.logout();
1719            fail("must not pass here");
1720        } catch (LoginException le) {
1721            assertSame(TestLoginModule.staticLE, le);
1722        }
1723        // additional cleanup to make it PerfTests compatible
1724        clear();
1725    }
1726
1727    /**
1728     * Tests LoginContext.logout()<br>
1729     * It must wrap RuntimeExceptions into LoginException
1730     */
1731    public void testLogout_03() throws Exception {
1732        TestConfig.addInstalledRequired("TestLoginModule");
1733        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_LOGOUT;
1734        TestLoginModule.staticRE = new RuntimeException();
1735
1736        LoginContext lc = new LoginContext(CONFIG_NAME);
1737        lc.login();
1738        try {
1739            lc.logout();
1740            fail("must not pass here");
1741        } catch (LoginException le) {
1742            // ok
1743        }
1744        // additional cleanup to make it PerfTests compatible
1745        clear();
1746    }
1747
1748    /**
1749     * Tests LoginContext.logout()<br>
1750     * It must wrap Errors into LoginException
1751     */
1752    public void testLogout_04() throws Exception {
1753        TestConfig.addInstalledRequired("TestLoginModule");
1754        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_LOGOUT;
1755        TestLoginModule.staticERR = new Error();
1756
1757        LoginContext lc = new LoginContext(CONFIG_NAME);
1758        lc.login();
1759        try {
1760            lc.logout();
1761            fail("must not pass here");
1762        } catch (LoginException le) {
1763            // ok
1764        }
1765        // additional cleanup to make it PerfTests compatible
1766        clear();
1767    }
1768
1769    /**
1770     * Tests LoginContext.getSubject()<br>
1771     * Must return null if no subject was provided by user an no login attempt
1772     * was made.
1773     */
1774    public void testGetSubject_00() throws Exception {
1775        LoginContext lc = new LoginContext(CONFIG_NAME);
1776        assertNull(lc.getSubject());
1777        // additional cleanup to make it PerfTests compatible
1778        clear();
1779    }
1780
1781    /**
1782     * Tests LoginContext.getSubject()<br>
1783     * Must return subject created after successful login.
1784     */
1785    public void testGetSubject_01() throws Exception {
1786        TestConfig.addInstalledRequired("TestLoginModule_Success");
1787        LoginContext lc = new LoginContext(CONFIG_NAME);
1788        lc.login();
1789        assertNotNull(lc.getSubject());
1790        // additional cleanup to make it PerfTests compatible
1791        clear();
1792    }
1793
1794    /**
1795     * Tests LoginContext.getSubject()<br>
1796     * Must return null until successful login().
1797     */
1798    public void testGetSubject_02() throws Exception {
1799        TestConfig.addInstalledRequired("TestLoginModule");
1800        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_LOGIN;
1801        LoginContext lc = new LoginContext(CONFIG_NAME);
1802        assertNull(lc.getSubject());
1803        try {
1804            lc.login();
1805        } catch (LoginException _) {
1806            // ok
1807        }
1808        assertNull(lc.getSubject());
1809        TestLoginModule.staticMask = 0;
1810        lc.login();
1811        Subject saveSubject = lc.getSubject();
1812        assertNotNull(saveSubject);
1813        // Must return the same subject on subsequent calls
1814        lc.logout();
1815        lc.login();
1816        assertSame(lc.getSubject(), saveSubject);
1817        // additional cleanup to make it PerfTests compatible
1818        clear();
1819    }
1820
1821    /**
1822     * Tests context usage.
1823     * Case 0: If no Config provided by user, then LoginContext uses
1824     * its own context to invoke LoginModule's methods.
1825     */
1826    public void testContextUsage_0() throws Exception {
1827        Subject dummySubj = new Subject();
1828        final DomainCombiner dc = new SubjectDomainCombiner(dummySubj);
1829        AccessControlContext acc = new AccessControlContext(AccessController
1830                .getContext(), dc);
1831        PrivilegedExceptionAction<Void> action = new PrivilegedExceptionAction<Void>() {
1832            public Void run() throws Exception {
1833                implTestContextUsage(true, dc);
1834                return null;
1835            }
1836        };
1837        AccessController.doPrivileged(action, acc);
1838        // additional cleanup to make it PerfTests compatible
1839        clear();
1840    }
1841
1842    /**
1843     * Tests context usage.
1844     * Case 1: If Config was provided by user, then LoginContext
1845     * uses stored user's context and performs all call to LoginModule's
1846     * methods in that context.
1847     */
1848    public void testContextUsage_1() throws Exception {
1849        Subject dummySubj = new Subject();
1850        final DomainCombiner dc = new SubjectDomainCombiner(dummySubj);
1851        AccessControlContext acc = new AccessControlContext(AccessController
1852                .getContext(), dc);
1853        PrivilegedExceptionAction<Void> action = new PrivilegedExceptionAction<Void>() {
1854            public Void run() throws Exception {
1855                implTestContextUsage(false, dc);
1856                return null;
1857            }
1858        };
1859        AccessController.doPrivileged(action, acc);
1860        // additional cleanup to make it PerfTests compatible
1861        clear();
1862    }
1863
1864    static boolean TestLoginModule_Contexted_staticDone = false;
1865
1866    static boolean TestCallbackHandler_Contexted_staticDone = false;
1867
1868    /**
1869     * A special-purpose CallbackHandler<br>
1870     * with the following abilities:<br>
1871     * <il>
1872     * <li>it shows whether its class was initialized or not (via the external
1873     * variable <code>boolean TestCallbackHandler_Contexted_staticDone</code>)
1874     *
1875     * <li>keeps track of the active security contexts for each operation -
1876     * static{}, ctor(), handle()
1877     * </il>
1878     */
1879    public static class TestCallbackHandler_Contexted extends
1880            TestCallbackHandler {
1881        public static AccessControlContext accStatic;
1882
1883        public AccessControlContext accCtor;
1884
1885        public AccessControlContext accHandle;
1886
1887        static {
1888            accStatic = AccessController.getContext();
1889            TestCallbackHandler_Contexted_staticDone = true;
1890        }
1891
1892        /**
1893         * Provides an easy access to the first CallbackHandler created.
1894         */
1895        public static TestCallbackHandler_Contexted item() {
1896            return (TestCallbackHandler_Contexted) instances.get(0);
1897        }
1898
1899        public TestCallbackHandler_Contexted() {
1900            super();
1901            accCtor = AccessController.getContext();
1902        }
1903
1904        @Override
1905        public void handle(Callback[] cbs) {
1906            accHandle = AccessController.getContext();
1907        }
1908    }
1909
1910    /**
1911     * A special-purpose LoginModule<br>
1912     * with the following features:<br>
1913     * <il>
1914     * <li>it shows whether its class was initialized or not (via the external
1915     * variable <code>boolean TestLoginModule_Contexted_staticDone</code>)
1916     *
1917     * <li>keeps track of the active security contexts for each operation -
1918     * static{}, ctor(), initialize/login/commit/logout/abort
1919     *
1920     * <li>it also invokes callback handler (if any) during its login() method
1921     * </il>
1922     */
1923    public static class TestLoginModule_Contexted extends TestLoginModule {
1924        public static AccessControlContext accStatic;
1925        static {
1926            accStatic = AccessController.getContext();
1927            TestLoginModule_Contexted_staticDone = true;
1928        }
1929
1930        /**
1931         * Provides an easy access to instances of
1932         * TestLoginModule_Contexted_staticDone.
1933         */
1934        public static TestLoginModule_Contexted item(int i) {
1935            return (TestLoginModule_Contexted) TestLoginModule.get(i);
1936        }
1937
1938        /**
1939         * Provides an easy access to the very first instance of
1940         * TestLoginModule_Contexted_staticDone.
1941         */
1942        public static TestLoginModule_Contexted item() {
1943            return item(0);
1944        }
1945        // Below are AccessControlContext-s for the appropriate operations:
1946        public AccessControlContext accCtor;
1947
1948        public AccessControlContext accInit;
1949
1950        public AccessControlContext accLogin;
1951
1952        public AccessControlContext accCommit;
1953
1954        public AccessControlContext accLogout;
1955
1956        public AccessControlContext accAbort;
1957
1958        public TestLoginModule_Contexted() {
1959            super();
1960            accCtor = AccessController.getContext();
1961        }
1962
1963        @Override
1964        public void initialize(Subject subject,
1965                CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
1966            accInit = AccessController.getContext();
1967            super.initialize(subject, callbackHandler, sharedState, options);
1968        }
1969
1970        @Override
1971        public boolean login() throws LoginException {
1972            accLogin = AccessController.getContext();
1973            if (cbHandler != null) {
1974                try {
1975                    cbHandler.handle(null);
1976                } catch (UnsupportedCallbackException _) {
1977                    throw (LoginException) new LoginException().initCause(_);
1978                } catch (IOException _) {
1979                    throw (LoginException) new LoginException().initCause(_);
1980                }
1981            }
1982            return super.login();
1983        }
1984
1985        @Override
1986        public boolean commit() throws LoginException {
1987            accCommit = AccessController.getContext();
1988            return super.commit();
1989        }
1990
1991        @Override
1992        public boolean logout() throws LoginException {
1993            accLogout = AccessController.getContext();
1994            return super.logout();
1995        }
1996
1997        @Override
1998        public boolean abort() throws LoginException {
1999            accAbort = AccessController.getContext();
2000            return super.abort();
2001        }
2002    }
2003    /**
2004     * The real implementation of TestContextUsage_0 and TestContextUsage_1
2005     * methods.
2006     * @param useInstalledConfig
2007     * @param dc - which domain combiner to test for
2008     * @throws Exception
2009     */
2010    private void implTestContextUsage(boolean useInstalledConfig,
2011            DomainCombiner dc) throws Exception {
2012
2013        // the class was not loaded/initialized yet. it's legal to test statics
2014        boolean checkModuleStatic = !TestLoginModule_Contexted_staticDone;
2015        boolean checkCBHandlerStatic = !TestCallbackHandler_Contexted_staticDone;
2016        //        //_FIXME: debug
2017        //        if( checkModuleStatic ) {
2018        //            System.err.println("module static was checked. r u happy ? "+useInstalledConfig);
2019        //        }
2020        //        if( checkCBHandlerStatic ) {
2021        //            System.err.println("handler static was checked. r u happy ? "+useInstalledConfig);
2022        //        }
2023        //        //~fixme
2024        TestConfig.addInstalledRequired("TestLoginModule_Contexted");
2025
2026        //
2027        //CallbackHandler cbHandler = new TestCallbackHandler_Contexted();
2028        // The property will be cleared at setUp()
2029        Security.setProperty(DEFAULT_CBHANDLER_PROPERTY,
2030                getGlobalClassName("TestCallbackHandler_Contexted"));
2031
2032        LoginContext lc = new LoginContext(CONFIG_NAME, null, null,
2033                useInstalledConfig ? null : TestConfig.get());
2034        lc.login();
2035        lc.logout();
2036        //
2037        assertEquals(1, TestCallbackHandler.size());
2038
2039        // now, get abort() called
2040        TestLoginModule.staticMask = TestLoginModule.FAIL_AT_LOGIN;
2041        try {
2042            lc.login();
2043            fail("must not pass here");
2044        } catch (LoginException _) {
2045            // gut
2046        }
2047
2048        DomainCombiner match = useInstalledConfig ? null : dc;
2049        //
2050        if (checkModuleStatic) {
2051            assertSame(TestLoginModule_Contexted.accStatic.getDomainCombiner(),
2052                    match);
2053        }
2054        //
2055        assertSame(
2056                TestLoginModule_Contexted.item().accCtor.getDomainCombiner(),
2057                match);
2058        //
2059        assertSame(
2060                TestLoginModule_Contexted.item().accInit.getDomainCombiner(),
2061                match);
2062        //
2063        assertSame(TestLoginModule_Contexted.item().accLogin
2064                .getDomainCombiner(), match);
2065        //
2066        assertSame(TestLoginModule_Contexted.item().accCommit
2067                .getDomainCombiner(), match);
2068        //
2069        assertSame(TestLoginModule_Contexted.item().accLogout
2070                .getDomainCombiner(), match);
2071        //
2072        assertSame(TestLoginModule_Contexted.item().accAbort
2073                .getDomainCombiner(), match);
2074
2075        // handle() must be called from the wrapper, so it must be 'dc' and not
2076        // 'match' here
2077        assertSame(TestCallbackHandler_Contexted.item().accHandle
2078                .getDomainCombiner(), dc);
2079
2080        // ctor() for the Handler is called somewhere in
2081        // LoginContext.LoginContext().
2082        // It seems it's always get called from inside the powerful context
2083        // of LoginContext, so it's always 'null' here - they seem to use
2084        // doPriv(action) there
2085        assertSame(TestCallbackHandler_Contexted.item().accCtor
2086                .getDomainCombiner(), null);
2087
2088        if (useInstalledConfig) {
2089            assertNotNull(TestLoginModule_Contexted.item().cbHandler);
2090            assertNotSame(TestCallbackHandler_Contexted.item(),
2091                    TestLoginModule_Contexted.item().cbHandler);
2092
2093            if (checkCBHandlerStatic) {
2094                assertSame(TestCallbackHandler_Contexted.accStatic
2095                        .getDomainCombiner(), match);
2096            }
2097        } else {
2098            assertSame(TestCallbackHandler_Contexted.item(),
2099                    TestLoginModule_Contexted.item().cbHandler);
2100        }
2101    }
2102}
2103