From 5d90c9c14bf94ec2efb29750b587cc7ecd6f926d Mon Sep 17 00:00:00 2001 From: Emilio Setiadarma Date: Thu, 10 Aug 2023 19:50:09 -0700 Subject: [PATCH] NIFI-9164 Refactored tests in nifi-windows-event-log to JUnit 5 - Used LauncherInterceptor to handle custom class loading This closes #7623 Signed-off-by: David Handermann --- .../nifi-windows-event-log-processors/pom.xml | 20 ++- .../log/ConsumeWindowsEventLogFailTest.java | 39 ----- .../event/log/ConsumeWindowsEventLogTest.java | 134 ++++++++++-------- .../windows/event/log/JNAFailJUnitRunner.java | 42 ------ .../windows/event/log/JNAJUnitRunner.java | 51 ------- ...unner.java => JNALauncherInterceptor.java} | 83 ++++++----- .../event/log/jna/ErrorLookupTest.java | 19 +-- ...ventSubscribeXmlRenderingCallbackTest.java | 17 ++- ...unit.platform.launcher.LauncherInterceptor | 15 ++ 9 files changed, 175 insertions(+), 245 deletions(-) delete mode 100644 nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/ConsumeWindowsEventLogFailTest.java delete mode 100644 nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/JNAFailJUnitRunner.java delete mode 100644 nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/JNAJUnitRunner.java rename nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/{JNAOverridingJUnitRunner.java => JNALauncherInterceptor.java} (62%) create mode 100644 nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor diff --git a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/pom.xml b/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/pom.xml index 92d26e4a86..15bca78e79 100644 --- a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/pom.xml +++ b/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/pom.xml @@ -25,6 +25,22 @@ language governing permissions and limitations under the License. --> 3.29.2-GA + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + true + + + + + + + org.apache.nifi @@ -68,8 +84,8 @@ language governing permissions and limitations under the License. --> test - org.junit.vintage - junit-vintage-engine + org.junit.platform + junit-platform-launcher test diff --git a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/ConsumeWindowsEventLogFailTest.java b/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/ConsumeWindowsEventLogFailTest.java deleted file mode 100644 index 2a7b6b7ce0..0000000000 --- a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/ConsumeWindowsEventLogFailTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.nifi.processors.windows.event.log; - -import org.apache.nifi.util.TestRunner; -import org.apache.nifi.util.TestRunners; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Test scenario where we can't load the native libraries - */ -@RunWith(JNAFailJUnitRunner.class) -public class ConsumeWindowsEventLogFailTest { - - /** - * The processor should never be valid because we're using JNAFailJUnitRunner - */ - @Test - public void testValidate() { - TestRunner testRunner = TestRunners.newTestRunner(ConsumeWindowsEventLog.class); - testRunner.assertNotValid(); - } -} diff --git a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/ConsumeWindowsEventLogTest.java b/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/ConsumeWindowsEventLogTest.java index 05ee3a91ae..efd5d3674c 100644 --- a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/ConsumeWindowsEventLogTest.java +++ b/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/ConsumeWindowsEventLogTest.java @@ -14,36 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.apache.nifi.processors.windows.event.log; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isA; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - import com.sun.jna.Pointer; import com.sun.jna.platform.win32.Kernel32; import com.sun.jna.platform.win32.W32Errors; import com.sun.jna.platform.win32.WinError; import com.sun.jna.platform.win32.WinNT; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; import org.apache.nifi.annotation.lifecycle.OnScheduled; import org.apache.nifi.annotation.lifecycle.OnStopped; import org.apache.nifi.processor.exception.ProcessException; @@ -55,13 +32,43 @@ import org.apache.nifi.util.MockSessionFactory; import org.apache.nifi.util.ReflectionUtils; import org.apache.nifi.util.TestRunner; import org.apache.nifi.util.TestRunners; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; -@RunWith(JNAJUnitRunner.class) +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * Running tests may require {@code junit.platform.launcher.interceptors.enabled} + * property to be set to {@code true} to resolve class loading issues. + */ +@ExtendWith(MockitoExtension.class) public class ConsumeWindowsEventLogTest { @Mock Kernel32 kernel32; @@ -78,36 +85,13 @@ public class ConsumeWindowsEventLogTest { private ConsumeWindowsEventLog evtSubscribe; private TestRunner testRunner; - public static List mockEventHandles(WEvtApi wEvtApi, Kernel32 kernel32, List eventXmls) { - List eventHandles = new ArrayList<>(); - for (String eventXml : eventXmls) { - WinNT.HANDLE eventHandle = mock(WinNT.HANDLE.class); - when(wEvtApi.EvtRender(isNull(), eq(eventHandle), eq(WEvtApi.EvtRenderFlags.EVENT_XML), - anyInt(), any(Pointer.class), any(Pointer.class), any(Pointer.class))).thenAnswer(invocation -> { - Object[] arguments = invocation.getArguments(); - Pointer bufferUsed = (Pointer) arguments[5]; - byte[] array = StandardCharsets.UTF_16LE.encode(eventXml).array(); - if (array.length > (int) arguments[3]) { - when(kernel32.GetLastError()).thenReturn(W32Errors.ERROR_INSUFFICIENT_BUFFER).thenReturn(W32Errors.ERROR_SUCCESS); - } else { - ((Pointer) arguments[4]).write(0, array, 0, array.length); - } - bufferUsed.setInt(0, array.length); - return false; - }); - eventHandles.add(eventHandle); - } - return eventHandles; - } - - @Before + @BeforeEach public void setup() { evtSubscribe = new ConsumeWindowsEventLog(wEvtApi, kernel32); + lenient().when(subscriptionHandle.getPointer()).thenReturn(subscriptionPointer); - when(subscriptionHandle.getPointer()).thenReturn(subscriptionPointer); - - when(wEvtApi.EvtSubscribe(isNull(), isNull(), eq(ConsumeWindowsEventLog.DEFAULT_CHANNEL), eq(ConsumeWindowsEventLog.DEFAULT_XPATH), + lenient().when(wEvtApi.EvtSubscribe(isNull(), isNull(), eq(ConsumeWindowsEventLog.DEFAULT_CHANNEL), eq(ConsumeWindowsEventLog.DEFAULT_XPATH), isNull(), isNull(), isA(EventSubscribeXmlRenderingCallback.class), eq(WEvtApi.EvtSubscribeFlags.SUBSCRIBE_TO_FUTURE | WEvtApi.EvtSubscribeFlags.EVT_SUBSCRIBE_STRICT))) .thenReturn(subscriptionHandle); @@ -115,8 +99,9 @@ public class ConsumeWindowsEventLogTest { testRunner = TestRunners.newTestRunner(evtSubscribe); } - @Test(timeout = 10 * 1000) - public void testProcessesBlockedEvents() throws UnsupportedEncodingException { + @Test + @Timeout(value = 10) + public void testProcessesBlockedEvents() { testRunner.setProperty(ConsumeWindowsEventLog.MAX_EVENT_QUEUE_SIZE, "1"); testRunner.run(1, false, true); EventSubscribeXmlRenderingCallback renderingCallback = getRenderingCallback(); @@ -169,10 +154,9 @@ public class ConsumeWindowsEventLogTest { } @Test - public void testScheduleErrorThenTriggerSubscribe() throws InvocationTargetException, IllegalAccessException { + public void testScheduleErrorThenTriggerSubscribe() { evtSubscribe = new ConsumeWindowsEventLog(wEvtApi, kernel32); - when(subscriptionHandle.getPointer()).thenReturn(subscriptionPointer); when(wEvtApi.EvtSubscribe(isNull(), isNull(), eq(ConsumeWindowsEventLog.DEFAULT_CHANNEL), eq(ConsumeWindowsEventLog.DEFAULT_XPATH), @@ -221,18 +205,20 @@ public class ConsumeWindowsEventLogTest { verify(wEvtApi).EvtClose(subscriptionHandle); } - @Test(expected = ProcessException.class) + @Test public void testScheduleQueueStopThrowsException() throws Throwable { ReflectionUtils.invokeMethodsWithAnnotation(OnScheduled.class, evtSubscribe, testRunner.getProcessContext()); WinNT.HANDLE handle = mockEventHandles(wEvtApi, kernel32, Arrays.asList("test")).get(0); getRenderingCallback().onEvent(WEvtApi.EvtSubscribeNotifyAction.DELIVER, null, handle); - try { - ReflectionUtils.invokeMethodsWithAnnotation(OnStopped.class, evtSubscribe, testRunner.getProcessContext()); - } catch (InvocationTargetException e) { - throw e.getCause(); - } + assertThrows(ProcessException.class, () -> { + try { + ReflectionUtils.invokeMethodsWithAnnotation(OnStopped.class, evtSubscribe, testRunner.getProcessContext()); + } catch (final InvocationTargetException e) { + throw e.getCause(); + } + }); } public EventSubscribeXmlRenderingCallback getRenderingCallback() { @@ -257,6 +243,28 @@ public class ConsumeWindowsEventLogTest { assertEquals(ConsumeWindowsEventLog.RELATIONSHIPS, evtSubscribe.getRelationships()); } + public static List mockEventHandles(WEvtApi wEvtApi, Kernel32 kernel32, List eventXmls) { + List eventHandles = new ArrayList<>(); + for (String eventXml : eventXmls) { + WinNT.HANDLE eventHandle = mock(WinNT.HANDLE.class); + when(wEvtApi.EvtRender(isNull(), eq(eventHandle), eq(WEvtApi.EvtRenderFlags.EVENT_XML), + anyInt(), any(Pointer.class), any(Pointer.class), any(Pointer.class))).thenAnswer(invocation -> { + Object[] arguments = invocation.getArguments(); + Pointer bufferUsed = (Pointer) arguments[5]; + byte[] array = StandardCharsets.UTF_16LE.encode(eventXml).array(); + if (array.length > (int) arguments[3]) { + when(kernel32.GetLastError()).thenReturn(W32Errors.ERROR_INSUFFICIENT_BUFFER).thenReturn(W32Errors.ERROR_SUCCESS); + } else { + ((Pointer) arguments[4]).write(0, array, 0, array.length); + } + bufferUsed.setInt(0, array.length); + return false; + }); + eventHandles.add(eventHandle); + } + return eventHandles; + } + private static Set getCreatedSessions(TestRunner testRunner) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { MockSessionFactory processSessionFactory = (MockSessionFactory) testRunner.getProcessSessionFactory(); Method getCreatedSessions = processSessionFactory.getClass().getDeclaredMethod("getCreatedSessions"); diff --git a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/JNAFailJUnitRunner.java b/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/JNAFailJUnitRunner.java deleted file mode 100644 index 675375d444..0000000000 --- a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/JNAFailJUnitRunner.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.nifi.processors.windows.event.log; - -import org.junit.runners.model.InitializationError; - -import java.util.HashMap; -import java.util.Map; - -/** - * Native load failure to simulate case on all OSes (even Windows) - */ -public class JNAFailJUnitRunner extends JNAOverridingJUnitRunner { - - public JNAFailJUnitRunner(Class klass) throws InitializationError { - super(klass); - } - - @Override - protected Map> getClassOverrideMap() { - Map> classOverrideMap = new HashMap<>(); - Map nativeOverrideMap = new HashMap<>(); - nativeOverrideMap.put(LOAD_LIBRARY, "throw new " + UnsatisfiedLinkError.class.getCanonicalName() + "(\"JNAFailJUnitRunner\");"); - classOverrideMap.put(NATIVE_CANONICAL_NAME, nativeOverrideMap); - return classOverrideMap; - } -} diff --git a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/JNAJUnitRunner.java b/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/JNAJUnitRunner.java deleted file mode 100644 index b1608e3c8a..0000000000 --- a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/JNAJUnitRunner.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.nifi.processors.windows.event.log; - -import com.sun.jna.platform.win32.Kernel32Util; -import org.junit.runners.model.InitializationError; - -import java.util.HashMap; -import java.util.Map; - -/** - * Can't even use the JNA interface classes if the native library won't load. This is a workaround to allow mocking them for unit tests. - */ -public class JNAJUnitRunner extends JNAOverridingJUnitRunner { - public static final String TEST_COMPUTER_NAME = "testComputerName"; - public static final String KERNEL_32_UTIL_CANONICAL_NAME = Kernel32Util.class.getCanonicalName(); - - public JNAJUnitRunner(Class klass) throws InitializationError { - super(klass); - } - - @Override - protected Map> getClassOverrideMap() { - Map> classOverrideMap = new HashMap<>(); - - Map nativeOverrideMap = new HashMap<>(); - nativeOverrideMap.put(LOAD_LIBRARY, "return null;"); - classOverrideMap.put(NATIVE_CANONICAL_NAME, nativeOverrideMap); - - Map kernel32UtilMap = new HashMap<>(); - kernel32UtilMap.put("getComputerName", "return \"" + TEST_COMPUTER_NAME + "\";"); - classOverrideMap.put(KERNEL_32_UTIL_CANONICAL_NAME, kernel32UtilMap); - - return classOverrideMap; - } -} diff --git a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/JNAOverridingJUnitRunner.java b/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/JNALauncherInterceptor.java similarity index 62% rename from nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/JNAOverridingJUnitRunner.java rename to nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/JNALauncherInterceptor.java index 2ce8bc9026..5c55b9fe52 100644 --- a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/JNAOverridingJUnitRunner.java +++ b/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/JNALauncherInterceptor.java @@ -14,38 +14,38 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.apache.nifi.processors.windows.event.log; -import com.sun.jna.Native; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.CtMethod; -import org.junit.Assert; -import org.junit.runner.Description; -import org.junit.runner.Runner; -import org.junit.runner.notification.RunNotifier; -import org.junit.runners.model.InitializationError; -import org.mockito.junit.MockitoJUnitRunner; - import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; -/** - * Can't even use the JNA interface classes if the native library won't load. This is a workaround to allow mocking them for unit tests. - */ -public abstract class JNAOverridingJUnitRunner extends Runner { +import com.sun.jna.Native; +import com.sun.jna.platform.win32.Kernel32Util; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; +import org.junit.platform.launcher.LauncherInterceptor; + +import static org.junit.jupiter.api.Assertions.fail; + +public class JNALauncherInterceptor implements LauncherInterceptor { public static final String NATIVE_CANONICAL_NAME = Native.class.getCanonicalName(); public static final String LOAD_LIBRARY = "loadLibrary"; - private final Runner delegate; + public static final String TEST_COMPUTER_NAME = "testComputerName"; + public static final String KERNEL_32_UTIL_CANONICAL_NAME = Kernel32Util.class.getCanonicalName(); - public JNAOverridingJUnitRunner(Class klass) throws InitializationError { + private final URLClassLoader jnaMockClassLoader; + + public JNALauncherInterceptor() { Map> classOverrideMap = getClassOverrideMap(); String classpath = System.getProperty("java.class.path"); URL[] result = Pattern.compile(File.pathSeparator).splitAsStream(classpath).map(Paths::get).map(Path::toAbsolutePath).map(Path::toUri) @@ -54,12 +54,12 @@ public abstract class JNAOverridingJUnitRunner extends Runner { try { url = uri.toURL(); } catch (MalformedURLException e) { - Assert.fail(String.format("Unable to create URL for classpath entry '%s'", uri)); + fail(String.format("Unable to create URL for classpath entry '%s'", uri)); } return url; }) .toArray(URL[]::new); - ClassLoader jnaMockClassloader = new URLClassLoader(result, null) { + jnaMockClassLoader = new URLClassLoader(result, null) { @Override protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { Map classOverrides = classOverrideMap.get(name); @@ -86,8 +86,8 @@ public abstract class JNAOverridingJUnitRunner extends Runner { } catch (Exception e) { throw new ClassNotFoundException(name, e); } - } else if (name.startsWith("org.junit.") || name.startsWith("org.mockito")) { - Class result = JNAOverridingJUnitRunner.class.getClassLoader().loadClass(name); + } else if (name.startsWith("org.junit.")) { + Class result = JNALauncherInterceptor.class.getClassLoader().loadClass(name); if (resolve) { resolveClass(result); } @@ -96,23 +96,40 @@ public abstract class JNAOverridingJUnitRunner extends Runner { return super.loadClass(name, resolve); } }; + } + + @Override + public T intercept(final Invocation invocation) { + final Thread currentThread = Thread.currentThread(); + final ClassLoader originalClassLoader = currentThread.getContextClassLoader(); + currentThread.setContextClassLoader(jnaMockClassLoader); try { - delegate = (Runner) jnaMockClassloader.loadClass(MockitoJUnitRunner.class.getCanonicalName()).getConstructor(Class.class) - .newInstance(jnaMockClassloader.loadClass(klass.getCanonicalName())); - } catch (Exception e) { - throw new InitializationError(e); + return invocation.proceed(); + } finally { + currentThread.setContextClassLoader(originalClassLoader); } } - protected abstract Map> getClassOverrideMap(); - @Override - public Description getDescription() { - return delegate.getDescription(); + public void close() { + try { + jnaMockClassLoader.close(); + } catch (final IOException e) { + throw new UncheckedIOException("Failed to close custom class loader", e); + } } - @Override - public void run(RunNotifier notifier) { - delegate.run(notifier); + private Map> getClassOverrideMap() { + final Map> classOverrideMap = new HashMap<>(); + + final Map nativeOverrideMap = new HashMap<>(); + nativeOverrideMap.put(LOAD_LIBRARY, "return null;"); + classOverrideMap.put(NATIVE_CANONICAL_NAME, nativeOverrideMap); + + final Map kernel32UtilMap = new HashMap<>(); + kernel32UtilMap.put("getComputerName", "return \"" + TEST_COMPUTER_NAME + "\";"); + classOverrideMap.put(KERNEL_32_UTIL_CANONICAL_NAME, kernel32UtilMap); + + return classOverrideMap; } } diff --git a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/jna/ErrorLookupTest.java b/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/jna/ErrorLookupTest.java index ef4a91f665..98bf3beb33 100644 --- a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/jna/ErrorLookupTest.java +++ b/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/jna/ErrorLookupTest.java @@ -14,28 +14,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.apache.nifi.processors.windows.event.log.jna; import com.sun.jna.platform.win32.Kernel32; import com.sun.jna.platform.win32.WinError; -import org.apache.nifi.processors.windows.event.log.JNAJUnitRunner; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.when; -@RunWith(JNAJUnitRunner.class) +/** + * Running tests may require {@code junit.platform.launcher.interceptors.enabled} + * property to be set to {@code true} to resolve class loading issues. + */ +@ExtendWith(MockitoExtension.class) public class ErrorLookupTest { @Mock Kernel32 kernel32; private ErrorLookup errorLookup; - @Before + @BeforeEach public void setup() { errorLookup = new ErrorLookup(kernel32); } diff --git a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/jna/EventSubscribeXmlRenderingCallbackTest.java b/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/jna/EventSubscribeXmlRenderingCallbackTest.java index a1887374da..962d6b4f8e 100644 --- a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/jna/EventSubscribeXmlRenderingCallbackTest.java +++ b/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/java/org/apache/nifi/processors/windows/event/log/jna/EventSubscribeXmlRenderingCallbackTest.java @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.apache.nifi.processors.windows.event.log.jna; import com.sun.jna.Pointer; @@ -22,11 +21,11 @@ import com.sun.jna.platform.win32.Kernel32; import com.sun.jna.platform.win32.WinNT; import org.apache.nifi.logging.ComponentLog; import org.apache.nifi.processors.windows.event.log.ConsumeWindowsEventLogTest; -import org.apache.nifi.processors.windows.event.log.JNAJUnitRunner; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; import java.util.Arrays; import java.util.function.Consumer; @@ -37,7 +36,11 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@RunWith(JNAJUnitRunner.class) +/** + * Running tests may require {@code junit.platform.launcher.interceptors.enabled} + * property to be set to {@code true} to resolve class loading issues. + */ +@ExtendWith(MockitoExtension.class) public class EventSubscribeXmlRenderingCallbackTest { @Mock ComponentLog logger; @@ -60,7 +63,7 @@ public class EventSubscribeXmlRenderingCallbackTest { private EventSubscribeXmlRenderingCallback eventSubscribeXmlRenderingCallback; private int maxBufferSize; - @Before + @BeforeEach public void setup() { maxBufferSize = 8; eventSubscribeXmlRenderingCallback = new EventSubscribeXmlRenderingCallback(logger, consumer, maxBufferSize, wEvtApi, kernel32, errorLookup); diff --git a/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor b/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor new file mode 100644 index 0000000000..bf234104f3 --- /dev/null +++ b/nifi-nar-bundles/nifi-windows-event-log-bundle/nifi-windows-event-log-processors/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor @@ -0,0 +1,15 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +org.apache.nifi.processors.windows.event.log.JNALauncherInterceptor \ No newline at end of file