145 lines
5.4 KiB
Java
145 lines
5.4 KiB
Java
/*
|
|
* Copyright 2017 The Netty Project
|
|
*
|
|
* The Netty Project 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:
|
|
*
|
|
* https://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 io.netty5.util.internal;
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
import static org.junit.jupiter.api.Assertions.fail;
|
|
|
|
import io.netty5.util.CharsetUtil;
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.util.Arrays;
|
|
import java.util.UUID;
|
|
import java.util.concurrent.ThreadLocalRandom;
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
public class NativeLibraryLoaderTest {
|
|
|
|
@Test
|
|
public void testFileNotFound() {
|
|
try {
|
|
NativeLibraryLoader.load(UUID.randomUUID().toString(), NativeLibraryLoaderTest.class.getClassLoader());
|
|
fail();
|
|
} catch (UnsatisfiedLinkError error) {
|
|
assertTrue(error.getCause() instanceof FileNotFoundException
|
|
|| error.getCause() == null);
|
|
if (error.getCause() != null) {
|
|
verifySuppressedException(error, UnsatisfiedLinkError.class);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testFileNotFoundWithNullClassLoader() {
|
|
try {
|
|
NativeLibraryLoader.load(UUID.randomUUID().toString(), null);
|
|
fail();
|
|
} catch (UnsatisfiedLinkError error) {
|
|
assertTrue(error.getCause() instanceof FileNotFoundException
|
|
|| error.getCause() == null);
|
|
if (error.getCause() != null) {
|
|
verifySuppressedException(error, ClassNotFoundException.class);
|
|
}
|
|
}
|
|
}
|
|
|
|
@SuppressJava6Requirement(reason = "uses Java 7+ Throwable#getSuppressed but is guarded by version checks")
|
|
private static void verifySuppressedException(UnsatisfiedLinkError error,
|
|
Class<?> expectedSuppressedExceptionClass) {
|
|
try {
|
|
Throwable[] suppressed = error.getCause().getSuppressed();
|
|
assertTrue(suppressed.length == 1);
|
|
assertTrue(suppressed[0] instanceof UnsatisfiedLinkError);
|
|
suppressed = (suppressed[0]).getSuppressed();
|
|
assertTrue(suppressed.length == 1);
|
|
assertTrue(expectedSuppressedExceptionClass.isInstance(suppressed[0]));
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testPatchingId() throws IOException {
|
|
testPatchingId0(true, false);
|
|
}
|
|
|
|
@Test
|
|
public void testPatchingIdWithOsArch() throws IOException {
|
|
testPatchingId0(true, true);
|
|
}
|
|
|
|
@Test
|
|
public void testPatchingIdNotMatch() throws IOException {
|
|
testPatchingId0(false, false);
|
|
}
|
|
|
|
@Test
|
|
public void testPatchingIdWithOsArchNotMatch() throws IOException {
|
|
testPatchingId0(false, true);
|
|
}
|
|
|
|
private static void testPatchingId0(boolean match, boolean withOsArch) throws IOException {
|
|
byte[] bytes = new byte[1024];
|
|
ThreadLocalRandom.current().nextBytes(bytes);
|
|
byte[] idBytes = ("/workspace/netty-tcnative/boringssl-static/target/" +
|
|
"native-build/target/lib/libnetty_tcnative-2.0.20.Final.jnilib").getBytes(CharsetUtil.UTF_8);
|
|
|
|
String originalName;
|
|
if (match) {
|
|
originalName = "netty-tcnative";
|
|
} else {
|
|
originalName = "nonexist_tcnative";
|
|
}
|
|
String name = "shaded_" + originalName;
|
|
if (withOsArch) {
|
|
name += "_osx_x86_64";
|
|
}
|
|
|
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
out.write(bytes, 0, bytes.length);
|
|
out.write(idBytes, 0, idBytes.length);
|
|
out.write(bytes, 0 , bytes.length);
|
|
|
|
out.flush();
|
|
byte[] inBytes = out.toByteArray();
|
|
out.close();
|
|
|
|
InputStream inputStream = new ByteArrayInputStream(inBytes);
|
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
try {
|
|
assertEquals(match,
|
|
NativeLibraryLoader.patchShadedLibraryId(inputStream, outputStream, originalName, name));
|
|
|
|
outputStream.flush();
|
|
byte[] outputBytes = outputStream.toByteArray();
|
|
assertArrayEquals(bytes, Arrays.copyOfRange(outputBytes, 0, bytes.length));
|
|
byte[] patchedId = Arrays.copyOfRange(outputBytes, bytes.length, bytes.length + idBytes.length);
|
|
assertEquals(!match, Arrays.equals(idBytes, patchedId));
|
|
assertArrayEquals(bytes,
|
|
Arrays.copyOfRange(outputBytes, bytes.length + idBytes.length, outputBytes.length));
|
|
assertEquals(inBytes.length, outputBytes.length);
|
|
} finally {
|
|
inputStream.close();
|
|
outputStream.close();
|
|
}
|
|
}
|
|
}
|