Class LanguageTestContexts
null or blank name with a run's message, though
not one with a name a language reserves: they have no engine, and so no languages to ask. Each context from
evaluation or action is for a run of its own, so the values it keeps with
EvaluationContext.runScoped(java.lang.Object, java.util.function.Supplier<? extends T>) aren't shared with another context; actionInRun(io.github.brantunger.unruly.api.language.EvaluationContext, java.lang.Object) creates one in the run
of another context, and shares its values. A context's run started when the context was created, by the system
clock, and has no tags, unless the context was created with evaluation(Map, Instant, Instant, Set) or
action(Map, Object, Instant, Instant, Set), which give it the EvaluationContext.startedAt() and
EvaluationContext.tags() of a run with an engine's clock and RunOptions.withTags(...), or with
actionInRun(io.github.brantunger.unruly.api.language.EvaluationContext, java.lang.Object) from such a context, which has the same start and tags. No run ends by itself, so
endRun(io.github.brantunger.unruly.api.language.EvaluationContext) closes the values a context keeps with EvaluationContext.runScopedClosing(java.lang.Object, java.util.function.Supplier<? extends T>), and the actions
it registered with EvaluationContext.onCancel(Runnable) that haven't started, as the end of a run does.
To check a language against everything the engine promises for its rules, extend
ExpressionLanguageContractTest.
-
Method Summary
Modifier and TypeMethodDescriptionstatic ActionContextCreates the context an action runs against.static ActionContextCreates the context an action runs against, for a run with a deadline.static ActionContextaction(Map<String, ? extends @Nullable Object> facts, Object output, @Nullable Instant deadline, Instant startedAt, Set<String> tags) Creates the context an action runs against, for a run that started atstartedAtby its engine's clock and was giventags: so a language's test can check what its actions make of the run'sEvaluationContext.startedAt()andEvaluationContext.tags(), as a run withRulesEngineBuilder.clock(...)andRunOptions.withTags(...)gives them.static ActionContextactionInRun(EvaluationContext sameRun, Object output) Creates the context an action runs against, in the same run as another context: so a language's test can check that its actions find what its conditions kept withEvaluationContext.runScoped(java.lang.Object, java.util.function.Supplier<? extends T>).static CompileContextcompile()Creates a compile context without imports.static CompileContextcompile(ExpressionLanguage language, Set<String> packageImports, Set<Class<?>> classImports, ClassLoader classLoader, Class<?> outputType, Map<String, String> options, Map<String, Class<?>> declaredFacts, boolean allFactsDeclared, List<String> languageImports) Creates a compile context for one language, which rejects exactly the declarations an engine with that language rejects when it's built: a fact may not be declared with a name the language reserves, as itsExpressionLanguage.reservedFactNames()returns them, asked once, so a language that reserves no name may declareoutput.static CompileContextCreates a compile context.static CompileContextcompile(Set<String> packageImports, Set<Class<?>> classImports, ClassLoader classLoader, Class<?> outputType, Map<String, String> options) Creates a compile context with an output type and the language's options.static CompileContextcompile(Set<String> packageImports, Set<Class<?>> classImports, ClassLoader classLoader, Class<?> outputType, Map<String, String> options, Map<String, Class<?>> declaredFacts, boolean allFactsDeclared) Creates a compile context for an engine that was told which facts its rules use, so a language's tests can check what it makes of the declarations.static CompileContextcompile(Set<String> packageImports, Set<Class<?>> classImports, ClassLoader classLoader, Class<?> outputType, Map<String, String> options, Map<String, Class<?>> declaredFacts, boolean allFactsDeclared, List<String> languageImports) Creates a compile context with the language's own imports, as the engine's builder was given them withRulesEngineBuilder.languageImports(...), so a language's tests can check what it makes of them.static voidendRun(EvaluationContext context) Ends the run of a context, as the engine ends a run: closes the actions the run registered withEvaluationContext.onCancel(Runnable)that haven't started, then the values the run keeps withEvaluationContext.runScopedClosing(java.lang.Object, java.util.function.Supplier<? extends T>), in the reverse of the order they were made, so a language's test can check that it releases what it opened for the run.static EvaluationContextevaluation(Map<String, ? extends @Nullable Object> facts) Creates the context a condition is evaluated against.static EvaluationContextevaluation(Map<String, ? extends @Nullable Object> facts, @Nullable Instant deadline) Creates the context a condition is evaluated against, for a run with a deadline.static EvaluationContextevaluation(Map<String, ? extends @Nullable Object> facts, @Nullable Instant deadline, Instant startedAt, Set<String> tags) Creates the context a condition is evaluated against, for a run that started atstartedAtby its engine's clock and was giventags: so a language's test can check what its conditions make of the run'sEvaluationContext.startedAt()andEvaluationContext.tags(), as a run withRulesEngineBuilder.clock(...)andRunOptions.withTags(...)gives them.
-
Method Details
-
compile
Creates a compile context without imports. Its class loader is the current thread's context class loader, or this class's class loader if the thread has none, as the engine chooses one.- Returns:
- The context
-
compile
public static CompileContext compile(Set<String> packageImports, Set<Class<?>> classImports, ClassLoader classLoader) Creates a compile context.- Parameters:
packageImports- The imported packages, such asjava.util; copiedclassImports- The classes imported one by one; copiedclassLoader- The class loader to look up classes in the imported packages with- Returns:
- The context
- Throws:
NullPointerException- if an argument, or an element of a set, isnullIllegalArgumentException- if an imported package has more than 1,000 characters or more than 64 dot-separated parts, or isn't a valid package name, which an engine rejects too, with the same messageStackOverflowError- if an imported package has a code point above U+00FF, the JDK's tables of such characters, which the check of its name reads, aren't known to be built yet, as no engine has been built and no such import checked yet, and the stack has too little room left to build them, before any is touched, asEngineCompileContextsays (#1366); the next call checks again
-
compile
public static CompileContext compile(Set<String> packageImports, Set<Class<?>> classImports, ClassLoader classLoader, Class<?> outputType, Map<String, String> options) Creates a compile context with an output type and the language's options.- Parameters:
packageImports- The imported packages, such asjava.util; copiedclassImports- The classes imported one by one; copiedclassLoader- The class loader to look up classes in the imported packages withoutputType- The type of the output object, as the engine's builder was told;Object.classwhen it wasn'toptions- The language's options, as the engine's builder was given them; copied- Returns:
- The context
- Throws:
NullPointerException- if an argument, or an element of a set or of the options, isnullIllegalArgumentException- if an imported package has more than 1,000 characters or more than 64 dot-separated parts, or isn't a valid package name, which an engine rejects too, with the same messageStackOverflowError- if an imported package has a code point above U+00FF, the JDK's tables of such characters, which the check of its name reads, aren't known to be built yet, as no engine has been built and no such import checked yet, and the stack has too little room left to build them, before any is touched, asEngineCompileContextsays (#1366); the next call checks again
-
compile
public static CompileContext compile(Set<String> packageImports, Set<Class<?>> classImports, ClassLoader classLoader, Class<?> outputType, Map<String, String> options, Map<String, Class<?>> declaredFacts, boolean allFactsDeclared) Creates a compile context for an engine that was told which facts its rules use, so a language's tests can check what it makes of the declarations.- Parameters:
packageImports- The imported packages, such asjava.util; copiedclassImports- The classes imported one by one; copiedclassLoader- The class loader to look up classes in the imported packages withoutputType- The type of the output object, as the engine's builder was told;Object.classwhen it wasn'toptions- The language's options, as the engine's builder was given them; copieddeclaredFacts- The declared type of each fact, by name, as the engine's builder was told; copiedallFactsDeclared- Whether a run may supply only the declared facts, asRulesEngineBuilder.requireDeclaredFacts()says- Returns:
- The context. A fact declared with a primitive type is given as its wrapper, as an engine gives it.
- Throws:
NullPointerException- if an argument, or an element of a set, of the options or of the declarations, isnullIllegalArgumentException- if an imported package has more than 1,000 characters or more than 64 dot-separated parts, or isn't a valid package name, or a fact is declared with a blank name or the nameoutput, which an engine rejects too when one of its languages reserves it, as the defaultExpressionLanguage.reservedFactNames()doesStackOverflowError- if an imported package has a code point above U+00FF, the JDK's tables of such characters, which the check of its name reads, aren't known to be built yet, as no engine has been built and no such import checked yet, and the stack has too little room left to build them, before any is touched, asEngineCompileContextsays (#1366); the next call checks again
-
compile
public static CompileContext compile(Set<String> packageImports, Set<Class<?>> classImports, ClassLoader classLoader, Class<?> outputType, Map<String, String> options, Map<String, Class<?>> declaredFacts, boolean allFactsDeclared, List<String> languageImports) Creates a compile context with the language's own imports, as the engine's builder was given them withRulesEngineBuilder.languageImports(...), so a language's tests can check what it makes of them.- Parameters:
packageImports- The imported packages, such asjava.util; copiedclassImports- The classes imported one by one; copiedclassLoader- The class loader to look up classes in the imported packages withoutputType- The type of the output object, as the engine's builder was told;Object.classwhen it wasn'toptions- The language's options, as the engine's builder was given them; copieddeclaredFacts- The declared type of each fact, by name, as the engine's builder was told; copiedallFactsDeclared- Whether a run may supply only the declared facts, asRulesEngineBuilder.requireDeclaredFacts()sayslanguageImports- The language's own imports, such aslodash/fp, as written and in order; copied- Returns:
- The context. Its
CompileContext.languageImports()arelanguageImports, duplicates included. A fact declared with a primitive type is given as its wrapper, as an engine gives it. - Throws:
NullPointerException- if an argument, or an element of a set, of the language imports, of the options or of the declarations, isnullIllegalArgumentException- if an imported package has more than 1,000 characters or more than 64 dot-separated parts, or isn't a valid package name, a language import has more than 1,000 characters, or a fact is declared with a blank name or the nameoutput, which an engine rejects too when one of its languages reserves it, as the defaultExpressionLanguage.reservedFactNames()doesStackOverflowError- if an imported package has a code point above U+00FF, the JDK's tables of such characters, which the check of its name reads, aren't known to be built yet, as no engine has been built and no such import checked yet, and the stack has too little room left to build them, before any is touched, asEngineCompileContextsays (#1366); the next call checks again
-
compile
public static CompileContext compile(ExpressionLanguage language, Set<String> packageImports, Set<Class<?>> classImports, ClassLoader classLoader, Class<?> outputType, Map<String, String> options, Map<String, Class<?>> declaredFacts, boolean allFactsDeclared, List<String> languageImports) Creates a compile context for one language, which rejects exactly the declarations an engine with that language rejects when it's built: a fact may not be declared with a name the language reserves, as itsExpressionLanguage.reservedFactNames()returns them, asked once, so a language that reserves no name may declareoutput. The othercompilemethods rejectoutput, which the default reserves.- Parameters:
language- The language the context is for; asked for its name and the fact names it reservespackageImports- The imported packages, such asjava.util; copiedclassImports- The classes imported one by one; copiedclassLoader- The class loader to look up classes in the imported packages withoutputType- The type of the output object, as the engine's builder was told;Object.classwhen it wasn'toptions- The language's options, as the engine's builder was given them; copieddeclaredFacts- The declared type of each fact, by name, as the engine's builder was told; copiedallFactsDeclared- Whether a run may supply only the declared facts, asRulesEngineBuilder.requireDeclaredFacts()sayslanguageImports- The language's own imports, such aslodash/fp, as written and in order; copied- Returns:
- The context. Its
CompileContext.languageImports()arelanguageImports, duplicates included. A fact declared with a primitive type is given as its wrapper, as an engine gives it. - Throws:
NullPointerException- if an argument, or an element of a set, of the language imports, of the options or of the declarations, isnullIllegalArgumentException- if the language's name isnullor blank; if an imported package has more than 1,000 characters or more than 64 dot-separated parts, or isn't a valid package name, a language import has more than 1,000 characters, or a fact is declared with a blank name; or if a fact is declared with a name the language reserves, with the messagebuild()givesIllegalStateException- if the language'sreservedFactNames()returnsnullor a set holdingnull, asbuild()throws itStackOverflowError- if an imported package has a code point above U+00FF, the JDK's tables of such characters, which the check of its name reads, aren't known to be built yet, as no engine has been built and no such import checked yet, and the stack has too little room left to build them, before any is touched, asEngineCompileContextsays (#1366); the next call checks again
-
evaluation
Creates the context a condition is evaluated against.- Parameters:
facts- The facts by name, whose values can benull; copied- Returns:
- The context. Its facts are read-only, and a write fails with the message the engine uses for a condition. It equals only itself, as in a run, so two created from the same facts aren't equal.
- Throws:
NullPointerException- iffactsisnullIllegalArgumentException- if a fact's name isnullor blank, which a run rejects with the same message
-
evaluation
public static EvaluationContext evaluation(Map<String, ? extends @Nullable Object> facts, @Nullable Instant deadline) Creates the context a condition is evaluated against, for a run with a deadline.The context reads the system clock once, when it's created, to learn how far away the deadline is, and from then on times it with a monotonic clock, as a run does: a step of the system clock afterwards doesn't move when the context is cancelled. Its
EvaluationContext.timeLeft()is measured the same way.- Parameters:
facts- The facts by name, whose values can benull; copieddeadline- When the run must stop, ornullif it has none, as an engine built withoutrunTimeoutgives it- Returns:
- The context. Its
EvaluationContext.isCancelled()answers as it does in a run:trueonce the deadline has passed, measured with a monotonic clock from when the context was created, or while the calling thread's interrupt status is set. It equals only itself, as in a run. - Throws:
NullPointerException- iffactsisnullIllegalArgumentException- if a fact's name isnullor blank, which a run rejects with the same message
-
evaluation
public static EvaluationContext evaluation(Map<String, ? extends @Nullable Object> facts, @Nullable Instant deadline, Instant startedAt, Set<String> tags) Creates the context a condition is evaluated against, for a run that started atstartedAtby its engine's clock and was giventags: so a language's test can check what its conditions make of the run'sEvaluationContext.startedAt()andEvaluationContext.tags(), as a run withRulesEngineBuilder.clock(...)andRunOptions.withTags(...)gives them. The deadline is timed asevaluation(Map, Instant)describes.- Parameters:
facts- The facts by name, whose values can benull; copieddeadline- When the run must stop, ornullif it has none, as an engine built withoutrunTimeoutgives itstartedAt- When the run started, by the engine's clock, as a fixed clock gives ittags- The run's tags, asRunOptions.withTags(...)was given them, or empty for a run that uses every rule; copied- Returns:
- The context. Its
EvaluationContext.startedAt()isstartedAt, and itsEvaluationContext.tags()aretagsas a run has them: inStringorder and unmodifiable. It equals only itself, as in a run. - Throws:
NullPointerException- iffacts,startedAtortagsisnullIllegalArgumentException- if a fact's name isnullor blank, or a tag isnullor blank, which a run rejects with the same message
-
action
Creates the context an action runs against.- Parameters:
facts- The facts by name, whose values can benull; copiedoutput- The output object, which the action changes in place- Returns:
- The context. Its facts are read-only, and a write fails with the message the engine uses for an action. It equals only itself, as in a run, so two created from the same facts and output aren't equal.
- Throws:
NullPointerException- iffactsoroutputisnullIllegalArgumentException- if a fact's name isnullor blank, which a run rejects with the same message
-
action
public static ActionContext action(Map<String, ? extends @Nullable Object> facts, Object output, @Nullable Instant deadline) Creates the context an action runs against, for a run with a deadline.The context reads the system clock once, when it's created, to learn how far away the deadline is, and from then on times it with a monotonic clock, as a run does: a step of the system clock afterwards doesn't move when the context is cancelled. Its
EvaluationContext.timeLeft()is measured the same way.- Parameters:
facts- The facts by name, whose values can benull; copiedoutput- The output object, which the action changes in placedeadline- When the run must stop, ornullif it has none, as an engine built withoutrunTimeoutgives it- Returns:
- The context. Its
EvaluationContext.isCancelled()answers as it does in a run, and it equals only itself. - Throws:
NullPointerException- iffactsoroutputisnullIllegalArgumentException- if a fact's name isnullor blank, which a run rejects with the same message
-
action
public static ActionContext action(Map<String, ? extends @Nullable Object> facts, Object output, @Nullable Instant deadline, Instant startedAt, Set<String> tags) Creates the context an action runs against, for a run that started atstartedAtby its engine's clock and was giventags: so a language's test can check what its actions make of the run'sEvaluationContext.startedAt()andEvaluationContext.tags(), as a run withRulesEngineBuilder.clock(...)andRunOptions.withTags(...)gives them. The deadline is timed asaction(Map, Object, Instant)describes.- Parameters:
facts- The facts by name, whose values can benull; copiedoutput- The output object, which the action changes in placedeadline- When the run must stop, ornullif it has none, as an engine built withoutrunTimeoutgives itstartedAt- When the run started, by the engine's clock, as a fixed clock gives ittags- The run's tags, asRunOptions.withTags(...)was given them, or empty for a run that uses every rule; copied- Returns:
- The context. Its
EvaluationContext.startedAt()isstartedAt, and itsEvaluationContext.tags()aretagsas a run has them: inStringorder and unmodifiable. It equals only itself, as in a run. - Throws:
NullPointerException- iffacts,output,startedAtortagsisnullIllegalArgumentException- if a fact's name isnullor blank, or a tag isnullor blank, which a run rejects with the same message
-
actionInRun
Creates the context an action runs against, in the same run as another context: so a language's test can check that its actions find what its conditions kept withEvaluationContext.runScoped(java.lang.Object, java.util.function.Supplier<? extends T>).- Parameters:
sameRun- A context of the run, created by this class, such as withevaluation(Map)output- The output object, which the action changes in place- Returns:
- The context. It has the facts, deadline,
startandtagsofsameRun, and shares its run-scoped values. Its facts are read-only, and a write fails with the message the engine uses for an action. It equals only itself. - Throws:
NullPointerException- ifsameRunoroutputisnull
-
endRun
Ends the run of a context, as the engine ends a run: closes the actions the run registered withEvaluationContext.onCancel(Runnable)that haven't started, then the values the run keeps withEvaluationContext.runScopedClosing(java.lang.Object, java.util.function.Supplier<? extends T>), in the reverse of the order they were made, so a language's test can check that it releases what it opened for the run. Every value is closed, whatever the others throw, unless both waits below fail, and from then on asking for one withrunScopedClosing, or registering an action withonCancel, through any context of the run, throwsIllegalStateException, as it does once a run has ended. It first waits, with no limit, for arunScopedClosinginit running on another thread. If that wait fails, as it can when the stack or the heap runs out, it waits once more, as a run does, and closes what that hands over; if that fails too, it closes nothing, closes no action, and the run hasn't ended. A second call does nothing, unless both waits failed: it then closes the values left open.Called from a
runScopedClosinginit that goes on to return a value, it closes the run's values, and that value is closed too, and refused:runScopedClosingthrows the sameIllegalStateException, with what thatclose()threw suppressed on it, unless that is or carries a fatalError, which it throws in its place, carrying theIllegalStateException. So a value is never left open, unless both ofendRun's waits failed.It differs from a run in one way: a run logs what a
close()throws at WARN, and throws only a fatalError, but this throws whatever was thrown, so the test sees it.- Parameters:
context- A context of the run, created by this class, such as withevaluation(Map)- Throws:
NullPointerException- ifcontextisnullException- what waiting for an init on another thread threw, if it failed, or else the firstThrowablea value'sclose()threw, as it is; every otherclose()failure, what waiting again threw, and the first failure to keep one of them are suppressed on it, as far as keeping them doesn't fail: each once, and none it already carries or that carries itError- aVirtualMachineErrorother thanStackOverflowError, and other than anInternalErrorthat wraps one with noLinkageErrorbetween them, that keeping what failed before on the first failure threw, once every value is closed, in place of the first failure, which it doesn't carry
-