package org.luaj.vm2.libs.jse;

import junit.framework.TestCase;

import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;

public class LuaSchedulerTest extends TestCase {

	public void testWaitAndYieldRunCooperatively() {
		TestClock clock = new TestClock();
		Globals globals = JsePlatform.standardGlobals();
		LuaScheduler scheduler = new LuaScheduler(globals, clock);

		globals.load(
			"hits = {}\n" +
			"spawn(function()\n" +
			"  table.insert(hits, 'a')\n" +
			"  wait(10)\n" +
			"  table.insert(hits, 'b')\n" +
			"  yield('pause')\n" +
			"  table.insert(hits, 'c')\n" +
			"end)\n",
			"scheduler.lua"
		).call();

		assertEquals(1, scheduler.runReadyTasks());
		LuaTable hits = globals.get("hits").checktable();
		assertEquals("a", hits.get(1).tojstring());
		assertTrue(hits.get(2).isnil());

		clock.now = 9;
		assertEquals(0, scheduler.runReadyTasks());
		assertTrue(hits.get(2).isnil());

		clock.now = 10;
		assertEquals(1, scheduler.runReadyTasks());
		assertEquals("b", hits.get(2).tojstring());
		assertTrue(hits.get(3).isnil());

		assertEquals(1, scheduler.runReadyTasks());
		assertEquals("c", hits.get(3).tojstring());
		assertFalse(scheduler.hasPendingTasks());
	}

	public void testSpawnReturnsThreadHandle() {
		TestClock clock = new TestClock();
		Globals globals = JsePlatform.standardGlobals();
		LuaScheduler scheduler = new LuaScheduler(globals, clock);

		LuaValue thread = globals.load(
			"return spawn(function() wait(1) end)\n",
			"spawn.lua"
		).call();

		assertTrue(thread.isthread());
		assertEquals(1, scheduler.runReadyTasks());
		assertTrue(scheduler.hasPendingTasks());
	}

	static final class TestClock implements LuaScheduler.Clock {
		long now;

		public long nowMillis() {
			return now;
		}
	}
}
