mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-15 02:44:47 +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