Refactoring test suite
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
*.hanktest
|
||||
examples/shave/
|
||||
examples/shave/
|
||||
transcript.hlog
|
||||
validating.hlog
|
||||
@@ -3,5 +3,6 @@ IN DEBUG MODE!
|
||||
* Framing Hooper...
|
||||
* In with Hooper...
|
||||
>>> 2
|
||||
|
||||
Harris opens the door and pushes me inside. "Captain," he calls. "Could I have a moment?"
|
||||
The Captain, looking puzzled, steps out. The door is closed. Hooper stares at me, open—mouthed, about to say something. I probably have less than a minute before the Captain storms back in and declares this plan to be bunkum.
|
||||
@@ -10,6 +10,7 @@ I am not a machine, whatever they say about me.
|
||||
>>> 0
|
||||
|
||||
They suspect me to be a traitor. They think I stole the component from the calculating machine. They will be searching my bunk and cases.
|
||||
When they don't find it, they'll come back and demand I talk.
|
||||
I rattle my fingers on the field table.
|
||||
* Plan
|
||||
* Wait
|
||||
50
src/Story.hx
50
src/Story.hx
@@ -433,16 +433,16 @@ class Story {
|
||||
if (linesArray.length > 1) {
|
||||
// debugTrace('Parsing haxe block "${preprocessedLines}"');
|
||||
}
|
||||
var program = parser.parseString(preprocessedLines);
|
||||
interp.execute(program);
|
||||
|
||||
executeHaxeBlock(preprocessedLines);
|
||||
|
||||
var currentLineId = {
|
||||
sourceFile: scriptLines[currentLine].sourceFile,
|
||||
lineNumber: scriptLines[currentLine].lineNumber
|
||||
};
|
||||
|
||||
trace(startingId);
|
||||
trace(currentLineId);
|
||||
// trace(startingId);
|
||||
// trace(currentLineId);
|
||||
if (startingId.lineNumber == currentLineId.lineNumber && startingId.sourceFile == currentLineId.sourceFile) {stepLine();}
|
||||
}
|
||||
|
||||
@@ -465,13 +465,13 @@ class Story {
|
||||
var line = scriptLines[idx++];
|
||||
if (line.sourceFile == id.sourceFile && line.lineNumber == id.lineNumber) {
|
||||
gotoLine(idx);
|
||||
debugTrace('Found the right line');
|
||||
// debugTrace('Found the right line');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function stepLine() {
|
||||
debugTrace('stepLine called');
|
||||
// debugTrace('stepLine called');
|
||||
if (!finished) {
|
||||
// debugTrace('Stepping to line ${Std.string(scriptLines[currentLine+1])}');
|
||||
gotoLine(currentLine+1);
|
||||
@@ -541,7 +541,7 @@ class Story {
|
||||
|
||||
private function queueEmbeddedBlock(dummyFile: String) {
|
||||
if (embeddedBlocksQueued.length == 0) {
|
||||
trace('${dummyFile} got here first');
|
||||
// trace('${dummyFile} got here first');
|
||||
gotoFile(dummyFile);
|
||||
}
|
||||
embeddedBlocksQueued.push(dummyFile);
|
||||
@@ -551,14 +551,14 @@ class Story {
|
||||
private function processEmbeddedLines(parent: LineID, childNumber: Int, lines: String) {
|
||||
embeddedEntryPoint = parent;
|
||||
var dummyFile = 'EMBEDDED BLOCK ${childNumber}/${Std.string(parent)}';
|
||||
debugTrace('processing ${dummyFile}');
|
||||
// debugTrace('processing ${dummyFile}');
|
||||
queueEmbeddedBlock(dummyFile);
|
||||
}
|
||||
|
||||
/** Execute a parsed script statement **/
|
||||
private function processLine(line: HankLine): StoryFrame {
|
||||
if (line.type != NoOp) {
|
||||
debugTrace('Processing ${Std.string(line)}');
|
||||
// debugTrace('Processing ${Std.string(line)}');
|
||||
}
|
||||
|
||||
var file = line.sourceFile;
|
||||
@@ -604,7 +604,7 @@ class Story {
|
||||
stepLine();
|
||||
embeddedEntryPoint = null;
|
||||
} else {
|
||||
trace('another block was queued');
|
||||
// trace('another block was queued');
|
||||
var nextBlock = embeddedBlocksQueued[0];
|
||||
gotoFile(nextBlock);
|
||||
}
|
||||
@@ -641,7 +641,7 @@ class Story {
|
||||
return Error("Trust me, you'd rather not use a triple-nested Haxe block");
|
||||
}
|
||||
processHaxeBlock(code);
|
||||
trace('done that');
|
||||
// trace('done that');
|
||||
return Empty;
|
||||
|
||||
// Execute choice declarations by collecting the set of choices and presenting valid ones to the player
|
||||
@@ -846,12 +846,33 @@ class Story {
|
||||
private function checkChoiceCondition(choice: Choice): Bool {
|
||||
return if (Util.startsWithEnclosure(choice.text, "{", "}")) {
|
||||
var conditionExpression = Util.findEnclosure(choice.text, "{", "}");
|
||||
var parsed = parser.parseString(conditionExpression);
|
||||
var conditionValue = interp.expr(parsed);
|
||||
var conditionValue = evaluateHaxeExpression(conditionExpression);
|
||||
conditionValue;
|
||||
} else true;
|
||||
}
|
||||
|
||||
private function evaluateHaxeExpression(expression: String) {
|
||||
// It's common to want to && or || section/label names, but they're integers, not bools. Allow this.
|
||||
var expandedExpression = expression;
|
||||
|
||||
var parsed = parser.parseString(expandedExpression);
|
||||
try {
|
||||
var value = interp.expr(parsed);
|
||||
return value;
|
||||
} catch (e: Dynamic) {
|
||||
throw 'Error evaluating expression ${expression}: ${Std.string(e)}';
|
||||
}
|
||||
}
|
||||
|
||||
private function executeHaxeBlock(block: String) {
|
||||
try {
|
||||
var program = parser.parseString(block);
|
||||
interp.execute(program);
|
||||
} catch (e: Dynamic) {
|
||||
throw 'Error evaluating haxe block: ${Std.string(e)}\n${block}';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Process a choice into the desired form to show the player
|
||||
@param chosen Whether to show the choice's "before" or "after" text to the player
|
||||
@@ -901,9 +922,8 @@ class Story {
|
||||
Skip script execution to the desired target
|
||||
**/
|
||||
public function divert(target: String): StoryFrame {
|
||||
debugTrace('diverting to ${target}');
|
||||
// debugTrace('diverting to ${target}');
|
||||
// TODO check the current section for a subsection by the name of target, or else parse . notation for subsections
|
||||
// TODO if going to a labeled gather, set the choice depth to that gather's depth - 1
|
||||
// debugTrace('going to section ${section}');
|
||||
// Update this section's view count
|
||||
if (!interp.variables.exists(target)) {
|
||||
|
||||
@@ -14,22 +14,19 @@ class StoryTestCase extends utest.Test {
|
||||
|
||||
private function validateAgainstTranscript(storyFile: String, transcriptFile: String, fullTranscript: Bool = true, debug: Bool = false, debugPrints: Bool = false) {
|
||||
|
||||
trace('validating ${storyFile}');
|
||||
if (debugPrints) trace('validating ${storyFile}');
|
||||
|
||||
var story: Story = new Story(debug,'validating.hanktest', debugPrints);
|
||||
var story: Story = new Story(debug,'validating.hlog', debugPrints);
|
||||
story.loadScript(storyFile);
|
||||
var transcriptLines = sys.io.File.getContent(transcriptFile).split('\n');
|
||||
|
||||
var i = 0;
|
||||
while (i < transcriptLines.length) {
|
||||
var line = transcriptLines[i];
|
||||
trace(line);
|
||||
var frame = story.nextFrame();
|
||||
|
||||
if (debugPrints) {
|
||||
if (debugPrints) {
|
||||
trace('Frame ${i}: ${Std.string(frame)}');
|
||||
}
|
||||
trace('Frame ${i}: ${Std.string(frame)}');
|
||||
}
|
||||
|
||||
if (StringTools.startsWith(line, "*")) {
|
||||
@@ -76,6 +73,6 @@ class StoryTestCase extends utest.Test {
|
||||
// After all transcript lines are validated, there should be nothing left in the story flow!
|
||||
Assert.equals(StoryFrame.Finished, story.nextFrame());
|
||||
}
|
||||
trace('done with ${storyFile}');
|
||||
if (debugPrints) trace('done with ${storyFile}');
|
||||
}
|
||||
}
|
||||
@@ -13,23 +13,35 @@ class StoryTest extends src.StoryTestCase {
|
||||
|
||||
public function testParseHelloWorld() {
|
||||
var story: Story = new Story();
|
||||
story.loadScript("examples/hello.hank"); assertComplexEquals(OutputText('Hello, world!'), story.scriptLines[0].type);
|
||||
story.loadScript("examples/hello/main.hank"); assertComplexEquals(OutputText('Hello, world!'), story.scriptLines[0].type);
|
||||
}
|
||||
|
||||
public function testHelloWorld() {
|
||||
var story: Story = new Story();
|
||||
story.loadScript("examples/hello.hank");
|
||||
story.loadScript("examples/hello/main.hank");
|
||||
assertComplexEquals(HasText("Hello, world!"), story.nextFrame());
|
||||
Assert.equals(StoryFrame.Finished, story.nextFrame());
|
||||
Assert.equals(StoryFrame.Finished, story.nextFrame());
|
||||
}
|
||||
|
||||
public function testRunFullSpec2() {
|
||||
validateAgainstTranscript("examples/main.hank", "examples/tests/main1.hanktest");
|
||||
}
|
||||
public function testAllExamples() {
|
||||
var exampleFolders = sys.FileSystem.readDirectory('examples');
|
||||
|
||||
public function testRunFullSpec3() {
|
||||
validateAgainstTranscript("examples/main.hank", "examples/tests/main2.hanktest");
|
||||
// Iterate through every example in the examples folder
|
||||
for (folder in exampleFolders) {
|
||||
trace('Running tests for example "${folder}"');
|
||||
var files = sys.FileSystem.readDirectory('examples/${folder}');
|
||||
|
||||
for (file in files) {
|
||||
if (StringTools.endsWith(file, '.hlog')) {
|
||||
trace(' Running ${file}');
|
||||
|
||||
var debug = file.indexOf("debug") != -1;
|
||||
var partial = file.indexOf("partial") != -1;
|
||||
validateAgainstTranscript('examples/${folder}/main.hank', 'examples/${folder}/${file}', !partial, debug, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,8 +49,8 @@ class StoryTest extends src.StoryTestCase {
|
||||
**/
|
||||
public function testRunFullSpec1() {
|
||||
trace('testing the main hank example manually');
|
||||
var story: Story = new Story(true, "transcript.hanktest", true);
|
||||
story.loadScript("examples/main.hank");
|
||||
var story: Story = new Story(true, "transcript.hlog", true);
|
||||
story.loadScript("examples/main/main.hank");
|
||||
var frame1 = story.nextFrame();
|
||||
// This calls the INCLUDE statement. Ensure that all lines
|
||||
// were included
|
||||
@@ -82,12 +94,12 @@ class StoryTest extends src.StoryTestCase {
|
||||
Assert.equals(StoryFrame.Finished, story.nextFrame());
|
||||
|
||||
// Validate the transcript that was produced
|
||||
validateAgainstTranscript("examples/main.hank", "transcript.hanktest");
|
||||
validateAgainstTranscript("examples/main/main.hank", "transcript.hlog");
|
||||
}
|
||||
|
||||
public function testViewCounts() {
|
||||
var story = new Story(true);
|
||||
story.loadScript("examples/main.hank");
|
||||
story.loadScript("examples/main/main.hank");
|
||||
|
||||
Assert.equals(0, story.interp.variables['start']);
|
||||
Assert.equals(0, story.interp.variables['choice_example']);
|
||||
@@ -106,7 +118,7 @@ class StoryTest extends src.StoryTestCase {
|
||||
public function testParseFullSpec() {
|
||||
// Parse the main.hank script and test that all lines are correctly parsed
|
||||
var story = new Story(true);
|
||||
story.loadScript("examples/main.hank");
|
||||
story.loadScript("examples/main/main.hank");
|
||||
Assert.equals(40+22, story.lineCount);
|
||||
|
||||
// TODO test a few line numbers from the script to make sure the parsed versions match. Especially block line numbers
|
||||
@@ -116,7 +128,7 @@ class StoryTest extends src.StoryTestCase {
|
||||
|
||||
var lineTypes = [
|
||||
// TODO the 22 lines of the extra.hank file
|
||||
IncludeFile('examples/extra.hank'),
|
||||
IncludeFile('examples/main/extra.hank'),
|
||||
NoOp,
|
||||
Divert('start'),
|
||||
NoOp,
|
||||
@@ -156,7 +168,7 @@ class StoryTest extends src.StoryTestCase {
|
||||
OutputText("These should all say 'mouse':"),
|
||||
OutputText("{what_happened}"),
|
||||
OutputText("{variable_declared_in_block}"),
|
||||
EOF('examples/main.hank')
|
||||
EOF('examples/main/main.hank')
|
||||
];
|
||||
|
||||
var idx = 23;
|
||||
@@ -165,47 +177,4 @@ class StoryTest extends src.StoryTestCase {
|
||||
assertComplexEquals(lineTypes[i++], story.scriptLines[idx++].type);
|
||||
}
|
||||
}
|
||||
|
||||
@Ignored
|
||||
public function testRunIntercept1() {
|
||||
validateAgainstTranscript("examples/TheIntercept.hank", "examples/tests/intercept1.hanktest", false,
|
||||
false,
|
||||
true);
|
||||
}
|
||||
|
||||
@Ignored
|
||||
public function testRunInterceptDebug1() {
|
||||
validateAgainstTranscript(
|
||||
"examples/TheIntercept.hank",
|
||||
"examples/tests/interceptDebug1.hanktest",
|
||||
false, // Don't validate all of the Intercept until the port is done
|
||||
true, // Set DEBUG to true
|
||||
true); // Use debugTrace statements
|
||||
}
|
||||
|
||||
public function testEmbeddedHankMindfuck() {
|
||||
// Test the situation where embedded Hank lines are triggered, and later the story loops to the same Haxe block with different conditions
|
||||
validateAgainstTranscript("examples/mindfuck.hank", "examples/tests/mindfuck.hanktest", true, true, true);
|
||||
}
|
||||
|
||||
public function testConditionalBlocks() {
|
||||
trace('Testing conditional example in production mode');
|
||||
validateAgainstTranscript("examples/conditional.hank", "examples/tests/conditional1.hanktest", true, false, true);
|
||||
trace('testing conditional example in debug mode');
|
||||
validateAgainstTranscript("examples/conditional.hank", "examples/tests/conditionalDebug1.hanktest", true, true, true);
|
||||
}
|
||||
|
||||
public function testLabels() {
|
||||
validateAgainstTranscript("examples/labels.hank", "examples/tests/labels1.hanktest");
|
||||
validateAgainstTranscript("examples/labels.hank", "examples/tests/labels2.hanktest");
|
||||
}
|
||||
|
||||
/** Test one of Nat's private WIP Hank stories **/
|
||||
public function testPrivateStories() {
|
||||
if (sys.FileSystem.exists('examples/shave')) {
|
||||
validateAgainstTranscript('examples/shave/shave-draft2.hank', 'examples/shave/tests/1.hanktest');
|
||||
} else {
|
||||
Assert.isTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user