Skip to content

Commit 3194547

Browse files
committed
Refactor ounit functions
1 parent 03d890d commit 3194547

File tree

3 files changed

+121
-130
lines changed

3 files changed

+121
-130
lines changed

modules/main/src/main/java/com/annimon/ownlang/modules/ounit/ounit.java

Lines changed: 67 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import com.annimon.ownlang.modules.Module;
66
import java.text.DecimalFormat;
77
import java.util.Collections;
8-
import java.util.LinkedHashMap;
98
import java.util.List;
109
import java.util.Map;
1110

@@ -22,110 +21,91 @@ public Map<String, Value> constants() {
2221

2322
@Override
2423
public Map<String, Function> functions() {
25-
final var result = new LinkedHashMap<String, Function>(16);
26-
result.put("assertEquals", new assertEquals());
27-
result.put("assertNotEquals", new assertNotEquals());
28-
result.put("assertSameType", new assertSameType());
29-
result.put("assertTrue", new assertTrue());
30-
result.put("assertFalse", new assertFalse());
31-
result.put("runTests", new runTests());
32-
return result;
24+
return Map.of(
25+
"assertEquals", this::assertEquals,
26+
"assertNotEquals", this::assertNotEquals,
27+
"assertSameType", this::assertSameType,
28+
"assertTrue", this::assertTrue,
29+
"assertFalse", this::assertFalse,
30+
"runTests", this::runTests
31+
);
3332
}
3433

3534
private static String microsToSeconds(long micros) {
3635
return new DecimalFormat("#0.0000").format(micros / 1000d / 1000d) + " sec";
3736
}
38-
39-
private static class assertEquals implements Function {
40-
@Override
41-
public Value execute(Value[] args) {
42-
Arguments.check(2, args.length);
43-
if (args[0].equals(args[1])) return NumberValue.ONE;
44-
throw new OUnitAssertionException("Values are not equal: "
45-
+ "1: " + args[0] + ", 2: " + args[1]);
46-
}
37+
38+
private Value assertEquals(Value[] args) {
39+
Arguments.check(2, args.length);
40+
if (args[0].equals(args[1])) return NumberValue.ONE;
41+
throw new OUnitAssertionException("Values are not equal: "
42+
+ "1: " + args[0] + ", 2: " + args[1]);
4743
}
4844

49-
private static class assertNotEquals implements Function {
50-
@Override
51-
public Value execute(Value[] args) {
52-
Arguments.check(2, args.length);
53-
if (!args[0].equals(args[1])) return NumberValue.ONE;
54-
throw new OUnitAssertionException("Values are equal: " + args[0]);
55-
}
45+
private Value assertNotEquals(Value[] args) {
46+
Arguments.check(2, args.length);
47+
if (!args[0].equals(args[1])) return NumberValue.ONE;
48+
throw new OUnitAssertionException("Values are equal: " + args[0]);
5649
}
5750

58-
private static class assertSameType implements Function {
59-
@Override
60-
public Value execute(Value[] args) {
61-
Arguments.check(2, args.length);
62-
if (args[0].type() == args[1].type()) return NumberValue.ONE;
63-
throw new OUnitAssertionException("Types mismatch. "
64-
+ "1: " + Types.typeToString(args[0].type())
65-
+ ", 2: " + Types.typeToString(args[1].type()));
66-
}
51+
private Value assertSameType(Value[] args) {
52+
Arguments.check(2, args.length);
53+
if (args[0].type() == args[1].type()) return NumberValue.ONE;
54+
throw new OUnitAssertionException("Types mismatch. "
55+
+ "1: " + Types.typeToString(args[0].type())
56+
+ ", 2: " + Types.typeToString(args[1].type()));
6757
}
6858

69-
private static class assertTrue implements Function {
70-
@Override
71-
public Value execute(Value[] args) {
72-
Arguments.check(1, args.length);
73-
if (args[0].asInt() != 0) return NumberValue.ONE;
74-
throw new OUnitAssertionException("Expected true, but found false.");
75-
}
59+
private Value assertTrue(Value[] args) {
60+
Arguments.check(1, args.length);
61+
if (args[0].asInt() != 0) return NumberValue.ONE;
62+
throw new OUnitAssertionException("Expected true, but found false.");
7663
}
7764

78-
private static class assertFalse implements Function {
79-
@Override
80-
public Value execute(Value[] args) {
81-
Arguments.check(1, args.length);
82-
if (args[0].asInt() == 0) return NumberValue.ONE;
83-
throw new OUnitAssertionException("Expected false, but found true.");
84-
}
65+
private Value assertFalse(Value[] args) {
66+
Arguments.check(1, args.length);
67+
if (args[0].asInt() == 0) return NumberValue.ONE;
68+
throw new OUnitAssertionException("Expected false, but found true.");
8569
}
86-
87-
private static class runTests implements Function {
88-
89-
@Override
90-
public Value execute(Value[] args) {
91-
final var testFunctions = ScopeHandler.functions().entrySet().stream()
92-
.filter(e -> e.getKey().toLowerCase().startsWith("test"))
93-
.toList();
94-
List<TestInfo> tests = testFunctions.stream()
95-
.map(e -> runTest(e.getKey(), e.getValue()))
96-
.toList();
9770

98-
int failures = 0;
99-
long summaryTime = 0;
100-
final StringBuilder result = new StringBuilder();
101-
for (TestInfo test : tests) {
102-
if (!test.isPassed) failures++;
103-
summaryTime += test.elapsedTimeInMicros;
104-
result.append(Console.newline());
105-
result.append(test.info());
106-
}
71+
private Value runTests(Value[] args) {
72+
final var testFunctions = ScopeHandler.functions().entrySet().stream()
73+
.filter(e -> e.getKey().toLowerCase().startsWith("test"))
74+
.toList();
75+
List<TestInfo> tests = testFunctions.stream()
76+
.map(e -> runTest(e.getKey(), e.getValue()))
77+
.toList();
78+
79+
int failures = 0;
80+
long summaryTime = 0;
81+
final StringBuilder result = new StringBuilder();
82+
for (TestInfo test : tests) {
83+
if (!test.isPassed) failures++;
84+
summaryTime += test.elapsedTimeInMicros;
10785
result.append(Console.newline());
108-
result.append(String.format("Tests run: %d, Failures: %d, Time elapsed: %s",
109-
tests.size(), failures,
110-
microsToSeconds(summaryTime)));
111-
return new StringValue(result.toString());
86+
result.append(test.info());
11287
}
88+
result.append(Console.newline());
89+
result.append(String.format("Tests run: %d, Failures: %d, Time elapsed: %s",
90+
tests.size(), failures,
91+
microsToSeconds(summaryTime)));
92+
return new StringValue(result.toString());
93+
}
11394

114-
private TestInfo runTest(String name, Function f) {
115-
final long startTime = System.nanoTime();
116-
boolean isSuccessfull;
117-
String failureDescription;
118-
try {
119-
f.execute();
120-
isSuccessfull = true;
121-
failureDescription = "";
122-
} catch (OUnitAssertionException oae) {
123-
isSuccessfull = false;
124-
failureDescription = oae.getMessage();
125-
}
126-
final long elapsedTime = System.nanoTime() - startTime;
127-
return new TestInfo(name, isSuccessfull, failureDescription, elapsedTime / 1000);
95+
private TestInfo runTest(String name, Function f) {
96+
final long startTime = System.nanoTime();
97+
boolean isSuccessfull;
98+
String failureDescription;
99+
try {
100+
f.execute();
101+
isSuccessfull = true;
102+
failureDescription = "";
103+
} catch (OUnitAssertionException oae) {
104+
isSuccessfull = false;
105+
failureDescription = oae.getMessage();
128106
}
107+
final long elapsedTime = System.nanoTime() - startTime;
108+
return new TestInfo(name, isSuccessfull, failureDescription, elapsedTime / 1000);
129109
}
130110

131111
private static class OUnitAssertionException extends RuntimeException {
@@ -142,7 +122,7 @@ private record TestInfo(
142122
long elapsedTimeInMicros
143123
) {
144124
public String info() {
145-
return String.format("%s [%s]\n%sElapsed: %s\n",
125+
return "%s [%s]\n%sElapsed: %s\n".formatted(
146126
name,
147127
isPassed ? "passed" : "FAILED",
148128
isPassed ? "" : (failureDescription + "\n"),
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.annimon.ownlang.parser;
2+
3+
import com.annimon.ownlang.lib.FunctionValue;
4+
import com.annimon.ownlang.lib.NumberValue;
5+
import com.annimon.ownlang.lib.ScopeHandler;
6+
import com.annimon.ownlang.parser.ast.Node;
7+
import com.annimon.ownlang.stages.Stage;
8+
import com.annimon.ownlang.stages.StagesData;
9+
import static org.junit.jupiter.api.Assertions.*;
10+
import static org.junit.jupiter.api.Assertions.fail;
11+
12+
public class MockOUnitStage implements Stage<Node, Node> {
13+
14+
@Override
15+
public Node perform(StagesData stagesData, Node input) {
16+
ScopeHandler.resetScope();
17+
ScopeHandler.setFunction("assertEquals", (args) -> {
18+
assertEquals(args[0], args[1]);
19+
return NumberValue.ONE;
20+
});
21+
ScopeHandler.setFunction("assertNotEquals", (args) -> {
22+
assertNotEquals(args[0], args[1]);
23+
return NumberValue.ONE;
24+
});
25+
ScopeHandler.setFunction("assertSameType", (args) -> {
26+
assertEquals(args[0].type(), args[1].type());
27+
return NumberValue.ONE;
28+
});
29+
ScopeHandler.setFunction("assertTrue", (args) -> {
30+
assertTrue(args[0].asInt() != 0);
31+
return NumberValue.ONE;
32+
});
33+
ScopeHandler.setFunction("assertFalse", (args) -> {
34+
assertFalse(args[0].asInt() != 0);
35+
return NumberValue.ONE;
36+
});
37+
ScopeHandler.setFunction("assertFail", (args) -> {
38+
assertThrows(Throwable.class,
39+
() -> ((FunctionValue) args[0]).getValue().execute());
40+
return NumberValue.ONE;
41+
});
42+
ScopeHandler.setFunction("fail", (args) -> {
43+
if (args.length > 0) {
44+
fail(args[0].asString());
45+
} else {
46+
fail();
47+
}
48+
return NumberValue.ONE;
49+
});
50+
return input;
51+
}
52+
}

ownlang-parser/src/test/java/com/annimon/ownlang/parser/ProgramsTest.java

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
import com.annimon.ownlang.Console;
44
import com.annimon.ownlang.exceptions.OwnLangParserException;
5-
import com.annimon.ownlang.lib.FunctionValue;
6-
import com.annimon.ownlang.lib.NumberValue;
75
import com.annimon.ownlang.lib.ScopeHandler;
86
import com.annimon.ownlang.parser.ast.ClassDeclarationStatement;
97
import com.annimon.ownlang.parser.ast.FunctionDefineStatement;
@@ -42,53 +40,14 @@ public static void createStage() {
4240
.then(new ParserStage())
4341
.then(new LinterStage(LinterStage.Mode.SEMANTIC))
4442
.thenConditional(true, new OptimizationStage(9))
45-
.then(ProgramsTest::mockOUnit)
43+
.then(new MockOUnitStage())
4644
.then(new ExecutionStage())
4745
.then((stagesData, input) -> {
4846
input.accept(testFunctionsExecutor);
4947
return input;
5048
});
5149
}
5250

53-
private static Node mockOUnit(StagesData stagesData, Node input) {
54-
ScopeHandler.resetScope();
55-
// Let's mock junit methods as ounit functions
56-
ScopeHandler.setFunction("assertEquals", (args) -> {
57-
assertEquals(args[0], args[1]);
58-
return NumberValue.ONE;
59-
});
60-
ScopeHandler.setFunction("assertNotEquals", (args) -> {
61-
assertNotEquals(args[0], args[1]);
62-
return NumberValue.ONE;
63-
});
64-
ScopeHandler.setFunction("assertSameType", (args) -> {
65-
assertEquals(args[0].type(), args[1].type());
66-
return NumberValue.ONE;
67-
});
68-
ScopeHandler.setFunction("assertTrue", (args) -> {
69-
assertTrue(args[0].asInt() != 0);
70-
return NumberValue.ONE;
71-
});
72-
ScopeHandler.setFunction("assertFalse", (args) -> {
73-
assertFalse(args[0].asInt() != 0);
74-
return NumberValue.ONE;
75-
});
76-
ScopeHandler.setFunction("assertFail", (args) -> {
77-
assertThrows(Throwable.class,
78-
() -> ((FunctionValue) args[0]).getValue().execute());
79-
return NumberValue.ONE;
80-
});
81-
ScopeHandler.setFunction("fail", (args) -> {
82-
if (args.length > 0) {
83-
fail(args[0].asString());
84-
} else {
85-
fail();
86-
}
87-
return NumberValue.ONE;
88-
});
89-
return input;
90-
}
91-
9251
@ParameterizedTest
9352
@MethodSource("data")
9453
public void testProgram(InputSource inputSource) {
@@ -119,7 +78,7 @@ public void visit(FunctionDefineStatement s) {
11978

12079
@Override
12180
public void visit(ClassDeclarationStatement s) {
122-
81+
// skip for tests
12382
}
12483
};
12584
}

0 commit comments

Comments
 (0)