Browse Source

Update server tests for modern UTest + add test-adapter config

Jens Fischer 6 năm trước cách đây
mục cha
commit
6f9eb90299

+ 0 - 2
.gitignore

@@ -106,8 +106,6 @@ Makefile.modules
 
 /tests/unit/compiler_loops/log.txt
 tests/benchs/mandelbrot/bin/
-tests/server/test/cases/
-tests/server/test.js
 
 tests/unit/pypy3-*
 tmp.tmp

+ 4 - 0
tests/server/.gitignore

@@ -0,0 +1,4 @@
+.unittest
+test/cases
+test.js
+dump

+ 10 - 0
tests/server/.vscode/launch.json

@@ -0,0 +1,10 @@
+{
+	"version": "0.2.0",
+	"configurations": [
+		{
+			"name": "Macro",
+			"type": "haxe-eval",
+			"request": "launch"
+		}
+	]
+}

+ 12 - 0
tests/server/.vscode/settings.json

@@ -0,0 +1,12 @@
+{
+	"haxe.diagnosticsPathFilter": "${workspaceRoot}/src",
+	"editor.formatOnSave": true,
+	"haxeTestExplorer.testCommand": [
+		"${haxe}",
+		"build.hxml",
+		"-lib",
+		"test-adapter",
+		"-cmd",
+		"node test.js"
+	]
+}

+ 13 - 0
tests/server/.vscode/tasks.json

@@ -0,0 +1,13 @@
+{
+	"version": "2.0.0",
+	"tasks": [
+		{
+			"type": "hxml",
+			"file": "build.hxml",
+			"group": {
+				"kind": "build",
+				"isDefault": true
+			}
+		}
+	]
+}

+ 37 - 19
tests/server/src/AsyncMacro.hx

@@ -1,27 +1,45 @@
 import haxe.macro.Expr;
 import haxe.macro.Context;
 
+using StringTools;
+
 class AsyncMacro {
-	static public macro function async(e:Expr) {
-		var el = switch (e.expr) {
-			case EBlock(el): el;
-			case _: Context.error("Block expression expected", e.pos);
-		}
-		el.unshift(macro var _done = utest.Assert.createAsync(5000));
-		el.push(macro _done());
-		function loop(el:Array<Expr>) {
-			var e0 = el.shift();
-			return if (el.length == 0) {
-				e0;
-			} else switch (e0) {
-				case macro runHaxe($a{args}):
-					var e = loop(el);
-					args.push(macro () -> $e);
-					macro runHaxe($a{args});
+	static public macro function build():Array<Field> {
+		var fields = Context.getBuildFields();
+		for (field in fields) {
+			if (!field.name.startsWith("test")) {
+				continue;
+			}
+			switch (field.kind) {
+				case FFun(f):
+					f.args.push({
+						name: "async",
+						type: macro:utest.Async
+					});
+					switch (f.expr.expr) {
+						case EBlock(el):
+							el.push(macro async.done());
+							f.expr = transformHaxeCalls(el);
+						case _:
+							Context.error("Block expression expected", f.expr.pos);
+					}
 				case _:
-					macro { $e0; ${loop(el)}};
 			}
 		}
-		return loop(el);
+		return fields;
+	}
+
+	static function transformHaxeCalls(el:Array<Expr>) {
+		var e0 = el.shift();
+		return if (el.length == 0) {
+			e0;
+		} else switch (e0) {
+			case macro runHaxe($a{args}):
+				var e = transformHaxeCalls(el);
+				args.push(macro() -> $e);
+				macro runHaxe($a{args});
+			case _:
+				macro {$e0; ${transformHaxeCalls(el)}};
+		}
 	}
-}
+}

+ 241 - 242
tests/server/src/HaxeServer.hx

@@ -7,261 +7,260 @@ import js.node.stream.Readable;
 using StringTools;
 
 class ErrorUtils {
-    public static function errorToString(error:Dynamic, intro:String):String {
-        var result = intro + Std.string(error);
-        var stack = haxe.CallStack.exceptionStack();
-        if (stack != null && stack.length > 0)
-            result += "\n" + haxe.CallStack.toString(stack);
-        return result;
-    }
+	public static function errorToString(error:Dynamic, intro:String):String {
+		var result = intro + Std.string(error);
+		var stack = haxe.CallStack.exceptionStack();
+		if (stack != null && stack.length > 0)
+			result += "\n" + haxe.CallStack.toString(stack);
+		return result;
+	}
 }
 
 private class DisplayRequest {
-    // these are used for the queue
-    public var prev:DisplayRequest;
-    public var next:DisplayRequest;
-
-    var args:Array<String>;
-    var stdin:String;
-    var callback:String->Void;
-    var errback:String->Void;
-
-    static var stdinSepBuf = new Buffer([1]);
-
-    public function new(args:Array<String>, stdin:String, callback:String->Void, errback:String->Void) {
-        this.args = args;
-        this.stdin = stdin;
-        this.callback = callback;
-        this.errback = errback;
-    }
-
-    public function prepareBody():Buffer {
-        if (stdin != null) {
-            args.push("-D");
-            args.push("display-stdin");
-        }
-
-        var lenBuf = new Buffer(4);
-        var chunks = [lenBuf];
-        var length = 0;
-        for (arg in args) {
-            var buf = new Buffer(arg + "\n");
-            chunks.push(buf);
-            length += buf.length;
-        }
-
-        if (stdin != null) {
-            chunks.push(stdinSepBuf);
-            var buf = new Buffer(stdin);
-            chunks.push(buf);
-            length += buf.length + stdinSepBuf.length;
-        }
-
-        lenBuf.writeInt32LE(length, 0);
-
-        return Buffer.concat(chunks, length + 4);
-    }
-
-    public function processResult(context:Context, data:String) {
-        var buf = new StringBuf();
-        var hasError = false;
-        for (line in data.split("\n")) {
-            switch (line.fastCodeAt(0)) {
-                case 0x01: // print
-                    var line = line.substring(1).replace("\x01", "\n");
+	// these are used for the queue
+	public var prev:DisplayRequest;
+	public var next:DisplayRequest;
+
+	var args:Array<String>;
+	var stdin:String;
+	var callback:String->Void;
+	var errback:String->Void;
+
+	static var stdinSepBuf = new Buffer([1]);
+
+	public function new(args:Array<String>, stdin:String, callback:String->Void, errback:String->Void) {
+		this.args = args;
+		this.stdin = stdin;
+		this.callback = callback;
+		this.errback = errback;
+	}
+
+	public function prepareBody():Buffer {
+		if (stdin != null) {
+			args.push("-D");
+			args.push("display-stdin");
+		}
+
+		var lenBuf = new Buffer(4);
+		var chunks = [lenBuf];
+		var length = 0;
+		for (arg in args) {
+			var buf = new Buffer(arg + "\n");
+			chunks.push(buf);
+			length += buf.length;
+		}
+
+		if (stdin != null) {
+			chunks.push(stdinSepBuf);
+			var buf = new Buffer(stdin);
+			chunks.push(buf);
+			length += buf.length + stdinSepBuf.length;
+		}
+
+		lenBuf.writeInt32LE(length, 0);
+
+		return Buffer.concat(chunks, length + 4);
+	}
+
+	public function processResult(context:Context, data:String) {
+		var buf = new StringBuf();
+		var hasError = false;
+		for (line in data.split("\n")) {
+			switch (line.fastCodeAt(0)) {
+				case 0x01: // print
+					var line = line.substring(1).replace("\x01", "\n");
 					context.sendLogMessage("Haxe print: " + line + "\n");
-                case 0x02: // error
-                    hasError = true;
-                default:
-                    buf.add(line);
-                    buf.addChar("\n".code);
-            }
-        }
-
-        var data = buf.toString().trim();
-
-        if (hasError)
-            return errback(data);
-
-        try {
-            callback(data);
-        } catch (e:Any) {
-            errback(ErrorUtils.errorToString(e, "Exception while handling Haxe completion response: "));
-        }
-    }
+				case 0x02: // error
+					hasError = true;
+				default:
+					buf.add(line);
+					buf.addChar("\n".code);
+			}
+		}
+
+		var data = buf.toString().trim();
+
+		if (hasError)
+			return errback(data);
+
+		try {
+			callback(data);
+		} catch (e:Any) {
+			errback(ErrorUtils.errorToString(e, "Exception while handling Haxe completion response: "));
+		}
+	}
 }
 
 typedef DisplayServerConfigBase = {
-    var haxePath:String;
-    var arguments:Array<String>;
-    var env:haxe.DynamicAccess<String>;
+	var haxePath:String;
+	var arguments:Array<String>;
+	var env:haxe.DynamicAccess<String>;
 }
 
 typedef Context = {
-    function sendErrorMessage(msg:String):Void;
-    function sendLogMessage(msg:String):Void;
-    var displayServerConfig:DisplayServerConfigBase;
+	function sendErrorMessage(msg:String):Void;
+	function sendLogMessage(msg:String):Void;
+	var displayServerConfig:DisplayServerConfigBase;
 }
 
 private class MessageBuffer {
-    static inline var DEFAULT_SIZE = 8192;
-
-    var index:Int;
-    var buffer:Buffer;
-
-    public function new() {
-        index = 0;
-        buffer = new Buffer(DEFAULT_SIZE);
-    }
-
-    public function append(chunk:Buffer):Void {
-        if (buffer.length - index >= chunk.length) {
-            chunk.copy(buffer, index, 0, chunk.length);
-        } else {
-            var newSize = (Math.ceil((index + chunk.length) / DEFAULT_SIZE) + 1) * DEFAULT_SIZE;
-            if (index == 0) {
-                buffer = new Buffer(newSize);
-                chunk.copy(buffer, 0, 0, chunk.length);
-            } else {
-                buffer = Buffer.concat([buffer.slice(0, index), chunk], newSize);
-            }
-        }
-        index += chunk.length;
-    }
-
-    public function tryReadLength():Int {
-        if (index < 4)
-            return -1;
-        var length = buffer.readInt32LE(0);
-        buffer = buffer.slice(4);
-        index -= 4;
-        return length;
-    }
-
-    public function tryReadContent(length:Int):String {
-        if (index < length)
-            return null;
-        var result = buffer.toString("utf-8", 0, length);
-        var nextStart = length;
-        buffer.copy(buffer, 0, nextStart);
-        index -= nextStart;
-        return result;
-    }
-
-    public function getContent():String {
-        return buffer.toString("utf-8", 0, index);
-    }
+	static inline var DEFAULT_SIZE = 8192;
+
+	var index:Int;
+	var buffer:Buffer;
+
+	public function new() {
+		index = 0;
+		buffer = new Buffer(DEFAULT_SIZE);
+	}
+
+	public function append(chunk:Buffer):Void {
+		if (buffer.length - index >= chunk.length) {
+			chunk.copy(buffer, index, 0, chunk.length);
+		} else {
+			var newSize = (Math.ceil((index + chunk.length) / DEFAULT_SIZE) + 1) * DEFAULT_SIZE;
+			if (index == 0) {
+				buffer = new Buffer(newSize);
+				chunk.copy(buffer, 0, 0, chunk.length);
+			} else {
+				buffer = Buffer.concat([buffer.slice(0, index), chunk], newSize);
+			}
+		}
+		index += chunk.length;
+	}
+
+	public function tryReadLength():Int {
+		if (index < 4)
+			return -1;
+		var length = buffer.readInt32LE(0);
+		buffer = buffer.slice(4);
+		index -= 4;
+		return length;
+	}
+
+	public function tryReadContent(length:Int):String {
+		if (index < length)
+			return null;
+		var result = buffer.toString("utf-8", 0, length);
+		var nextStart = length;
+		buffer.copy(buffer, 0, nextStart);
+		index -= nextStart;
+		return result;
+	}
+
+	public function getContent():String {
+		return buffer.toString("utf-8", 0, index);
+	}
 }
 
 class HaxeServer {
-    var proc:ChildProcessObject;
-
-    var context:Context;
-    var buffer:MessageBuffer;
-    var nextMessageLength:Int;
-
-    var requestsHead:DisplayRequest;
-    var requestsTail:DisplayRequest;
-    var currentRequest:DisplayRequest;
-
-    public function new(context:Context) {
-        this.context = context;
-    }
-
-    static var reTrailingNewline = ~/\r?\n$/;
-
-    public function start() {
-        stop();
-
-        inline function error(s) context.sendErrorMessage(s);
-
-        var env = new haxe.DynamicAccess();
-        for (key in js.Node.process.env.keys())
-            env[key] = js.Node.process.env[key];
-
-        buffer = new MessageBuffer();
-        nextMessageLength = -1;
-
-        proc = ChildProcess.spawn(context.displayServerConfig.haxePath, context.displayServerConfig.arguments.concat(["--wait", "stdio"]), {env: env});
-
-        proc.stdout.on(ReadableEvent.Data, function(buf:Buffer) {
-            context.sendLogMessage(reTrailingNewline.replace(buf.toString(), ""));
-        });
-        proc.stderr.on(ReadableEvent.Data, onData);
-
-        proc.on(ChildProcessEvent.Exit, onExit);
-    }
-
-    public function stop() {
-        if (proc != null) {
-            proc.removeAllListeners();
-            proc.kill();
-            proc = null;
-        }
-
-        requestsHead = requestsTail = currentRequest = null;
-    }
-
-    public function restart(reason:String) {
-        context.sendLogMessage('Restarting Haxe completion server: $reason');
-        start();
-    }
-
-    function onExit(_, _) {
-        var haxeResponse = buffer.getContent();
-        trace("\nError message from the compiler:\n");
-        trace(haxeResponse);
-    }
-
-    function onData(data:Buffer) {
-        buffer.append(data);
-        while (true) {
-            if (nextMessageLength == -1) {
-                var length = buffer.tryReadLength();
-                if (length == -1)
-                    return;
-                nextMessageLength = length;
-            }
-            var msg = buffer.tryReadContent(nextMessageLength);
-            if (msg == null)
-                return;
-            nextMessageLength = -1;
-            if (currentRequest != null) {
-                var request = currentRequest;
-                currentRequest = null;
-                request.processResult(context, msg);
-                checkQueue();
-            }
-        }
-    }
-
-    public function process(args:Array<String>, stdin:String, callback:String->Void, errback:String->Void) {
-        // create a request object
-        var request = new DisplayRequest(args, stdin, callback, errback);
-
-        // add to the queue
-        if (requestsHead == null) {
-            requestsHead = requestsTail = request;
-        } else {
-            requestsTail.next = request;
-            request.prev = requestsTail;
-            requestsTail = request;
-        }
-
-        // process the queue
-        checkQueue();
-    }
-
-    function checkQueue() {
-        // there's a currently processing request, wait and don't send another one to Haxe
-        if (currentRequest != null)
-            return;
-
-        // pop the first request still in queue, set it as current and send to Haxe
-        if (requestsHead != null) {
-            currentRequest = requestsHead;
-            requestsHead = currentRequest.next;
-            proc.stdin.write(currentRequest.prepareBody());
-        }
-    }
-}
+	var proc:ChildProcessObject;
+	var context:Context;
+	var buffer:MessageBuffer;
+	var nextMessageLength:Int;
+	var requestsHead:DisplayRequest;
+	var requestsTail:DisplayRequest;
+	var currentRequest:DisplayRequest;
+
+	public function new(context:Context) {
+		this.context = context;
+	}
+
+	static var reTrailingNewline = ~/\r?\n$/;
+
+	public function start() {
+		stop();
+
+		inline function error(s)
+			context.sendErrorMessage(s);
+
+		var env = new haxe.DynamicAccess();
+		for (key in js.Node.process.env.keys())
+			env[key] = js.Node.process.env[key];
+
+		buffer = new MessageBuffer();
+		nextMessageLength = -1;
+
+		proc = ChildProcess.spawn(context.displayServerConfig.haxePath, context.displayServerConfig.arguments.concat(["--wait", "stdio"]), {env: env});
+
+		proc.stdout.on(ReadableEvent.Data, function(buf:Buffer) {
+			context.sendLogMessage(reTrailingNewline.replace(buf.toString(), ""));
+		});
+		proc.stderr.on(ReadableEvent.Data, onData);
+
+		proc.on(ChildProcessEvent.Exit, onExit);
+	}
+
+	public function stop() {
+		if (proc != null) {
+			proc.removeAllListeners();
+			proc.kill();
+			proc = null;
+		}
+
+		requestsHead = requestsTail = currentRequest = null;
+	}
+
+	public function restart(reason:String) {
+		context.sendLogMessage('Restarting Haxe completion server: $reason');
+		start();
+	}
+
+	function onExit(_, _) {
+		var haxeResponse = buffer.getContent();
+		trace("\nError message from the compiler:\n");
+		trace(haxeResponse);
+	}
+
+	function onData(data:Buffer) {
+		buffer.append(data);
+		while (true) {
+			if (nextMessageLength == -1) {
+				var length = buffer.tryReadLength();
+				if (length == -1)
+					return;
+				nextMessageLength = length;
+			}
+			var msg = buffer.tryReadContent(nextMessageLength);
+			if (msg == null)
+				return;
+			nextMessageLength = -1;
+			if (currentRequest != null) {
+				var request = currentRequest;
+				currentRequest = null;
+				request.processResult(context, msg);
+				checkQueue();
+			}
+		}
+	}
+
+	public function process(args:Array<String>, stdin:String, callback:String->Void, errback:String->Void) {
+		// create a request object
+		var request = new DisplayRequest(args, stdin, callback, errback);
+
+		// add to the queue
+		if (requestsHead == null) {
+			requestsHead = requestsTail = request;
+		} else {
+			requestsTail.next = request;
+			request.prev = requestsTail;
+			requestsTail = request;
+		}
+
+		// process the queue
+		checkQueue();
+	}
+
+	function checkQueue() {
+		// there's a currently processing request, wait and don't send another one to Haxe
+		if (currentRequest != null)
+			return;
+
+		// pop the first request still in queue, set it as current and send to Haxe
+		if (requestsHead != null) {
+			currentRequest = requestsHead;
+			requestsHead = currentRequest.next;
+			proc.stdin.write(currentRequest.prepareBody());
+		}
+	}
+}

+ 11 - 9
tests/server/src/HaxeServerTestCase.hx

@@ -2,19 +2,20 @@ import haxe.display.JsonModuleTypes.JsonModuleType;
 import haxe.Json;
 import HaxeServer;
 import utest.Assert;
+import utest.ITest;
+
 using StringTools;
 using Lambda;
 
 class TestContext {
 	public var messages:Array<String> = []; // encapsulation is overrated
-
 	public var displayServerConfig:DisplayServerConfigBase;
 
 	public function new(config:DisplayServerConfigBase) {
 		this.displayServerConfig = config;
 	}
 
-	public function sendErrorMessage(msg:String) { }
+	public function sendErrorMessage(msg:String) {}
 
 	public function sendLogMessage(msg:String) {
 		var split = msg.split("\n");
@@ -24,22 +25,23 @@ class TestContext {
 	}
 }
 
-class HaxeServerTestCase {
+@:autoBuild(AsyncMacro.build())
+class HaxeServerTestCase implements ITest {
 	var context:TestContext;
 	var server:HaxeServer;
 	var vfs:Vfs;
 	var testDir:String;
 	var storedTypes:Array<JsonModuleType<Any>>;
+	var i:Int = 0;
 
-	public function new() {
-		testDir = "test/cases/" + Type.getClassName(Type.getClass(this));
-	}
+	public function new() {}
 
 	public function setup() {
+		testDir = "test/cases/" + i++;
 		context = new TestContext({
 			haxePath: "haxe",
 			arguments: ["-v", "--cwd", testDir],
-			env: { }
+			env: {}
 		});
 		vfs = new Vfs(testDir);
 		server = new HaxeServer(context);
@@ -50,7 +52,7 @@ class HaxeServerTestCase {
 		server.stop();
 	}
 
-	function runHaxe(args:Array<String>, storeTypes = false, done:Void -> Void) {
+	function runHaxe(args:Array<String>, storeTypes = false, done:Void->Void) {
 		context.messages = [];
 		storedTypes = [];
 		if (storeTypes) {
@@ -127,4 +129,4 @@ class HaxeServerTestCase {
 			Assert.isTrue(check(type), null, p);
 		}
 	}
-}
+}

+ 60 - 81
tests/server/src/Main.hx

@@ -1,98 +1,77 @@
-import AsyncMacro.async;
 using StringTools;
 
-class NoModification extends HaxeServerTestCase {
-	public function test() {
-		async({
-			vfs.putContent("HelloWorld.hx", getTemplate("HelloWorld.hx"));
-			var args = ["-main", "HelloWorld.hx", "--no-output", "-js", "no.js"];
-			runHaxe(args);
-			runHaxe(args);
-			assertReuse("HelloWorld");
-			runHaxe(args);
-			assertReuse("HelloWorld");
-		});
+class ServerTests extends HaxeServerTestCase {
+	@:timeout(5000)
+	function testNoModification() {
+		vfs.putContent("HelloWorld.hx", getTemplate("HelloWorld.hx"));
+		var args = ["-main", "HelloWorld.hx", "--no-output", "-js", "no.js"];
+		runHaxe(args);
+		runHaxe(args);
+		assertReuse("HelloWorld");
+		runHaxe(args);
+		assertReuse("HelloWorld");
 	}
-}
 
-class Modification extends HaxeServerTestCase {
-	public function test() {
-		async({
-			vfs.putContent("HelloWorld.hx", getTemplate("HelloWorld.hx"));
-			var args = ["-main", "HelloWorld.hx", "--no-output", "-js", "no.js"];
-			runHaxe(args);
-			vfs.touchFile("HelloWorld.hx");
-			runHaxe(args);
-			assertSkipping("HelloWorld");
-			assertNotCacheModified("HelloWorld");
-		});
+	@:timeout(5000)
+	function testModification() {
+		vfs.putContent("HelloWorld.hx", getTemplate("HelloWorld.hx"));
+		var args = ["-main", "HelloWorld.hx", "--no-output", "-js", "no.js"];
+		runHaxe(args);
+		vfs.touchFile("HelloWorld.hx");
+		runHaxe(args);
+		assertSkipping("HelloWorld");
+		assertNotCacheModified("HelloWorld");
 	}
-}
 
-class Dependency extends HaxeServerTestCase {
-	public function test() {
-		async({
-			vfs.putContent("WithDependency.hx", getTemplate("WithDependency.hx"));
-			vfs.putContent("Dependency.hx", getTemplate("Dependency.hx"));
-			var args = ["-main", "WithDependency.hx", "--no-output", "-js", "no.js"];
-			runHaxe(args);
-			vfs.touchFile("Dependency.hx");
-			runHaxe(args);
-			assertSkipping("WithDependency", "Dependency");
-			assertNotCacheModified("Dependency");
-			runHaxe(args);
-			assertReuse("Dependency");
-			assertReuse("WithDependency");
-		});
+	@:timeout(5000)
+	function testDependency() {
+		vfs.putContent("WithDependency.hx", getTemplate("WithDependency.hx"));
+		vfs.putContent("Dependency.hx", getTemplate("Dependency.hx"));
+		var args = ["-main", "WithDependency.hx", "--no-output", "-js", "no.js"];
+		runHaxe(args);
+		vfs.touchFile("Dependency.hx");
+		runHaxe(args);
+		assertSkipping("WithDependency", "Dependency");
+		assertNotCacheModified("Dependency");
+		runHaxe(args);
+		assertReuse("Dependency");
+		assertReuse("WithDependency");
 	}
-}
 
-class Macro extends HaxeServerTestCase {
-	public function test() {
-		async({
-			vfs.putContent("MacroMain.hx", getTemplate("MacroMain.hx"));
-			vfs.putContent("Macro.hx", getTemplate("Macro.hx"));
-			var args = ["-main", "MacroMain.hx", "--no-output", "-js", "no.js"];
-			runHaxe(args);
-			assertHasPrint("1");
-			vfs.touchFile("MacroMain.hx");
-			runHaxe(args);
-			assertHasPrint("1");
-			vfs.touchFile("Macro.hx");
-			runHaxe(args);
-			assertHasPrint("1");
-			vfs.putContent("Macro.hx", getTemplate("Macro.hx").replace("1", "2"));
-			runHaxe(args);
-			assertHasPrint("2");
-			vfs.touchFile("MacroMain.hx");
-			runHaxe(args);
-			assertHasPrint("2");
-		});
+	@:timeout(5000)
+	function testMacro() {
+		vfs.putContent("MacroMain.hx", getTemplate("MacroMain.hx"));
+		vfs.putContent("Macro.hx", getTemplate("Macro.hx"));
+		var args = ["-main", "MacroMain.hx", "--no-output", "-js", "no.js"];
+		runHaxe(args);
+		assertHasPrint("1");
+		vfs.touchFile("MacroMain.hx");
+		runHaxe(args);
+		assertHasPrint("1");
+		vfs.touchFile("Macro.hx");
+		runHaxe(args);
+		assertHasPrint("1");
+		vfs.putContent("Macro.hx", getTemplate("Macro.hx").replace("1", "2"));
+		runHaxe(args);
+		assertHasPrint("2");
+		vfs.touchFile("MacroMain.hx");
+		runHaxe(args);
+		assertHasPrint("2");
 	}
-}
 
-class DceEmpty extends HaxeServerTestCase {
-	public function test() {
-		async({
-			vfs.putContent("Empty.hx", getTemplate("Empty.hx"));
-			var args = ["-main", "Empty", "--no-output", "-java", "java"];
-			runHaxe(args);
-			runHaxe(args, true);
-			assertHasField("", "Type", "enumIndex", true);
-		});
+	@:timeout(5000)
+	function testDceEmpty() {
+		vfs.putContent("Empty.hx", getTemplate("Empty.hx"));
+		var args = ["-main", "Empty", "--no-output", "-java", "java"];
+		runHaxe(args);
+		runHaxe(args, true);
+		assertHasField("", "Type", "enumIndex", true);
 	}
 }
 
 class Main {
 	static public function main() {
 		Vfs.removeDir("test/cases");
-		var runner = new utest.Runner();
-		runner.addCase(new NoModification());
-		runner.addCase(new Modification());
-		runner.addCase(new Dependency());
-		runner.addCase(new Macro());
-		runner.addCase(new DceEmpty());
-		utest.ui.Report.create(runner);
-		runner.run();
+		utest.UTest.run([new ServerTests()]);
 	}
-}
+}

+ 3 - 3
tests/server/src/Vfs.hx

@@ -17,8 +17,8 @@ class Vfs {
 		var path = getPhysicalPath(path);
 		FileSystem.createDirectory(path.dir);
 		var file = Fs.openSync(path.dir + "/" + path.file + "." + path.ext, 'a');
-        var last = Date.fromString(Fs.fstatSync(file).mtime.toTimeString().substr(0, 8));
-        var notNow = js.Date.fromHaxeDate(DateTools.delta(last, 1000));
+		var last = Date.fromString(Fs.fstatSync(file).mtime.toTimeString().substr(0, 8));
+		var notNow = js.Date.fromHaxeDate(DateTools.delta(last, 1000));
 		Fs.futimesSync(file, notNow, notNow);
 		Fs.closeSync(file);
 	}
@@ -58,4 +58,4 @@ class Vfs {
 			FileSystem.deleteDirectory(dir);
 		}
 	}
-}
+}

+ 1 - 1
tests/server/test/templates/Dependency.hx

@@ -2,4 +2,4 @@ class Dependency {
 	static public function get() {
 		return "Hello World";
 	}
-}
+}

+ 2 - 4
tests/server/test/templates/Empty.hx

@@ -1,5 +1,3 @@
 class Empty {
-	public static function main() {
-
-	}
-}
+	public static function main() {}
+}

+ 1 - 1
tests/server/test/templates/HelloWorld.hx

@@ -2,4 +2,4 @@ class HelloWorld {
 	public static function main() {
 		trace("Hello World");
 	}
-}
+}

+ 1 - 1
tests/server/test/templates/Macro.hx

@@ -5,4 +5,4 @@ class Macro {
 		Sys.println(x++);
 		return macro null;
 	}
-}
+}

+ 1 - 1
tests/server/test/templates/MacroMain.hx

@@ -2,4 +2,4 @@ class MacroMain {
 	static public function main() {
 		Macro.test();
 	}
-}
+}

+ 1 - 1
tests/server/test/templates/WithDependency.hx

@@ -2,4 +2,4 @@ class WithDependency {
 	public static function main() {
 		trace(Dependency.get());
 	}
-}
+}