GEODE-27: Adding a test to verify the bundled jars have not changed This allows us to make sure we don't accidentally start shipping jars that we didn't intend to.
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/db17e38c Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/db17e38c Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/db17e38c Branch: refs/heads/develop Commit: db17e38cc6c66729573d8d91de2c1b61f47f2620 Parents: 02b95b4 Author: Dan Smith <[email protected]> Authored: Tue Mar 15 14:43:07 2016 -0700 Committer: Dan Smith <[email protected]> Committed: Fri Mar 18 13:43:55 2016 -0700 ---------------------------------------------------------------------- .../gemstone/gemfire/BundledJarsJUnitTest.java | 129 +++++++++++++++++++ .../src/test/resources/expected_jars.txt | 82 ++++++++++++ 2 files changed, 211 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/db17e38c/geode-assembly/src/test/java/com/gemstone/gemfire/BundledJarsJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-assembly/src/test/java/com/gemstone/gemfire/BundledJarsJUnitTest.java b/geode-assembly/src/test/java/com/gemstone/gemfire/BundledJarsJUnitTest.java new file mode 100644 index 0000000..8ae3b22 --- /dev/null +++ b/geode-assembly/src/test/java/com/gemstone/gemfire/BundledJarsJUnitTest.java @@ -0,0 +1,129 @@ +/* + * 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 com.gemstone.gemfire; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.jar.JarFile; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.gemstone.gemfire.internal.FileUtil; +import com.gemstone.gemfire.test.junit.categories.UnitTest; +import com.gemstone.gemfire.util.test.TestUtil; + +@Category(UnitTest.class) +public class BundledJarsJUnitTest { + + private static final String VERSION_PATTERN = "[0-9-_.v]{3,}.*\\.jar$"; + protected static final String GEMFIRE_HOME = System.getenv("GEMFIRE"); + private Set<String> expectedJars; + + @Before + public void loadExpectedJars() throws IOException { + String expectedJarFile = TestUtil.getResourcePath(BundledJarsJUnitTest.class, "/expected_jars.txt"); + + expectedJars = Files.lines(Paths.get(expectedJarFile)) + .collect(Collectors.toSet()); + } + + @Test + public void verifyBundledJarsHaveNotChanged() throws IOException { + TreeMap<String, String> sortedJars = getBundledJars(); + Stream<String> lines = sortedJars.entrySet().stream().map(entry -> removeVersion(entry.getKey())); + Set<String> bundledJarNames = new TreeSet<String>(lines.collect(Collectors.toSet())); + + Files.write(Paths.get("bundled_jars.txt"), bundledJarNames); + + TreeSet<String> newJars = new TreeSet<String>(bundledJarNames); + newJars.removeAll(expectedJars); + TreeSet<String> missingJars = new TreeSet<String>(expectedJars); + missingJars.removeAll(bundledJarNames); + + StringBuilder message = new StringBuilder(); + message.append("The bundled jars have changed. Please make sure you update the licence and notice"); + message.append("\nas described in https://cwiki.apache.org/confluence/display/GEODE/License+Guide+for+Contributors"); + message.append("\nWhen fixed, copy geode-assembly/build/test/bundled_jars.txt"); + message.append("\nto src/test/resources/expected_jars.txt"); + message.append("\nRemoved Jars\n--------------\n"); + message.append(String.join("\n", missingJars)); + message.append("\n\nAdded Jars\n--------------\n"); + message.append(String.join("\n", newJars)); + message.append("\n\n"); + + assertTrue(message.toString(), expectedJars.equals(bundledJarNames)); + + } + + /** + * Find all of the jars bundled with the project. + * Key is the name of the jar, value is the path. + */ + protected TreeMap<String, String> getBundledJars() { + File gemfireHomeDirectory= new File(GEMFIRE_HOME); + + assertTrue("Please set the GEMFIRE environment variable to the product installation directory.", + gemfireHomeDirectory.isDirectory()); + + List<File> jars = FileUtil.findAll(gemfireHomeDirectory, ".*\\.jar"); + TreeMap<String, String> sortedJars = new TreeMap<String, String>(); + jars.stream().forEach(jar -> sortedJars.put(jar.getName(), jar.getPath())); + + List<File> wars = FileUtil.findAll(gemfireHomeDirectory, ".*\\.war"); + TreeSet<File> sortedWars = new TreeSet<File>(wars); + sortedWars.stream().flatMap(BundledJarsJUnitTest::extractJarNames) + .forEach(jar -> sortedJars.put(jar.getName(), jar.getPath())); + + sortedJars.keySet().removeIf(s -> s.startsWith("geode")); + return sortedJars; + } + + private String removeVersion(String name) { + return name.replaceAll(VERSION_PATTERN, ""); + } + + /** + * Find of of the jar files embedded within a war + */ + private static Stream<File> extractJarNames(File war) { + try (JarFile warContents = new JarFile(war)) { + return warContents.stream() + //Look for jars in the war + .filter(entry -> entry.getName().endsWith(".jar")) + //Create a File with a path that includes the war name + .map(entry -> new File(war.getName(), entry.getName())) + //Materialize the list of files while the war is still open + .collect(Collectors.toList()).stream(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/db17e38c/geode-assembly/src/test/resources/expected_jars.txt ---------------------------------------------------------------------- diff --git a/geode-assembly/src/test/resources/expected_jars.txt b/geode-assembly/src/test/resources/expected_jars.txt new file mode 100644 index 0000000..a566c4d --- /dev/null +++ b/geode-assembly/src/test/resources/expected_jars.txt @@ -0,0 +1,82 @@ +activation +antlr +classmate +commons-beanutils +commons-collections +commons-digester +commons-fileupload +commons-io +commons-lang +commons-logging +commons-modeler +fastutil +findbugs-annotations +gfsh-dependencies.jar +guava +jackson-annotations +jackson-core +jackson-databind +jackson-module-scala +jansi +javax.mail-api +javax.resource-api +javax.servlet-api +javax.transaction-api +jetty-http +jetty-io +jetty-security +jetty-server +jetty-servlet +jetty-util +jetty-webapp +jetty-xml +jgroups +jline +jna +json4s-ast +json4s-core +json4s-ext +json4s-jackson +json4s-native +log4j-api +log4j-core +log4j-jcl +log4j-jul +log4j-slf4j-impl +lucene-analyzers-common +lucene-core +lucene-queries +lucene-queryparser +mx4j +mx4j-remote +mx4j-tools +netty-all +paranamer +ra.jar +scala-library +scala-reflect +slf4j-api +snappy-java +spring-aop +spring-aspects +spring-beans +spring-context +spring-context-support +spring-core +spring-data-commons +spring-data-gemfire +spring-expression +spring-hateoas +spring-ldap-core +spring-oxm +spring-security-config +spring-security-core +spring-security-ldap +spring-security-web +spring-shell +spring-tx +spring-web +spring-webmvc +swagger-annotations +swagger-core +swagger-springmvc
