1818import static org .junit .jupiter .api .Assertions .assertTrue ;
1919
2020public class BasicConstraintTests extends ProceduralSchedulingSetup {
21- private ConstraintInvocationId fruitTresholdConstraintId ;
21+ private ConstraintInvocationId fruitThresholdConstraintId ;
22+ private ConstraintInvocationId noMessageConstraintId ;
2223
2324 @ BeforeEach
2425 void localBeforeEach () throws IOException {
2526 try (final var gateway = new GatewayRequests (playwright )) {
26- final int fruitTresholdConstraintJarId = gateway .uploadJarFile ("build/libs/FruitThresholdConstraint.jar" );
27- // Add Scheduling Procedure
28- fruitTresholdConstraintId = hasura .createConstraintSpecProcedure (
29- "Test Constraint Procedure 1" ,
30- fruitTresholdConstraintJarId ,
27+ final int fruitThresholdConstraintJarId = gateway .uploadJarFile ("build/libs/FruitThresholdConstraint.jar" );
28+ final int noMessageConstraintJarId = gateway .uploadJarFile ("build/libs/NoMessageConstraint.jar" );
29+ // Add Constraint Procedures
30+ fruitThresholdConstraintId = hasura .createConstraintSpecProcedure (
31+ "Fruit Threshold Constraint" ,
32+ fruitThresholdConstraintJarId ,
3133 planId
3234 );
35+ noMessageConstraintId = hasura .createConstraintSpecProcedure (
36+ "No Message Constraint" ,
37+ noMessageConstraintJarId ,
38+ planId
39+ );
40+
41+ // Disable the noMessageConstraint by default
42+ hasura .updatePlanConstraintSpecEnabled (noMessageConstraintId .invocationId (), false );
3343 }
3444 }
3545
3646 @ AfterEach
3747 void localAfterEach () throws IOException {
38- hasura .deleteConstraint (fruitTresholdConstraintId .id ());
48+ hasura .deleteConstraint (fruitThresholdConstraintId .id ());
49+ hasura .deleteConstraint (noMessageConstraintId .id ());
3950 }
4051
4152 /**
@@ -47,8 +58,15 @@ void executeConstraintRunWithoutArguments() throws IOException {
4758 hasura .awaitSimulation (planId );
4859 final var resp = hasura .checkConstraints (planId );
4960 assertEquals (1 , resp .constraintsRun ().size ());
50- assertEquals (1 , resp .constraintsRun ().getFirst ().errors ().size ());
51- assertTrue (resp .constraintsRun ().getFirst ().errors ().getFirst ().message ().contains ("gov.nasa.jpl.aerie.merlin.protocol.types.InstantiationException: Invalid arguments for input type \" FruitThresholdConstraint\" : extraneous arguments: [], unconstructable arguments: [], missing arguments: [MissingArgument[parameterName=upperBound, schema=IntSchema[]]], valid arguments: [ValidArgument[parameterName=lowerBound, serializedValue=NumericValue[value=5]]]" ));
61+ final var constraint = resp .constraintsRun ().getFirst ();
62+ assertEquals (1 , constraint .errors ().size ());
63+ assertTrue (constraint .errors ().getFirst ().message ().contains (
64+ "gov.nasa.jpl.aerie.merlin.protocol.types.InstantiationException: Invalid arguments for input type "
65+ + "\" FruitThresholdConstraint\" : "
66+ + "extraneous arguments: [], "
67+ + "unconstructable arguments: [], "
68+ + "missing arguments: [MissingArgument[parameterName=upperBound, schema=IntSchema[]]], "
69+ + "valid arguments: [ValidArgument[parameterName=lowerBound, serializedValue=NumericValue[value=5]]]" ));
5270 }
5371
5472 /**
@@ -57,7 +75,7 @@ void executeConstraintRunWithoutArguments() throws IOException {
5775 @ Test
5876 void executeConstraintRunWithArguments () throws IOException {
5977 final var args = Json .createObjectBuilder ().add ("upperBound" , 10 ).build ();
60- hasura .updateConstraintArguments (fruitTresholdConstraintId .invocationId (), args );
78+ hasura .updateConstraintArguments (fruitThresholdConstraintId .invocationId (), args );
6179 hasura .awaitSimulation (planId );
6280 final var resp = hasura .checkConstraints (planId );
6381 assertTrue (resp .constraintsRun ().getFirst ().success ());
@@ -68,20 +86,55 @@ void executeConstraintRunWithArguments() throws IOException {
6886 assertEquals (violation .windows (), List .of (new ConstraintResult .Interval (0 , Duration .hours (48 ).micros ())));
6987 }
7088
89+ /**
90+ * Test that constraints with a violation message include said violation message.
91+ */
92+ @ Test
93+ void messageReturnedIfPresent () throws IOException {
94+ // Enable the NoMessageConstraint
95+ hasura .updatePlanConstraintSpecEnabled (noMessageConstraintId .invocationId (), true );
96+
97+ // Assign args to the constraints
98+ final var args = Json .createObjectBuilder ().add ("upperBound" , 10 ).build ();
99+ hasura .updateConstraintArguments (fruitThresholdConstraintId .invocationId (), args );
100+ hasura .updateConstraintArguments (noMessageConstraintId .invocationId (), args );
101+
102+ // Get Constraint Results
103+ hasura .awaitSimulation (planId );
104+ final var resp = hasura .checkConstraints (planId );
105+
106+ assertEquals (2 , resp .constraintsRun ().size ());
107+
108+ final var firstConstraint = resp .constraintsRun ().getFirst ();
109+ assertEquals (fruitThresholdConstraintId .invocationId (), firstConstraint .constraintInvocationId ());
110+ assertTrue (firstConstraint .success ());
111+ assertEquals (1 , firstConstraint .result ().get ().violations ().size ());
112+ final var firstConstraintViolation = firstConstraint .result ().get ().violations ().getFirst ();
113+ assertTrue (firstConstraintViolation .message ().isPresent ());
114+ assertEquals ("Fruit count is outside of boundaries: [5, 10]" , firstConstraintViolation .message ().get ());
115+
116+ final var secondConstraint = resp .constraintsRun ().getLast ();
117+ assertEquals (noMessageConstraintId .invocationId (), firstConstraint .constraintInvocationId ());
118+ assertTrue (secondConstraint .success ());
119+ assertEquals (1 , secondConstraint .result ().get ().violations ().size ());
120+ final var secondConstraintViolation = secondConstraint .result ().get ().violations ().getFirst ();
121+ assertTrue (secondConstraintViolation .message ().isEmpty ());
122+ }
123+
71124 /**
72125 * Queries the procedural constraints arguments.
73126 */
74127 @ Test
75128 void effectiveArgumentsQuery () throws IOException {
76129 final var effectiveArgs = hasura .getEffectiveProceduralConstraintsArgumentsBulk (
77- List .of (Pair .of (fruitTresholdConstraintId .id (), Json .createObjectBuilder ().add ("upperBound" , 10 ).build ())));
130+ List .of (Pair .of (fruitThresholdConstraintId .id (), Json .createObjectBuilder ().add ("upperBound" , 10 ).build ())));
78131 assertEquals (1 , effectiveArgs .size ());
79- assertTrue (effectiveArgs .get ( 0 ).success ());
80- assertTrue (effectiveArgs .get ( 0 ).arguments ().isPresent ());
81- assertTrue (effectiveArgs .get ( 0 ).errors ().isEmpty ());
132+ assertTrue (effectiveArgs .getFirst ( ).success ());
133+ assertTrue (effectiveArgs .getFirst ( ).arguments ().isPresent ());
134+ assertTrue (effectiveArgs .getFirst ( ).errors ().isEmpty ());
82135
83136 // Check returned Arguments
84- final var args = effectiveArgs .get ( 0 ).arguments ().get ();
137+ final var args = effectiveArgs .getFirst ( ).arguments ().get ();
85138 assertEquals (2 , args .size ());
86139 assertEquals (10 , args .getInt ("upperBound" ));
87140 assertEquals (5 , args .getInt ("lowerBound" ));
0 commit comments