blob: d9789ae800ed55b3d0d3fed3a448e6a05e762893 [file] [log] [blame]
package org.eclipse.indigo.tests.repos;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import junit.framework.Test;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.query.IQueryResult;
public class VersionChecking extends TestRepo {
private static final String EQUALS = "equals";
private static final String STARTS_WITH = "startsWith";
private static final int STARTWITH_MATCH_LENGTH = 5;
/**
* The test setup in this suite method is atypical, but handy do to local
* testing from workbench. For production work, currently, the values are
* set in ant execute method. If/when converted to true JUnit tests, this
* suite method will need to be chaanged to a more typical form, and no
* value hard coded.
*/
public static Test suite() {
System.out.println("test version checking");
VersionChecking test = new VersionChecking();
test.setName("testVersionUniqness");
test.setRepoURLToTest("file:///home/shared/webtools/testStagingRepo");
test.setOutputDirectory("/home/davidw/temp");
return test;
}
public boolean testVersionUniqness() throws URISyntaxException, ProvisionException, OperationCanceledException, IOException {
IQueryResult<IInstallableUnit> allIUs = getAllIUs();
analyzeVersionPatterns(allIUs);
return analyzeNonUniqueVersions(allIUs);
}
private void analyzeVersionPatterns(IQueryResult<IInstallableUnit> allIUs) throws IOException {
FileWriter outfileWriter = null;
File outfile = null;
String testDirName = getOutputDirectory();
try {
outfile = new File(testDirName, "versionPatterns.txt");
outfileWriter = new FileWriter(outfile);
System.out.println("output: " + outfile.getAbsolutePath());
outfileWriter.write("Version qualifer patterns used in repository" + EOL + EOL);
outfileWriter.write("Repository ('repoURLToTest'): " + getRepoURLToTest() + EOL + EOL);
outfileWriter.write("(Exploratory report ... maybe eventually used to find typos, such as 'qualfer')" + EOL + EOL);
List<String> allQualifiers = collectQualifiers(allIUs, outfileWriter);
collapseSortedQualifiers(outfileWriter, allQualifiers);
}
finally {
if (outfileWriter != null) {
try {
outfileWriter.close();
}
catch (IOException e) {
// would be weird
e.printStackTrace();
}
}
}
}
private void collapseSortedQualifiers(FileWriter outfileWriter, List<String> allQualifiers) throws IOException, Error {
String reference = null;
int refCount = 0;
String type = EQUALS;
Collections.sort(allQualifiers);
outfileWriter.write(EOL + "Count of (sorted) patterns matching up to " + STARTWITH_MATCH_LENGTH + " characters." + EOL + EOL);
for (String q : allQualifiers) {
if (reference == null) {
reference = q;
refCount = 1;
}
else {
if (reference.equals(q)) {
refCount++;
type = EQUALS;
}
else {
if (reference.length() == 0) {
reference = "[empty string]";
outfileWriter.write(refCount + "\t" + type + "\t\t\t" + reference + EOL);
reference = q;
refCount = 1;
type = EQUALS;
}
else if (startsSimilar(reference, q)) {
refCount++;
type = STARTS_WITH;
}
else {
if (STARTS_WITH.equals(type)) {
outfileWriter.write(refCount + "\t" + type + "\t\t" + subsection(reference) + EOL);
}
else if (EQUALS.equals(type)) {
outfileWriter.write(refCount + "\t" + type + "\t\t\t" + reference + EOL);
}
else {
throw new Error();
}
reference = q;
refCount = 1;
type = EQUALS;
}
}
}
}
}
private List<String> collectQualifiers(IQueryResult<IInstallableUnit> allIUs, FileWriter outfileWriter) throws IOException, Error {
List<String> allQualifiers = new ArrayList();
int nonOSGiCompatible = 0;
int nLessThanFour = 0;
int nMoreThanFour = 0;
for (IInstallableUnit iu : allIUs.toUnmodifiableSet()) {
// exclude categories, since they are (often) intended to work with same ID, multiple versions
boolean isCategory = "true".equals(iu.getProperty("org.eclipse.equinox.p2.type.category"));
// we exclude these things in some other repo reports ... to improve focus ... but suspect not needed here.
// boolean isFragment = "true".equals(iu.getProperty("org.eclipse.equinox.p2.type.fragment"));
// !isFragment && !isFeatureGroup(iu)
if (!isCategory && !isSpecial(iu)) {
//String bundleId = iu.getId();
Version bundleVersion = iu.getVersion();
if (bundleVersion.isOSGiCompatible()) {
if (bundleVersion.getSegmentCount() == 4) {
Comparable qualifier = bundleVersion.getSegment(3);
if (qualifier instanceof String) {
String qString = (String) qualifier;
if (qString.length() == 0) {
outfileWriter.write("zero length 4th segment: " + iu.getId() + EOL);
}
allQualifiers.add(qString);
}
else {
throw new Error("Program Error");
}
}
else if (bundleVersion.getSegmentCount() < 4) {
nLessThanFour++;
}
else if (bundleVersion.getSegmentCount() > 4) {
nMoreThanFour++;
}
}
else {
nonOSGiCompatible++;
}
}
}
outfileWriter.write(EOL + "Number of nonOSGi compatible versions: " + nonOSGiCompatible + EOL);
outfileWriter.write(EOL + "Number with more than 4 segments: " + nMoreThanFour + EOL);
outfileWriter.write(EOL + "Number wtih less than 4 segments: " + nLessThanFour + EOL + EOL);
return allQualifiers;
}
private boolean startsSimilar(String reference, String q) {
return (q.startsWith(subsection(reference)));
}
private String subsection(String reference) {
// length = endOffset - startOffset;
String result = reference;
if (reference.length() >= STARTWITH_MATCH_LENGTH) {
result = (reference.substring(0, STARTWITH_MATCH_LENGTH));
}
return result;
}
private boolean analyzeNonUniqueVersions(IQueryResult<IInstallableUnit> allIUs) throws IOException {
Map bundles = tabulateNonUniqueIDs(allIUs);
FileWriter outfileWriter = null;
File outfile = null;
String testDirName = getOutputDirectory();
try {
outfile = new File(testDirName, "nonUniqueVersions.txt");
outfileWriter = new FileWriter(outfile);
System.out.println("output: " + outfile.getAbsolutePath());
outfileWriter.write("Non Unique Versions used in repository" + EOL + EOL);
outfileWriter.write("Repository ('repoURLToTest'): " + getRepoURLToTest() + EOL + EOL);
int nUnique = 0;
for (Object bundleId : bundles.keySet()) {
Set versionSet = (Set) bundles.get(bundleId);
if (versionSet.size() == 1) {
nUnique++;
}
else {
printId(outfileWriter, bundleId);
for (Object version : versionSet) {
printVersion(outfileWriter, version);
}
}
}
outfileWriter.write(EOL + "Number of unique id-versions " + nUnique + EOL);
// always return false (no error), for now ... eventually may be able to
// figure out some heuristic to return "error", such as if new, non-expected multiple versions
return false;
}
finally {
if (outfileWriter != null) {
try {
outfileWriter.close();
}
catch (IOException e) {
// would be weird
e.printStackTrace();
}
}
}
}
private Map tabulateNonUniqueIDs(IQueryResult<IInstallableUnit> allIUs) {
Map bundles = new HashMap();
for (IInstallableUnit iu : allIUs.toUnmodifiableSet()) {
try {
// exclude categories, since they are (often) intended to work with same ID, multiple versions
boolean isCategory = "true".equals(iu.getProperty("org.eclipse.equinox.p2.type.category"));
// we exclude these things in some other repo reports ... to improve focus ... but suspect not needed here.
//boolean isFragment = "true".equals(iu.getProperty("org.eclipse.equinox.p2.type.fragment"));
// && !isSpecial(iu) && !isFragment && !isFeatureGroup(iu)
if (!isCategory) {
String bundleId = iu.getId();
Version bundleVersion = iu.getVersion();
// if bundle ID is already in map, we must have already found at least one
if (bundles.containsKey(bundleId)) {
Set versionSet = (Set) bundles.get(bundleId);
versionSet.add(bundleVersion);
}
else {
// haven't found one yet, so add it, with initial set of its (one) version
Set versionSet = new HashSet();
versionSet.add(bundleVersion);
bundles.put(bundleId, versionSet);
}
}
}
catch (RuntimeException e) {
e.printStackTrace();
}
}
return bundles;
}
private void printId(FileWriter out, Object id) throws IOException {
out.write(id + EOL);
}
private void printVersion(FileWriter out, Object version) throws IOException {
out.write("\t" + version + EOL);
}
}