169 lines
6.0 KiB
Haxe
169 lines
6.0 KiB
Haxe
package hank;
|
|
|
|
using StringTools;
|
|
import hank.Story.StoryFrame;
|
|
import hank.LogUtil;
|
|
import hank.HankBuffer;
|
|
|
|
import haxe.CallStack;
|
|
import utest.Assert;
|
|
|
|
class StoryTestCase extends utest.Test {
|
|
|
|
var testsDirectory: String;
|
|
var files: PreloadedFiles = new Map();
|
|
|
|
public function new(testsDirectory: String, ?preloadedFiles: PreloadedFiles) {
|
|
super();
|
|
this.testsDirectory = testsDirectory;
|
|
if (preloadedFiles != null)
|
|
this.files = preloadedFiles;
|
|
}
|
|
|
|
public function testAllExamples() {
|
|
var exampleTranscripts: Map<String, Array<String>> = new Map();
|
|
#if sys
|
|
var exampleFolders = sys.FileSystem.readDirectory(testsDirectory);
|
|
for (folder in exampleFolders) {
|
|
var files = sys.FileSystem.readDirectory('${testsDirectory}/${folder}');
|
|
exampleTranscripts.set(folder, [for(file in files) if (file.endsWith('.hlog')) file]);
|
|
}
|
|
#else
|
|
for (file in files.keys()) {
|
|
var parts = file.split('/');
|
|
|
|
if (parts[0] != testsDirectory) {
|
|
continue;
|
|
}
|
|
|
|
var folder = parts[1];
|
|
if (!exampleTranscripts.exists(folder)) {
|
|
exampleTranscripts.set(folder, new Array());
|
|
}
|
|
|
|
if (parts[2].endsWith('.hlog')) {
|
|
exampleTranscripts[folder].push(parts[2]);
|
|
}
|
|
}
|
|
#end
|
|
|
|
for (folder in exampleTranscripts.keys()) {
|
|
if (folder.startsWith('_')) {
|
|
trace('Skipping tests for example "${folder}"');
|
|
continue;
|
|
}
|
|
trace('Running tests for example "${folder}"');
|
|
|
|
for (file in exampleTranscripts[folder]) {
|
|
var disabled = file.indexOf("disabled") != -1;
|
|
var debug = file.indexOf("debug") != -1;
|
|
var partial = file.indexOf("partial") != -1;
|
|
if (!disabled) {
|
|
trace(' Running ${file}');
|
|
|
|
#if stop_on_error
|
|
validateAgainstTranscript('${testsDirectory}/${folder}/main.hank', '${testsDirectory}/${folder}/${file}', !partial, debug);
|
|
#else
|
|
try {
|
|
validateAgainstTranscript('${testsDirectory}/${folder}/main.hank', '${testsDirectory}/${folder}/${file}', !partial, debug);
|
|
} catch (e: Dynamic) {
|
|
var failMessage = 'Error testing $folder/$file at transcript line $lastTranscriptLine: $e, ${LogUtil.prettifyStack(CallStack.exceptionStack()) }';
|
|
trace(failMessage);
|
|
Assert.fail(failMessage);
|
|
}
|
|
#end
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var lastTranscriptLine = 0;
|
|
|
|
private function validateAgainstTranscript(storyFile: String, transcriptFile: String, fullTranscript: Bool = true, debug: Bool = false) {
|
|
var buffer = HankBuffer.FromFile(transcriptFile, files);
|
|
var transcriptLines = buffer.lines();
|
|
|
|
// If the transcript starts with a random seed, make sure the story uses that seed
|
|
var randomSeed = null;
|
|
if (transcriptLines[0].startsWith('@')) {
|
|
randomSeed = Std.parseInt(transcriptLines[0].substr(1));
|
|
transcriptLines.remove(transcriptLines[0]);
|
|
}
|
|
|
|
var story: Story = null;
|
|
|
|
// It's easier to debug exceptions on web if they travel up the stack
|
|
#if !sys
|
|
story = Story.FromFile(storyFile, files, randomSeed);
|
|
#else
|
|
try {
|
|
story = Story.FromFile(storyFile, files, randomSeed);
|
|
} catch (e: Dynamic) {
|
|
trace('Error parsing $storyFile: $e');
|
|
LogUtil.prettyPrintStack(CallStack.exceptionStack());
|
|
Assert.fail();
|
|
return;
|
|
}
|
|
#end
|
|
|
|
story.hInterface.addVariable("DEBUG", debug);
|
|
|
|
var i = 0;
|
|
while (i < transcriptLines.length) {
|
|
var line = transcriptLines[i];
|
|
lastTranscriptLine = i;
|
|
|
|
// Allow white-box story testing through expression value checks prefixed with #
|
|
if (line.startsWith("#")) {
|
|
var parts = line.substr(1).trim().split(':');
|
|
HankAssert.equals(parts[1].trim(), story.hInterface.evaluateExpr(parts[0], story.nodeScopes));
|
|
i +=1;
|
|
continue;
|
|
}
|
|
var frame = story.nextFrame();
|
|
if (line.startsWith("*")) {
|
|
// Collect the expected set of choices from the transcript.
|
|
var choices = new Array<String>();
|
|
do {
|
|
choices.push(line.substr(2));
|
|
|
|
line = transcriptLines[++i];
|
|
} while (line != null && line.startsWith("*"));
|
|
|
|
// Assert that the storyframe is a corresponding HasChoices enum
|
|
HankAssert.equals(HasChoices(choices), frame);
|
|
|
|
continue;
|
|
} else if (line.startsWith(">")) {
|
|
// Make the choice given, and check for expected output.
|
|
line = line.substr(1).ltrim();
|
|
var firstColonIdx = line.indexOf(':');
|
|
var index = Std.parseInt(line.substr(0, firstColonIdx))-1;
|
|
var expectedOutput = line.substr(firstColonIdx+1).trim();
|
|
// trace('expecting: ${expectedOutput}');
|
|
var output = story.choose(index);
|
|
// trace('got: ${output}');
|
|
HankAssert.equals(expectedOutput, output);
|
|
}
|
|
else if (line.length > 0) {
|
|
// Assert that the story's next frame is HasText(line)
|
|
// trace('${line} from ${frame}');
|
|
//trace('expecting: ${HasText(line)}');
|
|
//trace('got: $frame');
|
|
//trace('');
|
|
HankAssert.equals(HasText(line), frame);
|
|
}
|
|
|
|
if (frame == Finished) {
|
|
break;
|
|
}
|
|
|
|
i += 1;
|
|
}
|
|
|
|
if (fullTranscript) {
|
|
// After all transcript lines are validated, there should be nothing left in the story flow!
|
|
HankAssert.equals(StoryFrame.Finished, story.nextFrame());
|
|
}
|
|
}
|
|
} |