private void assertLoadUnloadInvocationCount(Class<?> testExtensionClass, int invocationCount) throws Exception { String simpleNameOfTestExtensionClass = testExtensionClass.getSimpleName(); setupClassesInBundle(simpleNameOfTestExtensionClass + ".class"); when(bundle.loadClass(contains(simpleNameOfTestExtensionClass))).thenReturn((Class) testExtensionClass); activator.start(context); assertThat(testExtensionClass.getField("loadInvoked").getInt(null), is(invocationCount)); activator.stop(context); assertThat(testExtensionClass.getField("unLoadInvoked").getInt(null), is(invocationCount)); }
@Test public void shouldReportAClassWhichIsAnnotatedAsAnExtensionIfItFailsDuringConstruction() throws Exception { setupClassesInBundle("PublicGoExtensionClassWhichThrowsAnExceptionInItsConstructor.class"); when(bundle.loadClass(contains("PublicGoExtensionClassWhichThrowsAnExceptionInItsConstructor"))).thenReturn((Class) PublicGoExtensionClassWhichThrowsAnExceptionInItsConstructor.class); activator.start(context); verifyErrorsReported( format("Class [PublicGoExtensionClassWhichThrowsAnExceptionInItsConstructor] is annotated with @Extension but cannot be constructed. Reason: java.lang.RuntimeException: %s.", CONSTRUCTOR_FAIL_MSG), NO_EXT_ERR_MSG); }
@Test public void testFindUserDnWhenUserPatternFoundByUniqueIdentifier() throws NamingException { conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN, "CN=%s,OU=org1,DC=foo,DC=bar"); NamingEnumeration<SearchResult> validResult = mockNamingEnumeration("CN=User1,OU=org1,DC=foo,DC=bar"); when(ctx.search(anyString(), anyString(), any(SearchControls.class))) .thenReturn(null) .thenReturn(validResult); search = new LdapSearch(conf, ctx); String expected = "CN=User1,OU=org1,DC=foo,DC=bar"; String actual = search.findUserDn("User1"); assertEquals(expected, actual); verify(ctx).search(eq("OU=org1,DC=foo,DC=bar"), contains("CN=User1"), any(SearchControls.class)); verify(ctx).search(eq("OU=org1,DC=foo,DC=bar"), contains("uid=User1"), any(SearchControls.class)); }
@Test public void loggerShouldBeAvailableToBeUsedInStaticBlocksAndConstructorAndLoadUnloadMethodsOfPluginExtensionClasses() throws Exception { setupClassesInBundle("PublicGoExtensionClassWhichLogsInAStaticBlock.class"); when(bundle.loadClass(contains("PublicGoExtensionClassWhichLogsInAStaticBlock"))).thenReturn((Class) PublicGoExtensionClassWhichLogsInAStaticBlock.class); activator.start(context); activator.stop(context); verify(loggingService).info(PLUGIN_ID, PublicGoExtensionClassWhichLogsInAStaticBlock.class.getName(), "HELLO from static block in PublicGoExtensionClassWhichLogsInAStaticBlock"); verify(loggingService).info(PLUGIN_ID, PublicGoExtensionClassWhichLogsInAStaticBlock.class.getName(), "HELLO from constructor in PublicGoExtensionClassWhichLogsInAStaticBlock"); verify(loggingService).info(PLUGIN_ID, PublicGoExtensionClassWhichLogsInAStaticBlock.class.getName(), "HELLO from load in PublicGoExtensionClassWhichLogsInAStaticBlock"); verify(loggingService).info(PLUGIN_ID, PublicGoExtensionClassWhichLogsInAStaticBlock.class.getName(), "HELLO from unload in PublicGoExtensionClassWhichLogsInAStaticBlock"); }
@Test public void shouldNotReportAClassWhichIsNotAnnotatedAsAnExtensionEvenIfItIsNotPublic() throws Exception { setupClassesInBundle("NonPublicClassWhichIsNotAGoExtension.class"); when(bundle.loadClass(contains("NonPublicClassWhichIsNotAGoExtension"))).thenReturn((Class) NonPublicClassWhichIsNotAGoExtension.class); activator.start(context); verifyErrorsReported(NO_EXT_ERR_MSG); }
@Test public void testFindUserDnWhenUserPatternFoundBySecondPattern() throws NamingException { conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN, "CN=%s,OU=org1,DC=foo,DC=bar:CN=%s,OU=org2,DC=foo,DC=bar"); NamingEnumeration<SearchResult> emptyResult = mockEmptyNamingEnumeration(); NamingEnumeration<SearchResult> validResult = mockNamingEnumeration("CN=User1,OU=org2,DC=foo,DC=bar"); when(ctx.search(anyString(), anyString(), any(SearchControls.class))) .thenReturn(emptyResult) .thenReturn(validResult); search = new LdapSearch(conf, ctx); String expected = "CN=User1,OU=org2,DC=foo,DC=bar"; String actual = search.findUserDn("User1"); assertEquals(expected, actual); verify(ctx).search(eq("OU=org1,DC=foo,DC=bar"), contains("CN=User1"), any(SearchControls.class)); verify(ctx).search(eq("OU=org2,DC=foo,DC=bar"), contains("CN=User1"), any(SearchControls.class)); }
@Test public void shouldReportAClassWhichIsAnnotatedAsAnExtensionIfItIsAbstract() throws Exception { setupClassesInBundle("PublicAbstractGoExtensionClass.class"); when(bundle.loadClass(contains("PublicAbstractGoExtensionClass"))).thenReturn((Class) PublicAbstractGoExtensionClass.class); activator.start(context); verifyErrorsReported("Class [PublicAbstractGoExtensionClass] is annotated with @Extension but is abstract.", NO_EXT_ERR_MSG); }
@Test public void shouldReportAClassWhichIsAnnotatedAsAnExtensionIfItIsNotInstantiable() throws Exception { setupClassesInBundle("PublicGoExtensionClassWhichDoesNotHaveADefaultConstructor.class"); when(bundle.loadClass(contains("PublicGoExtensionClassWhichDoesNotHaveADefaultConstructor"))).thenReturn((Class) PublicGoExtensionClassWhichDoesNotHaveADefaultConstructor.class); activator.start(context); verifyErrorsReported("Class [PublicGoExtensionClassWhichDoesNotHaveADefaultConstructor] is annotated with @Extension but cannot be constructed. " + "Make sure it and all of its parent classes have a default constructor.", NO_EXT_ERR_MSG); }
@Test public void shouldReportAClassWhichIsAnnotatedAsAnExtensionIfItIsNotPublic() throws Exception { setupClassesInBundle("NonPublicGoExtensionClass.class"); when(bundle.loadClass(contains("NonPublicGoExtensionClass"))).thenReturn((Class) NonPublicGoExtensionClass.class); activator.start(context); verifyErrorsReported("Class [NonPublicGoExtensionClass] is annotated with @Extension but is not public.", NO_EXT_ERR_MSG); }
@Test public void shouldInvokeMethodWithLoadUnloadAnnotationAtPluginStart() throws Exception { setupClassesInBundle("GoExtensionWithLoadUnloadAnnotation.class"); when(bundle.loadClass(contains("GoExtensionWithLoadUnloadAnnotation"))).thenReturn((Class) GoExtensionWithLoadUnloadAnnotation.class); activator.start(context); assertThat(GoExtensionWithLoadUnloadAnnotation.loadInvoked, is(1)); activator.stop(context); assertThat(GoExtensionWithLoadUnloadAnnotation.unLoadInvoked, is(1)); }
@Test public void shouldHandleExceptionGeneratedByLoadMethodAtPluginStart() throws Exception { setupClassesInBundle("GoExtensionWithLoadAnnotationMethodThrowingException.class"); when(bundle.loadClass(contains("GoExtensionWithLoadAnnotationMethodThrowingException"))).thenReturn((Class) GoExtensionWithLoadAnnotationMethodThrowingException.class); activator.start(context); assertThat(activator.hasErrors(), is(true)); verifyErrorsReported("Class [GoExtensionWithLoadAnnotationMethodThrowingException] is annotated with @Extension but cannot be registered. " + "Reason: java.io.IOException: Load Dummy Checked Exception."); }
@Test public void testIsUserMemberOfGroupWhenUserId() throws NamingException { conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN, "CN=%s,OU=org1,DC=foo,DC=bar"); NamingEnumeration<SearchResult> validResult = LdapTestUtils.mockNamingEnumeration("CN=User1"); NamingEnumeration<SearchResult> emptyResult = LdapTestUtils.mockEmptyNamingEnumeration(); when(ctx.search(anyString(), contains("(uid=usr1)"), any(SearchControls.class))) .thenReturn(validResult); when(ctx.search(anyString(), contains("(uid=usr2)"), any(SearchControls.class))) .thenReturn(emptyResult); search = new LdapSearch(conf, ctx); assertTrue(search.isUserMemberOfGroup("usr1", "grp1")); assertFalse(search.isUserMemberOfGroup("usr2", "grp2")); }
@Test public void testFindGroupsForUser() throws NamingException { conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPDNPATTERN, "CN=%s,OU=org1,DC=foo,DC=bar"); NamingEnumeration<SearchResult> groupsResult = mockNamingEnumeration("CN=Group1,OU=org1,DC=foo,DC=bar"); when(ctx.search(eq("OU=org1,DC=foo,DC=bar"), contains("User1"), any(SearchControls.class))) .thenReturn(groupsResult); search = new LdapSearch(conf, ctx); List<String> expected = Arrays.asList("CN=Group1,OU=org1,DC=foo,DC=bar"); List<String> actual = search.findGroupsForUser("CN=User1,OU=org1,DC=foo,DC=bar"); assertEquals(expected, actual); }
@Test public void testFindUserDnWhenUserPatternFoundByFirstPattern() throws NamingException { conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN, "CN=%s,OU=org1,DC=foo,DC=bar:CN=%s,OU=org2,DC=foo,DC=bar"); NamingEnumeration<SearchResult> emptyResult = mockEmptyNamingEnumeration(); NamingEnumeration<SearchResult> validResult = mockNamingEnumeration("CN=User1,OU=org2,DC=foo,DC=bar"); when(ctx.search(anyString(), anyString(), any(SearchControls.class))) .thenReturn(validResult) .thenReturn(emptyResult); search = new LdapSearch(conf, ctx); String expected = "CN=User1,OU=org2,DC=foo,DC=bar"; String actual = search.findUserDn("User1"); assertEquals(expected, actual); verify(ctx).search(eq("OU=org1,DC=foo,DC=bar"), contains("CN=User1"), any(SearchControls.class)); }
@Test public void testIsUserMemberOfGroupWhenUserDn() throws NamingException { conf.setVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN, "CN=%s,OU=org1,DC=foo,DC=bar"); NamingEnumeration<SearchResult> validResult = LdapTestUtils.mockNamingEnumeration("CN=User1"); NamingEnumeration<SearchResult> emptyResult = LdapTestUtils.mockEmptyNamingEnumeration(); when(ctx.search(anyString(), contains("(uid=User1)"), any(SearchControls.class))) .thenReturn(validResult); when(ctx.search(anyString(), contains("(uid=User2)"), any(SearchControls.class))) .thenReturn(emptyResult); search = new LdapSearch(conf, ctx); assertTrue(search.isUserMemberOfGroup("CN=User1,OU=org1,DC=foo,DC=bar", "grp1")); assertFalse(search.isUserMemberOfGroup("CN=User2,OU=org1,DC=foo,DC=bar", "grp2")); } }
@Test public void shouldHandleExceptionGeneratedByUnLoadMethodAtPluginStop() throws Exception { setupClassesInBundle("GoExtensionWithUnloadAnnotationMethodThrowingException.class"); when(bundle.loadClass(contains("GoExtensionWithUnloadAnnotationMethodThrowingException"))).thenReturn((Class) GoExtensionWithUnloadAnnotationMethodThrowingException.class); activator.start(context); assertThat(activator.hasErrors(), is(false)); activator.stop(context); assertThat(activator.hasErrors(), is(true)); verifyErrorsReported("Invocation of unload method [public int com.thoughtworks.go.plugin.activation.GoExtensionWithUnloadAnnotationMethodThrowingException" + ".throwExceptionAgain(com.thoughtworks.go.plugin.api.info.PluginContext) " + "throws java.io.IOException]. " + "Reason: java.io.IOException: Unload Dummy Checked Exception."); }
@Test public void shouldGenerateExceptionWhenThereAreMoreThanOneLoadAnnotationsAtPluginStart() throws Exception { String expectedErrorMessageWithMethodsWithIncreasingOrder = "Class [GoExtensionWithMultipleLoadUnloadAnnotation] is annotated with @Extension will not be registered. " + "Reason: java.lang.RuntimeException: More than one method with @Load annotation not allowed. " + "Methods Found: [public void com.thoughtworks.go.plugin.activation.GoExtensionWithMultipleLoadUnloadAnnotation.setupData1(com.thoughtworks.go.plugin.api.info.PluginContext), " + "public void com.thoughtworks.go.plugin.activation.GoExtensionWithMultipleLoadUnloadAnnotation.setupData2(com.thoughtworks.go.plugin.api.info.PluginContext)]."; String expectedErrorMessageWithMethodsWithDecreasingOrder = "Class [GoExtensionWithMultipleLoadUnloadAnnotation] is annotated with @Extension will not be registered. " + "Reason: java.lang.RuntimeException: More than one method with @Load annotation not allowed. " + "Methods Found: [public void com.thoughtworks.go.plugin.activation.GoExtensionWithMultipleLoadUnloadAnnotation.setupData2(com.thoughtworks.go.plugin.api.info.PluginContext), " + "public void com.thoughtworks.go.plugin.activation.GoExtensionWithMultipleLoadUnloadAnnotation.setupData1(com.thoughtworks.go.plugin.api.info.PluginContext)]."; setupClassesInBundle("GoExtensionWithMultipleLoadUnloadAnnotation.class"); when(bundle.loadClass(contains("GoExtensionWithMultipleLoadUnloadAnnotation"))).thenReturn((Class) GoExtensionWithMultipleLoadUnloadAnnotation.class); activator.start(context); assertThat(activator.hasErrors(), is(true)); verifyThatOneOfTheErrorMessagesIsPresent(expectedErrorMessageWithMethodsWithIncreasingOrder, expectedErrorMessageWithMethodsWithDecreasingOrder); activator.stop(context); verifyThatOneOfTheErrorMessagesIsPresent(expectedErrorMessageWithMethodsWithIncreasingOrder, expectedErrorMessageWithMethodsWithDecreasingOrder); }
@Test public void testTrackDelayedMetricsTenant() { // enable tracking delayed metrics and track tracker.setIsTrackingDelayedMetrics(); tracker.trackDelayedMetricsTenant(tenantId, delayedMetrics); // verify verify(loggerMock, atLeastOnce()).info("[TRACKER] Tracking delayed metrics started"); verify(loggerMock, atLeastOnce()).info("[TRACKER][DELAYED METRIC] Tenant sending delayed metrics " + tenantId); verify(loggerMock, atLeastOnce()).info(contains("[TRACKER][DELAYED METRIC] " + tenantId + ".delayed.metric1 has collectionTime 2016-01-01 00:00:00 which is delayed")); verify(loggerMock, atLeastOnce()).info(contains("[TRACKER][DELAYED METRIC] " + tenantId + ".delayed.metric2 has collectionTime 2016-01-01 00:00:00 which is delayed")); }
@Test public void testDoesNotTrackDelayedMetricsTenant() { // disable tracking delayed metrics and track tracker.resetIsTrackingDelayedMetrics(); tracker.trackDelayedMetricsTenant(tenantId, delayedMetrics); // verify verify(loggerMock, atLeastOnce()).info("[TRACKER] Tracking delayed metrics stopped"); verify(loggerMock, never()).info("[TRACKER][DELAYED METRIC] Tenant sending delayed metrics " + tenantId); verify(loggerMock, never()).info(contains("[TRACKER][DELAYED METRIC] " + tenantId + ".delayed.metric1 has collectionTime 2016-01-01 00:00:00")); verify(loggerMock, never()).info(contains("[TRACKER][DELAYED METRIC] " + tenantId + ".delayed.metric2 has collectionTime 2016-01-01 00:00:00")); }
@Test public void testDoesNotTrackDelayedAggregatedMetricsTenant() { // disable tracking delayed metrics and track tracker.resetIsTrackingDelayedMetrics(); tracker.trackDelayedMetricsTenant(tenantId, delayedMetrics); // verify verify(loggerMock, atLeastOnce()).info("[TRACKER] Tracking delayed metrics stopped"); verify(loggerMock, never()).info("[TRACKER][DELAYED METRIC] Tenant sending delayed metrics " + tenantId); verify(loggerMock, never()).info(contains("[TRACKER][DELAYED METRIC] " + tenantId + ".delayed.metric1" + "," + tenantId + ".delayed.metric2 have collectionTime 2016-01-01 00:00:00 which is delayed")); } }