Concurrency
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
/// Unit tests for the dependency graph construction.
|
||||
///
|
||||
/// Tests DAG building from AST rules, cycle detection, and
|
||||
/// topological ordering.
|
||||
module antelope.tests.build.graph_test;
|
||||
|
||||
import antelope.build.graph;
|
||||
import antelope.build.target;
|
||||
|
||||
/// Test constructing a simple linear dependency graph.
|
||||
unittest
|
||||
{
|
||||
Target[] targets = [
|
||||
Target("all", TargetKind.phony, ["hello"], []),
|
||||
Target("hello", TargetKind.file, ["hello.o"], []),
|
||||
Target("hello.o", TargetKind.file, ["hello.c"], []),
|
||||
Target("hello.c", TargetKind.file, [], []),
|
||||
];
|
||||
|
||||
auto graph = DependencyGraph.fromTargets(targets);
|
||||
assert(graph.nodes.length == 4);
|
||||
}
|
||||
|
||||
/// Test cycle detection.
|
||||
unittest
|
||||
{
|
||||
Target[] targets = [
|
||||
Target("a", TargetKind.file, ["b"], []),
|
||||
Target("b", TargetKind.file, ["c"], []),
|
||||
Target("c", TargetKind.file, ["a"], []),
|
||||
];
|
||||
|
||||
auto graph = DependencyGraph.fromTargets(targets);
|
||||
assert(graph.hasCycle());
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/// GNU Make compatibility conformance tests.
|
||||
///
|
||||
/// These tests verify that Antelope in -gnu mode produces the same
|
||||
/// output as GNU Make for a set of canonical Makefiles. Each test
|
||||
/// runs both Antelope and GNU Make on the same input and compares
|
||||
/// stdout, exit code, and files produced.
|
||||
module antelope.tests.compatibility.gnu_make_test;
|
||||
|
||||
import antelope.compatibility.gnu_make;
|
||||
import antelope.compatibility.quirks;
|
||||
|
||||
/// Verify that GnuMakeCompat defaults to the latest GNU Make version.
|
||||
unittest
|
||||
{
|
||||
auto compat = GnuMakeCompat.init;
|
||||
assert(compat.targetVersion == GnuMakeVersion.v4_4);
|
||||
}
|
||||
|
||||
/// Verify key quirks are enabled by default.
|
||||
unittest
|
||||
{
|
||||
// Backslash-newline in comments is a known GNU Make quirk
|
||||
// that many real-world Makefiles depend on.
|
||||
assert(GnuQuirk.defaultQuirks.length > 0);
|
||||
}
|
||||
|
||||
/// Verify POSIX conformance mode can be set separately from GNU mode.
|
||||
unittest
|
||||
{
|
||||
auto compat = GnuMakeCompat.init;
|
||||
auto posix = PosixCompat.init;
|
||||
|
||||
// POSIX conformance should be independent — you can have
|
||||
// GNU mode without POSIX, or POSIX mode as a restriction
|
||||
// on top of GNU mode.
|
||||
posix.mode = PosixConformance.gnu_mode;
|
||||
assert(posix.mode == PosixConformance.gnu_mode);
|
||||
|
||||
posix.mode = PosixConformance.posix_target;
|
||||
assert(posix.mode == PosixConformance.posix_target);
|
||||
|
||||
posix.mode = PosixConformance.strict;
|
||||
assert(posix.mode == PosixConformance.strict);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/// Unit tests for variable expansion in the evaluator.
|
||||
///
|
||||
/// Tests recursive expansion, simple vs recursive assignment semantics,
|
||||
/// and circular reference detection.
|
||||
module antelope.tests.evaluator.expansion_test;
|
||||
|
||||
import antelope.evaluator.expansion;
|
||||
import antelope.shell.environment;
|
||||
|
||||
/// Test simple variable reference expansion.
|
||||
unittest
|
||||
{
|
||||
auto env = Environment.init;
|
||||
env.set("CC", "gcc");
|
||||
env.set("CFLAGS", "-Wall -O2");
|
||||
|
||||
auto result = expand(env, "$(CC) $(CFLAGS)");
|
||||
assert(result == "gcc -Wall -O2");
|
||||
}
|
||||
|
||||
/// Test brace-delimited variable expansion.
|
||||
unittest
|
||||
{
|
||||
auto env = Environment.init;
|
||||
env.set("VAR", "value");
|
||||
|
||||
auto result = expand(env, "${VAR}");
|
||||
assert(result == "value");
|
||||
}
|
||||
|
||||
/// Test that undefined variables produce a warning but expand to empty.
|
||||
unittest
|
||||
{
|
||||
auto env = Environment.init;
|
||||
auto result = expand(env, "$(UNDEFINED)");
|
||||
assert(result == "");
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/// Unit tests for the Antelope lexer.
|
||||
///
|
||||
/// Tests tokenization of Makefile syntax: identifiers, operators,
|
||||
/// variable references, comments, recipe lines, and line continuations.
|
||||
module antelope.tests.parser.lexer_test;
|
||||
|
||||
import antelope.parser.lexer;
|
||||
|
||||
/// Test basic identifier and operator tokenization.
|
||||
unittest
|
||||
{
|
||||
auto lexer = Lexer("target: prereq\n");
|
||||
auto tok = lexer.nextToken();
|
||||
assert(tok.type == TokenType.identifier);
|
||||
assert(tok.value == "target");
|
||||
|
||||
tok = lexer.nextToken();
|
||||
assert(tok.type == TokenType.colon);
|
||||
|
||||
tok = lexer.nextToken();
|
||||
assert(tok.type == TokenType.identifier);
|
||||
assert(tok.value == "prereq");
|
||||
}
|
||||
|
||||
/// Test comment stripping — everything after '#' is ignored.
|
||||
unittest
|
||||
{
|
||||
auto lexer = Lexer("VAR = value # this is a comment\n");
|
||||
auto tok = lexer.nextToken();
|
||||
assert(tok.type == TokenType.identifier);
|
||||
assert(tok.value == "VAR");
|
||||
|
||||
tok = lexer.nextToken();
|
||||
assert(tok.type == TokenType.equals);
|
||||
|
||||
tok = lexer.nextToken();
|
||||
assert(tok.type == TokenType.identifier);
|
||||
assert(tok.value == "value");
|
||||
}
|
||||
|
||||
/// Test line continuation (backslash-newline).
|
||||
unittest
|
||||
{
|
||||
auto lexer = Lexer("target: prereq1 \\\n prereq2\n");
|
||||
auto tok = lexer.nextToken();
|
||||
assert(tok.type == TokenType.identifier);
|
||||
assert(tok.value == "target");
|
||||
|
||||
tok = lexer.nextToken();
|
||||
assert(tok.type == TokenType.colon);
|
||||
}
|
||||
|
||||
/// Test variable reference prefix ($).
|
||||
unittest
|
||||
{
|
||||
auto lexer = Lexer("$(VAR)\n");
|
||||
auto tok = lexer.nextToken();
|
||||
assert(tok.type == TokenType.dollar);
|
||||
}
|
||||
|
||||
/// Test recipe line detection (tab-prefixed).
|
||||
unittest
|
||||
{
|
||||
auto lexer = Lexer("\tgcc -c hello.c\n");
|
||||
auto tok = lexer.nextToken();
|
||||
assert(tok.type == TokenType.recipeLine);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/// Unit tests for the Antelope parser.
|
||||
///
|
||||
/// Tests recursive-descent parsing of rules, variable assignments,
|
||||
/// and directive blocks into the AST.
|
||||
module antelope.tests.parser.parser_test;
|
||||
|
||||
import antelope.parser.parser;
|
||||
import antelope.parser.ast;
|
||||
|
||||
/// Test parsing a simple rule with prerequisites and no recipe.
|
||||
unittest
|
||||
{
|
||||
auto root = parseMakefile("target: prereq1 prereq2\n");
|
||||
assert(root.type == AstType.rule_list);
|
||||
assert(root.children.length == 1);
|
||||
|
||||
auto rule = root.children[0];
|
||||
assert(rule.type == AstType.rule);
|
||||
}
|
||||
|
||||
/// Test parsing a variable assignment.
|
||||
unittest
|
||||
{
|
||||
auto root = parseMakefile("CC = gcc\n");
|
||||
assert(root.type == AstType.rule_list);
|
||||
assert(root.children.length == 1);
|
||||
|
||||
auto var = root.children[0];
|
||||
assert(var.type == AstType.variable_assignment);
|
||||
}
|
||||
Reference in New Issue
Block a user