You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by ch...@apache.org on 2022/09/15 10:31:21 UTC
[flink] 01/02: [FLINK-29287][tests] Add PackagingTestUtils
This is an automated email from the ASF dual-hosted git repository.
chesnay pushed a commit to branch release-1.16
in repository https://gitbox.apache.org/repos/asf/flink.git
commit c4d254a92a2346a5d29da9f41c4df0022d6c2f36
Author: Chesnay Schepler <ch...@apache.org>
AuthorDate: Tue Sep 13 18:26:15 2022 +0200
[FLINK-29287][tests] Add PackagingTestUtils
---
.../apache/flink/packaging/PackagingTestUtils.java | 104 ++++++++++++++++
.../flink/packaging/PackagingTestUtilsTest.java | 134 +++++++++++++++++++++
2 files changed, 238 insertions(+)
diff --git a/flink-test-utils-parent/flink-test-utils/src/main/java/org/apache/flink/packaging/PackagingTestUtils.java b/flink-test-utils-parent/flink-test-utils/src/main/java/org/apache/flink/packaging/PackagingTestUtils.java
new file mode 100644
index 00000000000..69cc2faa4ca
--- /dev/null
+++ b/flink-test-utils-parent/flink-test-utils/src/main/java/org/apache/flink/packaging/PackagingTestUtils.java
@@ -0,0 +1,104 @@
+/*
+ * 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.flink.packaging;
+
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/** Test utils around jar packaging. */
+public class PackagingTestUtils {
+
+ /**
+ * Verifies that all files in the jar match one of the provided allow strings.
+ *
+ * <p>An allow item ending on a {@code "/"} is treated as an allowed parent directory.
+ * Otherwise, it is treated as an allowed file.
+ *
+ * <p>For example, given a jar containing a file {@code META-INF/NOTICES}:
+ *
+ * <p>These would pass:
+ *
+ * <ul>
+ * <li>{@code "META-INF/"}
+ * <li>{@code "META-INF/NOTICES"}
+ * </ul>
+ *
+ * <p>These would fail:
+ *
+ * <ul>
+ * <li>{@code "META-INF"}
+ * <li>{@code "META-INF/NOTICE"}
+ * <li>{@code "META-INF/NOTICES/"}
+ * </ul>
+ */
+ public static void assertJarContainsOnlyFilesMatching(
+ Path jarPath, Collection<String> allowedPaths) throws Exception {
+ final URI jar = jarPath.toUri();
+
+ try (final FileSystem fileSystem =
+ FileSystems.newFileSystem(
+ new URI("jar:file", jar.getHost(), jar.getPath(), jar.getFragment()),
+ Collections.emptyMap())) {
+ try (Stream<Path> walk = Files.walk(fileSystem.getPath("/"))) {
+ walk.filter(file -> !Files.isDirectory(file))
+ .map(file -> file.toAbsolutePath().toString())
+ .map(file -> file.startsWith("/") ? file.substring(1) : file)
+ .forEach(
+ file ->
+ assertThat(allowedPaths)
+ .as("Bad file in JAR: %s", file)
+ .anySatisfy(
+ allowedPath -> {
+ if (allowedPath.endsWith("/")) {
+ assertThat(file)
+ .startsWith(allowedPath);
+ } else {
+ assertThat(file)
+ .isEqualTo(allowedPath);
+ }
+ }));
+ }
+ }
+ }
+
+ /**
+ * Verifies that the given jar contains a service entry file for the given service.
+ *
+ * <p>Caution: This only checks that the file exists; the content is not verified.
+ */
+ public static void assertJarContainsServiceEntry(Path jarPath, Class<?> service)
+ throws Exception {
+ final URI jar = jarPath.toUri();
+
+ try (final FileSystem fileSystem =
+ FileSystems.newFileSystem(
+ new URI("jar:file", jar.getHost(), jar.getPath(), jar.getFragment()),
+ Collections.emptyMap())) {
+ assertThat(fileSystem.getPath("META-INF", "services", service.getName())).exists();
+ }
+ }
+}
diff --git a/flink-test-utils-parent/flink-test-utils/src/test/java/org/apache/flink/packaging/PackagingTestUtilsTest.java b/flink-test-utils-parent/flink-test-utils/src/test/java/org/apache/flink/packaging/PackagingTestUtilsTest.java
new file mode 100644
index 00000000000..451693c38dd
--- /dev/null
+++ b/flink-test-utils-parent/flink-test-utils/src/test/java/org/apache/flink/packaging/PackagingTestUtilsTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.flink.packaging;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+class PackagingTestUtilsTest {
+
+ @Test
+ void testAssertJarContainsOnlyFilesMatching(@TempDir Path tmp) throws Exception {
+ Path jar = createJar(tmp, Entry.fileEntry("", Arrays.asList("META-INF", "NOTICES")));
+
+ PackagingTestUtils.assertJarContainsOnlyFilesMatching(
+ jar, Collections.singleton("META-INF/"));
+ PackagingTestUtils.assertJarContainsOnlyFilesMatching(
+ jar, Collections.singleton("META-INF/NOTICES"));
+
+ assertThatThrownBy(
+ () ->
+ PackagingTestUtils.assertJarContainsOnlyFilesMatching(
+ jar, Collections.singleton("META-INF")))
+ .isInstanceOf(AssertionError.class);
+ assertThatThrownBy(
+ () ->
+ PackagingTestUtils.assertJarContainsOnlyFilesMatching(
+ jar, Collections.singleton("META-INF/NOTICE")))
+ .isInstanceOf(AssertionError.class);
+ assertThatThrownBy(
+ () ->
+ PackagingTestUtils.assertJarContainsOnlyFilesMatching(
+ jar, Collections.singleton("META-INF/NOTICES/")))
+ .isInstanceOf(AssertionError.class);
+ }
+
+ @Test
+ void testAssertJarContainsServiceEntry(@TempDir Path tmp) throws Exception {
+ final String service = PackagingTestUtilsTest.class.getName();
+ Path jar =
+ createJar(tmp, Entry.fileEntry("", Arrays.asList("META-INF", "services", service)));
+
+ PackagingTestUtils.assertJarContainsServiceEntry(jar, PackagingTestUtilsTest.class);
+
+ assertThatThrownBy(
+ () ->
+ PackagingTestUtils.assertJarContainsServiceEntry(
+ jar, PackagingTestUtils.class))
+ .isInstanceOf(AssertionError.class);
+ }
+
+ private static class Entry {
+ final String contents;
+ final List<String> path;
+ final boolean isDirectory;
+
+ public static Entry directoryEntry(List<String> path) {
+ return new Entry("", path, true);
+ }
+
+ public static Entry fileEntry(String contents, List<String> path) {
+ return new Entry(contents, path, false);
+ }
+
+ private Entry(String contents, List<String> path, boolean isDirectory) {
+ this.contents = contents;
+ this.path = path;
+ this.isDirectory = isDirectory;
+ }
+ }
+
+ private static Path createJar(Path tempDir, Entry... entries) throws Exception {
+ final Path path = tempDir.resolve(UUID.randomUUID().toString() + ".jar");
+
+ final URI uri = path.toUri();
+
+ final URI jarUri = new URI("jar:file", uri.getHost(), uri.getPath(), uri.getFragment());
+
+ // causes FileSystems#newFileSystem to automatically create a valid zip file
+ // this is easier than manually creating a valid empty zip file manually
+ final Map<String, String> env = new HashMap<>();
+ env.put("create", "true");
+
+ try (FileSystem zip = FileSystems.newFileSystem(jarUri, env)) {
+ // shortcut to getting the single root
+ final Path root = zip.getPath("/");
+ for (Entry entry : entries) {
+ final Path zipPath =
+ root.resolve(
+ zip.getPath(
+ entry.path.get(0),
+ entry.path
+ .subList(1, entry.path.size())
+ .toArray(new String[] {})));
+ if (entry.isDirectory) {
+ Files.createDirectories(zipPath);
+ } else {
+ Files.createDirectories(zipPath.getParent());
+ Files.write(zipPath, entry.contents.getBytes());
+ }
+ }
+ }
+ return path;
+ }
+}