mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 07:27:52 +01:00
Add junit rule for testing with node.
This commit is contained in:
parent
ffafeea189
commit
18841cf83d
163
test/de/inetsoftware/jwebassembly/WasmNodeRule.java
Normal file
163
test/de/inetsoftware/jwebassembly/WasmNodeRule.java
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 Volker Berlin (i-net software)
|
||||||
|
*
|
||||||
|
* Licensed 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 de.inetsoftware.jwebassembly;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
import org.junit.rules.TemporaryFolder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Junit Rule that compile the given classes and compare the results from node and Java.
|
||||||
|
*
|
||||||
|
* @author Volker Berlin
|
||||||
|
*/
|
||||||
|
public class WasmNodeRule extends TemporaryFolder {
|
||||||
|
|
||||||
|
private final Class<?>[] classes;
|
||||||
|
|
||||||
|
private File wasmFile;
|
||||||
|
|
||||||
|
private File scriptFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile the given classes to a Wasm and save it to a file.
|
||||||
|
*
|
||||||
|
* @param classes
|
||||||
|
* list of classes to compile
|
||||||
|
*/
|
||||||
|
public WasmNodeRule( Class<?>... classes ) {
|
||||||
|
if( classes == null || classes.length == 0 ) {
|
||||||
|
throw new IllegalArgumentException( "You need to set minimum one test class" );
|
||||||
|
}
|
||||||
|
this.classes = classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void before() throws Throwable {
|
||||||
|
super.before();
|
||||||
|
try {
|
||||||
|
wasmFile = newFile( "test.wasm" );
|
||||||
|
JWebAssembly wasm = new JWebAssembly();
|
||||||
|
for( Class<?> clazz : classes ) {
|
||||||
|
URL url = clazz.getResource( '/' + clazz.getName().replace( '.', '/' ) + ".class" );
|
||||||
|
wasm.addFile( url );
|
||||||
|
}
|
||||||
|
wasm.compileToBinary( wasmFile );
|
||||||
|
|
||||||
|
scriptFile = newFile( "test.js" );
|
||||||
|
URL scriptUrl = getClass().getResource( "nodetest.js" );
|
||||||
|
String expected = readStream( scriptUrl.openStream() );
|
||||||
|
expected = expected.replace( "{test.wasm}", wasmFile.getAbsolutePath().replace( '\\', '/' ) );
|
||||||
|
try (FileOutputStream scriptStream = new FileOutputStream( scriptFile )) {
|
||||||
|
scriptStream.write( expected.getBytes( StandardCharsets.UTF_8 ) );
|
||||||
|
}
|
||||||
|
} catch( Exception ex ) {
|
||||||
|
throwException( ex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a test single test. It run the method in Java and call it via node in the WenAssembly. If the result are
|
||||||
|
* different it fire an error.
|
||||||
|
*
|
||||||
|
* @param methodName
|
||||||
|
* the method name of the test.
|
||||||
|
* @param params
|
||||||
|
* the parameters for the method
|
||||||
|
*/
|
||||||
|
public void test( String methodName, Object... params ) {
|
||||||
|
try {
|
||||||
|
Class<?>[] types = new Class[params.length];
|
||||||
|
for( int i = 0; i < types.length; i++ ) {
|
||||||
|
Class<?> type = params[i].getClass();
|
||||||
|
switch( type.getName() ) {
|
||||||
|
case "java.lang.Integer":
|
||||||
|
type = int.class;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
types[i] = type;
|
||||||
|
}
|
||||||
|
Method method = null;
|
||||||
|
for( int i = 0; i < classes.length; i++ ) {
|
||||||
|
try {
|
||||||
|
Class<?> clazz = classes[i];
|
||||||
|
method = clazz.getDeclaredMethod( methodName, types );
|
||||||
|
} catch( NoSuchMethodException ex ) {
|
||||||
|
if( i == classes.length - 1 ) {
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
method.setAccessible( true );
|
||||||
|
Object expected = method.invoke( null, params );
|
||||||
|
|
||||||
|
String command = System.getProperty( "node.dir" );
|
||||||
|
command = command == null ? "node" : command + "/node";
|
||||||
|
ProcessBuilder processBuilder =
|
||||||
|
new ProcessBuilder( command, scriptFile.getAbsolutePath(), methodName );
|
||||||
|
for( int i = 0; i < params.length; i++ ) {
|
||||||
|
processBuilder.command().add( String.valueOf( params[i] ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
Process process = processBuilder.start();
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
String result = readStream( process.getInputStream() );
|
||||||
|
if( exitCode != 0 ) {
|
||||||
|
String errorMessage = readStream( process.getErrorStream() );
|
||||||
|
assertEquals( errorMessage, 0, exitCode );
|
||||||
|
}
|
||||||
|
assertEquals( String.valueOf( expected ), result );
|
||||||
|
} catch( Exception ex ) {
|
||||||
|
throwException( ex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a stream into a String.
|
||||||
|
*
|
||||||
|
* @param input
|
||||||
|
* the InputStream
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
|
public static String readStream( InputStream input ) {
|
||||||
|
try (Scanner scanner = new Scanner( input ).useDelimiter( "\\A" ) ) {
|
||||||
|
return scanner.hasNext() ? scanner.next() : "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throw any exception independent of signatures
|
||||||
|
*
|
||||||
|
* @param exception
|
||||||
|
* the exception
|
||||||
|
* @throws T
|
||||||
|
* a generic helper
|
||||||
|
*/
|
||||||
|
public static <T extends Throwable> void throwException( Throwable exception ) throws T {
|
||||||
|
throw (T)exception;
|
||||||
|
}
|
||||||
|
}
|
23
test/de/inetsoftware/jwebassembly/nodetest.js
Normal file
23
test/de/inetsoftware/jwebassembly/nodetest.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
var nodeFS = require('fs');
|
||||||
|
|
||||||
|
var filename = '{test.wasm}';
|
||||||
|
var ret = nodeFS['readFileSync'](filename);
|
||||||
|
|
||||||
|
function instantiate(bytes, imports) {
|
||||||
|
return WebAssembly.compile(bytes).then(
|
||||||
|
m => new WebAssembly.Instance(m, imports), reason => console.log(reason) );
|
||||||
|
}
|
||||||
|
|
||||||
|
var dependencies = {
|
||||||
|
"global": {},
|
||||||
|
"env": {}
|
||||||
|
};
|
||||||
|
dependencies["global.Math"] = Math;
|
||||||
|
|
||||||
|
|
||||||
|
instantiate( ret, dependencies ).then(
|
||||||
|
instance => console.log( instance.exports[process.argv[2]]( process.argv.slice(3) ) ),
|
||||||
|
reason => console.log(reason)
|
||||||
|
);
|
Loading…
x
Reference in New Issue
Block a user