blob: e7582e95fb518de9f56c79b9fbe7b5e47d74e793 [file] [log] [blame]
/*
* 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.jmeter;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.jmeter.junit.JMeterTestCase;
import org.apache.jmeter.util.JMeterUtils;
import org.junit.Before;
import org.junit.Test;
/**
* Check the eclipse and Maven version definitions against build.properties
*/
public class JMeterVersionTest extends JMeterTestCase {
// Convert between eclipse jar name and build.properties name
private static Map<String, String> JAR_TO_BUILD_PROP = new HashMap<>();
static {
JAR_TO_BUILD_PROP.put("bsf", "apache-bsf");
JAR_TO_BUILD_PROP.put("bsh", "beanshell");
JAR_TO_BUILD_PROP.put("geronimo-jms_1.1_spec", "jms");
JAR_TO_BUILD_PROP.put("httpmime", "httpclient"); // two jars same version
JAR_TO_BUILD_PROP.put("mail", "javamail");
JAR_TO_BUILD_PROP.put("oro", "jakarta-oro");
JAR_TO_BUILD_PROP.put("xercesImpl", "xerces");
JAR_TO_BUILD_PROP.put("xpp3_min", "xpp3");
}
private static final File JMETER_HOME = new File(JMeterUtils.getJMeterHome());
/**
* Versions of all libraries mentioned in build.properties (except checkstyle-all)
*/
private final Map<String, String> versions = new HashMap<>();
/**
* Names of library.version entries in build.properties, excluding jars not bundled (used for docs only)
*/
private final Set<String> propNames = new HashSet<>();
/**
* License file names found under license/bin (WITHOUT the .txt suffix)
*/
private final Set<String> liceFiles = new HashSet<>();
private File getFileFromHome(String relativeFile) {
return new File(JMETER_HOME, relativeFile);
}
private Properties prop;
@Before
public void setUp() throws Exception {
final Properties buildProp = new Properties();
final FileInputStream bp = new FileInputStream(getFileFromHome("build.properties"));
buildProp.load(bp);
bp.close();
for (Entry<Object, Object> entry : buildProp.entrySet()) {
final String key = (String) entry.getKey();
if (key.endsWith(".version")) {
final String value = (String) entry.getValue();
final String jarprop = key.replace(".version","");
final String old = versions.put(jarprop, value);
propNames.add(jarprop);
if (old != null) {
fail("Already have entry for "+key);
}
}
}
// remove docs-only jars
propNames.remove("jdom");
propNames.remove("velocity");
propNames.remove("commons-lang"); // lang3 is bundled, lang2 is doc-only
// remove optional checkstyle name
propNames.remove("checkstyle-all"); // not needed in Maven
buildProp.remove("checkstyle-all.loc"); // not a Maven download
versions.remove("checkstyle-all");
// remove option RAT jars
propNames.remove("rat");
versions.remove("rat");
propNames.remove("rat-tasks");
versions.remove("rat-tasks");
prop = buildProp;
final File licencesDir = getFileFromHome("licenses/bin");
licencesDir.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
if (! name.equalsIgnoreCase("README.txt")
&& !name.equals(".svn")) { // Allow for old-style SVN workspaces
liceFiles.add(name.replace(".txt",""));
}
return false;
}
});
}
/**
* Check eclipse.classpath contains the jars declared in build.properties
* @throws Exception if something fails
*/
@Test
public void testEclipse() throws Exception {
final BufferedReader eclipse = new BufferedReader(
new FileReader(getFileFromHome("eclipse.classpath"))); // assume default charset is OK here
// <classpathentry kind="lib" path="lib/geronimo-jms_1.1_spec-1.1.1.jar"/>
// <classpathentry kind="lib" path="lib/activation-1.1.1.jar"/>
// <classpathentry kind="lib" path="lib/jtidy-r938.jar"/>
final Pattern p = Pattern.compile("\\s+<classpathentry kind=\"lib\" path=\"lib/(?:api/)?(.+?)-([^-]+(-b\\d+|-BETA\\d)?)\\.jar\"/>");
final Pattern versionPat = Pattern.compile("\\$\\{(.+)\\.version\\}");
String line;
final ArrayList<String> toRemove = new ArrayList<>();
while((line=eclipse.readLine()) != null){
final Matcher m = p.matcher(line);
if (m.matches()) {
String jar = m.group(1);
String version = m.group(2);
// System.out.println(jar + " => " + version);
if (jar.endsWith("-jdk15on")) { // special handling
jar=jar.replace("-jdk15on","");
} else if (jar.equals("commons-jexl") && version.startsWith("2")) { // special handling
jar="commons-jexl2";
} else {
String tmp = JAR_TO_BUILD_PROP.get(jar);
if (tmp != null) {
jar = tmp;
}
}
String expected = versions.get(jar);
if(expected == null) {
System.err.println("Didn't find version for jar name extracted by regexp, jar name extracted:"+jar+", version extracted:"+version+", current line:"+line);
fail("Didn't find version for jar name extracted by regexp, jar name extracted:"+jar+", version extracted:"+version+", current line:"+line);
}
// Process ${xxx.version} references
final Matcher mp = versionPat.matcher(expected);
if (mp.matches()) {
String key = mp.group(1);
expected = versions.get(key);
toRemove.add(key); // in case it is not itself used we remove it later
}
propNames.remove(jar);
if (expected == null) {
fail("Versions list does not contain: " + jar);
} else {
if (!version.equals(expected)) {
assertEquals(jar,version,expected);
}
}
}
}
// remove any possibly unused references
for(Object key : toRemove.toArray()) {
propNames.remove(key);
}
eclipse.close();
if (propNames.size() > 0) {
fail("Should have no names left: "+Arrays.toString(propNames.toArray()) + ". Check eclipse.classpath");
}
}
@Test
public void testMaven() throws Exception {
final BufferedReader maven = new BufferedReader(
new FileReader(getFileFromHome("res/maven/ApacheJMeter_parent.pom"))); // assume default charset is OK here
// <apache-bsf.version>2.4.0</apache-bsf.version>
final Pattern p = Pattern.compile("\\s+<([^\\.]+)\\.version>([^<]+)<.*");
String line;
while((line=maven.readLine()) != null){
final Matcher m = p.matcher(line);
if (m.matches()) {
String jar = m.group(1);
String version = m.group(2);
String expected = versions.get(jar);
propNames.remove(jar);
if (expected == null) {
fail("Versions list does not contain: " + jar);
} else {
if (!version.equals(expected)) {
assertEquals(jar,expected,version);
}
}
}
}
maven.close();
if (propNames.size() > 0) {
fail("Should have no names left: "+Arrays.toString(propNames.toArray()) + ". Check ApacheJMeter_parent.pom");
}
}
@Test
public void testLicences() {
Set<String> liceNames = new HashSet<>();
for (Map.Entry<String, String> me : versions.entrySet()) {
final String key = me.getKey();
liceNames.add(key+"-"+me.getValue());
}
assertTrue("Expected at least one license file", liceFiles.size() > 0);
for(String l : liceFiles) {
if (!liceNames.remove(l)) {
fail("Mismatched version in license file " + l);
}
}
}
@Test
public void testLICENSE() throws Exception {
HashSet<String> buildOnly = new HashSet<>();
buildOnly.addAll(Arrays.asList(new String[]{"bcprov","bcmail","bcpkix"}));
// Build set of names expected to be mentioned in LICENSE
final HashSet<String> binaryJarNames = new HashSet<>();
for(Map.Entry<String, String> me : versions.entrySet()) {
final String key = me.getKey();
final String jarName = key + "-" + me.getValue();
if (propNames.contains(key) && !buildOnly.contains(key)) {
binaryJarNames.add(jarName);
}
}
// Extract the jar names fron LICENSE
final BufferedReader license = new BufferedReader(
new FileReader(getFileFromHome("LICENSE"))); // assume default charset is OK here
final Pattern p = Pattern.compile("^\\* (\\S+?)\\.jar(.*)");
final HashSet<String> namesInLicenseFile = new HashSet<>(); // names documented in LICENSE
final HashSet<String> externalNamesinLicenseFile = new HashSet<>(); // names documented in LICENSE with licenses/bin entries
String line;
while((line=license.readLine()) != null){
final Matcher m = p.matcher(line);
if (m.matches()) {
final String name = m.group(1);
assertTrue("Duplicate jar in LICENSE file " + line, namesInLicenseFile.add(name));
if (!binaryJarNames.contains(name)) {
fail("Unexpected entry in LICENCE file: " + line);
}
final String comment = m.group(2);
if (comment.length() > 0) { // must be in external list
externalNamesinLicenseFile.add(name);
}
}
}
license.close();
// Check all build.properties entries are in LICENSE file
for(String s : binaryJarNames) {
if (!namesInLicenseFile.contains(s)) {
fail("LICENSE does not contain entry for " + s);
}
}
// Check that external license files are present
for(String s : externalNamesinLicenseFile) {
if (!liceFiles.contains(s)) {
fail("bin/licenses does not contain a file for " + s);
}
}
// Check that there are no license/bin files not mentioned in LICENSE
for(String s : liceFiles) {
if (!namesInLicenseFile.contains(s)) {
fail("LICENSE does not contain entry for " + s);
}
}
}
/**
* Check that all downloads use Maven Central
*/
@Test
public void testMavenDownload() {
int fails = 0;
for (Entry<Object, Object> entry : prop.entrySet()) {
final String key = (String) entry.getKey();
if (key.endsWith(".loc")) {
final String value = (String) entry.getValue();
if (! value.startsWith("${maven2.repo}")) {
fails++;
System.err.println("ERROR: non-Maven download detected\n" + key + "=" +value);
}
}
}
if (fails > 0) {
// TODO replace with fail()
System.err.println("ERROR: All files must be available from Maven Central; but " + fails + " use(s) a different download source");
}
}
}