Skip to content

Commit

Permalink
fixed classpath traversal in general and for gradle ref #520
Browse files Browse the repository at this point in the history
  • Loading branch information
ptrthomas committed Sep 8, 2018
1 parent ec63ef0 commit 6ea511d
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 100 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ target/
.settings
.classpath
*.iml
build/
.gradle
gradle
gradlew
gradlew.*
karate-demo/activemq-data/
karate-netty/dependency-reduced-pom.xml
karate-junit4/src/test/java/com/intuit/karate/junit4/dev
Expand Down
99 changes: 56 additions & 43 deletions karate-core/src/main/java/com/intuit/karate/FileUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
import com.intuit.karate.core.Feature;
import com.intuit.karate.core.FeatureParser;
import java.net.URI;
import java.net.URL;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Properties;
import java.util.stream.Stream;
Expand All @@ -39,7 +41,7 @@ public class FileUtils {
public static final Charset UTF8 = StandardCharsets.UTF_8;

private static final String CLASSPATH = "classpath";

public static final String CLASSPATH_COLON = CLASSPATH + ":";
public static final String FILE_COLON = "file:";
public static final String SRC_TEST_JAVA = "src/test/java";
Expand Down Expand Up @@ -111,6 +113,9 @@ public static ScriptValue readFile(String text, ScenarioContext context) {
}

public static String removePrefix(String text) {
if (text == null) {
return null;
}
int pos = text.indexOf(':');
return pos == -1 ? text : text.substring(pos + 1);
}
Expand Down Expand Up @@ -312,42 +317,15 @@ public static void renameFileIfZeroBytes(String fileName) {
}
}

private static Path getPathFor(String pathString) {
pathString = pathString == null ? "." : pathString.trim();
try {
URI uri;
if (isClassPath(pathString)) {
pathString = removePrefix(pathString);
if (pathString.charAt(0) != '/') {
pathString = '/' + pathString;
}
uri = FileUtils.class.getResource(pathString).toURI();
} else {
if (isFilePath(pathString)) {
pathString = removePrefix(pathString);
}
uri = new File(pathString).toURI();
}
if (uri.getScheme().equals("jar")) {
FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.<String, Object>emptyMap());
return fileSystem.getPath(pathString);
} else {
return Paths.get(uri);
public static String toRelativeClassPath(File file) {
Path path = file.toPath();
for (Path rootPath : getAllClassPaths()) {
if (path.startsWith(rootPath)) {
Path relativePath = rootPath.relativize(path);
return CLASSPATH_COLON + relativePath.toString();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private static final String CLASSPATH_COLON_SLASH = CLASSPATH_COLON + "/";

private static Path getClassPathRoot() {
return getPathFor(CLASSPATH_COLON_SLASH);
}

public static String toRelativeClassPath(File file) {
Path rootPath = getClassPathRoot();
return CLASSPATH_COLON + rootPath.relativize(Paths.get(file.getAbsolutePath())).toString();
return null;
}

public static File getDirContaining(Class clazz) {
Expand Down Expand Up @@ -377,25 +355,61 @@ public static File fromRelativeClassPath(String relativePath) {
}

public static List<FileResource> scanForFeatureFilesOnClassPath() {
return scanForFeatureFiles(CLASSPATH_COLON_SLASH);
return scanForFeatureFiles(true, CLASSPATH_COLON);
}

public static List<FileResource> scanForFeatureFiles(List<String> paths) {
List<FileResource> list = new ArrayList();
for (String path : paths) {
list.addAll(scanForFeatureFiles(path));
boolean classpath = isClassPath(path);
list.addAll(scanForFeatureFiles(classpath, path));
}
return list;
}

public static List<FileResource> scanForFeatureFiles(String pathString) {
boolean classpath = isClassPath(pathString);
Path rootPath = classpath ? getClassPathRoot() : getPathFor(null);
Path thisPath = getPathFor(pathString);
public static List<Path> getAllClassPaths() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
try {
List<Path> list = new ArrayList();
Enumeration<URL> iterator = cl.getResources("");
while (iterator.hasMoreElements()) {
URL url = iterator.nextElement();
list.add(Paths.get(url.toURI()));
}
return list;
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public static List<FileResource> scanForFeatureFiles(boolean classpath, String searchPath) {
List<FileResource> files = new ArrayList();
if (classpath) {
searchPath = removePrefix(searchPath);
for (Path rootPath : getAllClassPaths()) {
collectFeatureFiles(rootPath, searchPath, files);
}
} else {
collectFeatureFiles(null, searchPath, files);
}
return files;
}

private static void collectFeatureFiles(Path rootPath, String searchPath, List<FileResource> files) {
boolean classpath = rootPath != null;
Path search;
if (classpath) {
search = rootPath.resolve(searchPath);
if (!search.toFile().exists()) {
return;
}
} else {
rootPath = new File("").toPath();
search = new File(searchPath).toPath();
}
Stream<Path> stream;
try {
stream = Files.walk(thisPath);
stream = Files.walk(search);
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand All @@ -408,7 +422,6 @@ public static List<FileResource> scanForFeatureFiles(String pathString) {
files.add(new FileResource(file, prefix + relativePath.toString()));
}
}
return files;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public static KarateStats parallel(String tagSelector, List<FileResource> resour
public static KarateStats parallel(String tagSelector, List<FileResource> resources, ExecutionHook hook, int threadCount, String reportDir) {
if (reportDir == null) {
reportDir = Engine.getBuildDir() + File.separator + "surefire-reports";
new File(reportDir).mkdirs();
}
final String finalReportDir = reportDir;
logger.info("Karate version: {}", FileUtils.getKarateVersion());
Expand Down Expand Up @@ -152,6 +153,7 @@ public static KarateStats parallel(String tagSelector, List<FileResource> resour
}
stats.setFeatureCount(executedFeatureCount);
stats.printStats(threadCount);
stats.setReportDir(reportDir);
return stats;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public class KarateStats {
private long endTime;
private Map<String, String> failedMap;
private Throwable failureReason;
private String reportDir;

private KarateStats(long startTime) {
this.startTime = startTime;
Expand All @@ -57,6 +58,14 @@ public static KarateStats startTimer() {
return new KarateStats(System.currentTimeMillis());
}

public String getReportDir() {
return reportDir;
}

public void setReportDir(String reportDir) {
this.reportDir = reportDir;
}

public void setFailureReason(Throwable failureReason) {
this.failureReason = failureReason;
}
Expand Down
14 changes: 13 additions & 1 deletion karate-core/src/test/java/com/intuit/karate/FileUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public void testRenameZeroLengthFile() {
}

@Test
public void testScanFiles() {
public void testScanFile() {
String relativePath = "classpath:com/intuit/karate/ui/test.feature";
List<FileResource> files = FileUtils.scanForFeatureFilesOnClassPath();
boolean found = false;
Expand All @@ -51,9 +51,21 @@ public void testScanFiles() {
assertTrue(found);
}

@Test
public void testScanFilePath() {
String relativePath = "classpath:com/intuit/karate/ui";
List<FileResource> files = FileUtils.scanForFeatureFiles(true, relativePath);
assertEquals(2, files.size());
}

@Test
public void testRelativePathForClass() {
assertEquals("classpath:com/intuit/karate", FileUtils.toRelativeClassPath(getClass()));
}

@Test
public void testGetAllClasspaths() {
FileUtils.getAllClassPaths();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ public class AllKarateFeaturesTest {

@Test
public void testParsingAllFeaturesInKarate() {
List<FileResource> files = FileUtils.scanForFeatureFiles("..");
List<FileResource> files = FileUtils.scanForFeatureFiles(false, "..");
for (FileResource file : files) {
logger.trace("parsing: {}", file.relativePath);
logger.debug("parsing: {}", file.relativePath);
FeatureParser.parse(file.file, file.relativePath);
}
}
Expand Down
99 changes: 55 additions & 44 deletions karate-demo/build.gradle
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
buildscript {
ext {
springBootVersion = '1.5.3.RELEASE'
gradleVersionProperty = '4.1'
karateVersion = '0.5.0'
masterThought = '3.8.0'
}
ext {
springBootVersion = '1.5.3.RELEASE'
springVersion = '4.3.8.RELEASE'
gradleVersionProperty = '4.1'
karateVersion = '0.9.0'
masterThoughtVersion = '3.8.0'
activeMqVersion = '5.15.2'
}
repositories {
maven { url 'https://plugins.gradle.org/m2/' }
maven { url "http://repo.spring.io/release" }
maven { url "http://repo.spring.io/milestone" }
maven { url "http://repo.spring.io/snapshot" }
maven { url "http://repo.spring.io/release" }
maven { url "http://repo.spring.io/milestone" }
maven { url "http://repo.spring.io/snapshot" }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}

apply plugin: 'eclipse'
Expand All @@ -22,57 +24,62 @@ apply plugin: 'idea'
apply plugin: 'org.springframework.boot'

jar {
baseName = 'karate-demo'
version = '0.5.1'
baseName = 'karate-demo'
version = karateVersion
}

bootRun {
systemProperties = System.properties
systemProperties = System.properties
}

// In this section you declare where to find the dependencies of your project
repositories {
mavenLocal()
mavenCentral()
maven { url "http://repo.spring.io/release" }
maven { url "http://repo.spring.io/milestone" }
maven { url "http://repo.spring.io/snapshot" }
maven { url "http://repo.spring.io/milestone" }
maven { url "http://repo.spring.io/snapshot" }
}

sourceSets {
test {
java
{
// Excluding UIRunner files as these require the javafx libraries
// which are not shipped with OpenJDK. These UIRunner classes are
// classes that allow developers to run/debug karate tests via a UI
// and as such are not required for headless runs on jenkins server
// but can run happily via IDE of the developer without needed to be
// compiled by gradle.
srcDir file('src/test/java')
exclude '**/*UiRunner*.java'
}
java
{
// Excluding UIRunner files as these require the javafx libraries
// which are not shipped with OpenJDK. These UIRunner classes are
// classes that allow developers to run/debug karate tests via a UI
// and as such are not required for headless runs on jenkins server
// but can run happily via IDE of the developer without needed to be
// compiled by gradle.
srcDir file('src/test/java')
exclude '**/*UiRunner*.java'
}
resources
{
// Using recommended karate project layout where karate feature files
// and associated javascript resources sit in same /test/java folders
// as their java counterparts.
srcDir file('src/test/java')
exclude '**/*.java'
}
{
// Using recommended karate project layout where karate feature files
// and associated javascript resources sit in same /test/java folders
// as their java counterparts.
srcDir file('src/test/java')
exclude '**/*.java'
}
}
}

dependencies {
compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.boot:spring-boot-starter-security'
compile 'commons-io:commons-io:2.5'
compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.boot:spring-boot-starter-security'
compile 'org.springframework:spring-jdbc:' + springVersion
compile 'com.github.java-json-tools:json-schema-validator:2.2.8'
compile 'commons-io:commons-io:2.5'
runtime 'com.h2database:h2:1.4.196'
testCompile 'junit:junit'
testCompile 'com.intuit.karate:karate-junit4:' + karateVersion
testCompile 'com.intuit.karate:karate-apache:' + karateVersion
testCompile 'net.masterthought:cucumber-reporting:' + masterThought
compile 'com.github.java-json-tools:json-schema-validator:2.2.8'

testCompile 'com.intuit.karate:karate-netty:' + karateVersion
testCompile 'org.apache.activemq:activemq-broker:' + activeMqVersion
testCompile 'org.apache.activemq:activemq-client:' + activeMqVersion
testCompile 'org.apache.activemq:activemq-kahadb-store:' + activeMqVersion
testCompile 'org.apache.geronimo.specs:geronimo-jms_1.1_spec:1.1.1'
testCompile 'net.masterthought:cucumber-reporting:' + masterThoughtVersion
}

test {
Expand All @@ -85,8 +92,12 @@ test {
systemProperty "karate.env", System.properties.getProperty("karate.env")
// Ensure tests are always run
outputs.upToDateWhen { false }
// attach debugger
if (System.getProperty('debug', 'false') == 'true') {
jvmArgs '-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=9009'
}
}

task wrapper(type: Wrapper) {
gradleVersion = gradleVersionProperty
task wrapper(type: Wrapper) {
gradleVersion = gradleVersionProperty
}
Loading

0 comments on commit 6ea511d

Please sign in to comment.