@SuppressWarnings({ "rawtypes" })

@Test
public void lockdown() throws Exception {
    RxJavaPlugins.reset();
    RxJavaPlugins.lockdown();
    try {
        assertTrue(RxJavaPlugins.isLockdown());
        Consumer a1 = Functions.emptyConsumer();
        Callable f0 = new Callable() {
            @Override
            public Object call() {
                return null;
            }
        };
        Function f1 = Functions.identity();
        BiFunction f2 = new BiFunction() {
            @Override
            public Object apply(Object t1, Object t2) {
                return t2;
            }
        };
        BooleanSupplier bs = new BooleanSupplier() {
            @Override
            public boolean getAsBoolean() throws Exception {
                return true;
            }
        };
        for (Method m : RxJavaPlugins.class.getMethods()) {
            if (m.getName().startsWith("set")) {
                Method getter;
                Class<?> paramType = m.getParameterTypes()[0];
                if (paramType == Boolean.TYPE) {
                    getter = RxJavaPlugins.class.getMethod("is" + m.getName().substring(3));
                } else {
                    getter = RxJavaPlugins.class.getMethod("get" + m.getName().substring(3));
                }
                Object before = getter.invoke(null);
                try {
                    if (paramType.isAssignableFrom(Boolean.TYPE)) {
                        m.invoke(null, true);
                    } else
                    if (paramType.isAssignableFrom(Callable.class)) {
                        m.invoke(null, f0);
                    } else
                    if (paramType.isAssignableFrom(Function.class)) {
                        m.invoke(null, f1);
                    } else
                    if (paramType.isAssignableFrom(Consumer.class)) {
                        m.invoke(null, a1);
                    } else
                    if (paramType.isAssignableFrom(BooleanSupplier.class)) {
                        m.invoke(null, bs);
                    } else {
                        m.invoke(null, f2);
                    }
                    fail("Should have thrown InvocationTargetException(IllegalStateException)");
                } catch (InvocationTargetException ex) {
                    if (ex.getCause() instanceof IllegalStateException) {
                        assertEquals("Plugins can't be changed anymore",ex.getCause().getMessage());
                    } else {
                        fail("Should have thrown InvocationTargetException(IllegalStateException)");
                    }
                }
                Object after = getter.invoke(null);
                if (paramType.isPrimitive()) {
                    assertEquals(m.toString(), before, after);
                } else {
                    assertSame(m.toString(), before, after);
                }
            }
        }
          Object o1 = RxJavaPlugins.getOnObservableCreate();
          Object o2 = RxJavaPlugins.getOnSingleCreate();
          Object o3 = RxJavaPlugins.getOnCompletableCreate();
          RxJavaPlugins.enableAssemblyTracking();
          RxJavaPlugins.clearAssemblyTracking();
          RxJavaPlugins.resetAssemblyTracking();
          assertSame(o1, RxJavaPlugins.getOnObservableCreate());
          assertSame(o2, RxJavaPlugins.getOnSingleCreate());
          assertSame(o3, RxJavaPlugins.getOnCompletableCreate());
    } finally {
        RxJavaPlugins.unlock();
        RxJavaPlugins.reset();
        assertFalse(RxJavaPlugins.isLockdown());
    }
}