33import static org .assertj .core .api .Assertions .assertThat ;
44
55import com .google .common .collect .ImmutableMap ;
6+ import com .google .common .collect .ImmutableSet ;
7+ import com .hubspot .jinjava .Jinjava ;
68import com .hubspot .jinjava .JinjavaConfig ;
79import com .hubspot .jinjava .LegacyOverrides ;
10+ import com .hubspot .jinjava .interpret .Context ;
811import com .hubspot .jinjava .interpret .Context .Library ;
912import com .hubspot .jinjava .interpret .DeferredValue ;
1013import com .hubspot .jinjava .interpret .JinjavaInterpreter ;
1417import com .hubspot .jinjava .objects .collections .PyList ;
1518import com .hubspot .jinjava .tree .ExpressionNodeTest ;
1619import java .util .ArrayList ;
17- import java .util .Collections ;
18- import org .junit .After ;
1920import org .junit .Before ;
2021import org .junit .Test ;
2122
2223public class EagerExpressionStrategyTest extends ExpressionNodeTest {
2324
25+ private Jinjava jinjava ;
26+
27+ class EagerExecutionModeNoRaw extends EagerExecutionMode {
28+
29+ @ Override
30+ public boolean isPreserveRawTags () {
31+ return false ; // So that we can run all the ExpressionNodeTest tests without having the extra `{% raw %}` tags inserted
32+ }
33+ }
34+
2435 @ Before
2536 public void eagerSetup () throws Exception {
37+ jinjava = new Jinjava (JinjavaConfig .newBuilder ().build ());
2638 jinjava
2739 .getGlobalContext ()
2840 .registerFunction (
@@ -35,51 +47,52 @@ public void eagerSetup() throws Exception {
3547 interpreter =
3648 new JinjavaInterpreter (
3749 jinjava ,
38- context ,
50+ new Context () ,
3951 JinjavaConfig
4052 .newBuilder ()
53+ .withExecutionMode (new EagerExecutionModeNoRaw ())
54+ .build ()
55+ );
56+ nestedInterpreter =
57+ new JinjavaInterpreter (
58+ jinjava ,
59+ interpreter .getContext (),
60+ JinjavaConfig
61+ .newBuilder ()
62+ .withNestedInterpretationEnabled (true )
63+ .withLegacyOverrides (
64+ LegacyOverrides .newBuilder ().withUsePyishObjectMapper (true ).build ()
65+ )
4166 .withExecutionMode (EagerExecutionMode .instance ())
4267 .build ()
4368 );
44- JinjavaInterpreter .pushCurrent (interpreter );
45- context .put ("deferred" , DeferredValue .instance ());
46- }
47-
48- @ After
49- public void teardown () {
50- JinjavaInterpreter .popCurrent ();
69+ interpreter .getContext ().put ("deferred" , DeferredValue .instance ());
70+ nestedInterpreter .getContext ().put ("deferred" , DeferredValue .instance ());
5171 }
5272
5373 @ Test
5474 public void itPreservesRawTags () {
5575 interpreter =
5676 new JinjavaInterpreter (
5777 jinjava ,
58- context ,
78+ new Context () ,
5979 JinjavaConfig
6080 .newBuilder ()
61- .withNestedInterpretationEnabled (false )
62- .withLegacyOverrides (
63- LegacyOverrides .newBuilder ().withUsePyishObjectMapper (true ).build ()
64- )
6581 .withExecutionMode (EagerExecutionMode .instance ())
6682 .build ()
6783 );
68- JinjavaInterpreter .pushCurrent (interpreter );
69- try {
70- assertExpectedOutput (
71- "{{ '{{ foo }}' }} {{ '{% something %}' }} {{ 'not needed' }}" ,
72- "{% raw %}{{ foo }}{% endraw %} {% raw %}{% something %}{% endraw %} not needed"
73- );
74- } finally {
75- JinjavaInterpreter .popCurrent ();
76- }
84+ assertExpectedOutput (
85+ interpreter ,
86+ "{{ '{{ foo }}' }} {{ '{% something %}' }} {{ 'not needed' }}" ,
87+ "{% raw %}{{ foo }}{% endraw %} {% raw %}{% something %}{% endraw %} not needed"
88+ );
7789 }
7890
7991 @ Test
8092 public void itPreservesRawTagsNestedInterpretation () {
81- context .put ("bar" , "bar" );
93+ nestedInterpreter . getContext () .put ("bar" , "bar" );
8294 assertExpectedOutput (
95+ nestedInterpreter ,
8396 "{{ '{{ 12345 }}' }} {{ '{% print bar %}' }} {{ 'not needed' }}" ,
8497 "12345 bar not needed"
8598 );
@@ -88,24 +101,27 @@ public void itPreservesRawTagsNestedInterpretation() {
88101 @ Test
89102 public void itPrependsMacro () {
90103 assertExpectedOutput (
104+ interpreter ,
91105 "{% macro foo(bar) %} {{ bar }} {% endmacro %}{{ foo(deferred) }}" ,
92106 "{% macro foo(bar) %} {{ bar }} {% endmacro %}{{ foo(deferred) }}"
93107 );
94108 }
95109
96110 @ Test
97111 public void itPrependsSet () {
98- context .put ("foo" , new PyList (new ArrayList <>()));
112+ interpreter . getContext () .put ("foo" , new PyList (new ArrayList <>()));
99113 assertExpectedOutput (
114+ interpreter ,
100115 "{{ foo.append(deferred) }}" ,
101116 "{% set foo = [] %}{{ foo.append(deferred) }}"
102117 );
103118 }
104119
105120 @ Test
106121 public void itDoesConcatenation () {
107- context .put ("foo" , "y'all" );
122+ interpreter . getContext () .put ("foo" , "y'all" );
108123 assertExpectedOutput (
124+ interpreter ,
109125 "{{ 'oh, ' ~ foo ~ foo ~ ' toaster' }}" ,
110126 "oh, y'ally'all toaster"
111127 );
@@ -116,6 +132,7 @@ public void itHandlesQuotesLikeJinja() {
116132 // {{ 'a|\'|\\\'|\\\\\'|"|\"|\\"|\\\\"|a ' ~ " b|\"|\\\"|\\\\\"|'|\'|\\'|\\\\'|b" }}
117133 // --> a|'|\'|\\'|"|"|\"|\\"|a b|"|\"|\\"|'|'|\'|\\'|b
118134 assertExpectedOutput (
135+ interpreter ,
119136 "{{ 'a|\\ '|\\ \\ \\ '|\\ \\ \\ \\ \\ '|\" |\\ \" |\\ \\ \" |\\ \\ \\ \\ \" |a ' " +
120137 "~ \" b|\\ \" |\\ \\ \\ \" |\\ \\ \\ \\ \\ \" |'|\\ '|\\ \\ '|\\ \\ \\ \\ '|b\" }}" ,
121138 "a|'|\\ '|\\ \\ '|\" |\" |\\ \" |\\ \\ \" |a b|\" |\\ \" |\\ \\ \" |'|'|\\ '|\\ \\ '|b"
@@ -125,6 +142,7 @@ public void itHandlesQuotesLikeJinja() {
125142 @ Test
126143 public void itGoesIntoDeferredExecutionMode () {
127144 assertExpectedOutput (
145+ interpreter ,
128146 "{{ is_deferred_execution_mode() }}" +
129147 "{% if deferred %}{{ is_deferred_execution_mode() }}{% endif %}" +
130148 "{{ is_deferred_execution_mode() }}" ,
@@ -135,6 +153,7 @@ public void itGoesIntoDeferredExecutionMode() {
135153 @ Test
136154 public void itGoesIntoDeferredExecutionModeWithMacro () {
137155 assertExpectedOutput (
156+ interpreter ,
138157 "{% macro def() %}{{ is_deferred_execution_mode() }}{% endmacro %}" +
139158 "{{ def() }}" +
140159 "{% if deferred %}{{ def() }}{% endif %}" +
@@ -145,20 +164,28 @@ public void itGoesIntoDeferredExecutionModeWithMacro() {
145164
146165 @ Test
147166 public void itDoesNotGoIntoDeferredExecutionModeUnnecessarily () {
148- assertExpectedOutput ("{{ is_deferred_execution_mode() }}" , "false" );
167+ assertExpectedOutput (interpreter , "{{ is_deferred_execution_mode() }}" , "false" );
149168 interpreter .getContext ().setDeferredExecutionMode (true );
150- assertExpectedOutput ("{{ is_deferred_execution_mode() }}" , "true" );
169+ assertExpectedOutput (interpreter , "{{ is_deferred_execution_mode() }}" , "true" );
151170 }
152171
153172 @ Test
154173 public void itDoesNotNestedInterpretIfThereAreFakeNotes () {
155- assertExpectedOutput ("{{ '{#something_to_{{keep}}' }}" , "{#something_to_{{keep}}" );
174+ assertExpectedOutput (
175+ nestedInterpreter ,
176+ "{{ '{#something_to_{{keep}}' }}" ,
177+ "{#something_to_{{keep}}"
178+ );
156179 }
157180
158181 @ Test
159182 public void itDoesNotReconstructWithDoubleCurlyBraces () {
160183 interpreter .getContext ().put ("foo" , ImmutableMap .of ("foo" , ImmutableMap .of ()));
161- assertExpectedOutput ("{{ deferred ~ foo }}" , "{{ deferred ~ {'foo': {} } }}" );
184+ assertExpectedOutput (
185+ interpreter ,
186+ "{{ deferred ~ foo }}" ,
187+ "{{ deferred ~ {'foo': {} } }}"
188+ );
162189 }
163190
164191 @ Test
@@ -167,6 +194,7 @@ public void itDoesNotReconstructWithNestedDoubleCurlyBraces() {
167194 .getContext ()
168195 .put ("foo" , ImmutableMap .of ("foo" , ImmutableMap .of ("bar" , ImmutableMap .of ())));
169196 assertExpectedOutput (
197+ interpreter ,
170198 "{{ deferred ~ foo }}" ,
171199 "{{ deferred ~ {'foo': {'bar': {} } } }}"
172200 );
@@ -175,6 +203,7 @@ public void itDoesNotReconstructWithNestedDoubleCurlyBraces() {
175203 @ Test
176204 public void itDoesNotReconstructDirectlyWrittenWithDoubleCurlyBraces () {
177205 assertExpectedOutput (
206+ interpreter ,
178207 "{{ deferred ~ {\n 'foo': {\n 'bar': deferred\n }\n }\n }}" ,
179208 "{{ deferred ~ {'foo': {'bar': deferred} } }}"
180209 );
@@ -184,6 +213,7 @@ public void itDoesNotReconstructDirectlyWrittenWithDoubleCurlyBraces() {
184213 public void itReconstructsWithNestedInterpretation () {
185214 interpreter .getContext ().put ("foo" , "{{ print 'bar' }}" );
186215 assertExpectedOutput (
216+ interpreter ,
187217 "{{ deferred ~ foo }}" ,
188218 "{{ deferred ~ '{{ print \\ 'bar\\ ' }}' }}"
189219 );
@@ -192,18 +222,24 @@ public void itReconstructsWithNestedInterpretation() {
192222 @ Test
193223 public void itDoesNotDoNestedInterpretationWithSyntaxErrors () {
194224 try (
195- InterpreterScopeClosable c = interpreter .enterScope (
196- ImmutableMap .of (Library .TAG , Collections . singleton ("print" ))
225+ InterpreterScopeClosable c = nestedInterpreter .enterScope (
226+ ImmutableMap .of (Library .TAG , ImmutableSet . of ("print" ))
197227 )
198228 ) {
199- interpreter .getContext ().put ("foo" , "{% print 'bar' %}" );
229+ nestedInterpreter .getContext ().put ("foo" , "{% print 'bar' %}" );
200230 // Rather than rendering this to an empty string
201- assertThat ( interpreter . render ( "{{ foo }}" )). isEqualTo ( "{% print 'bar' %}" );
231+ assertExpectedOutput ( nestedInterpreter , "{{ foo }}" , "{% print 'bar' %}" );
202232 }
203233 }
204234
205- private void assertExpectedOutput (String inputTemplate , String expectedOutput ) {
206- assertThat (interpreter .render (inputTemplate )).isEqualTo (expectedOutput );
235+ private void assertExpectedOutput (
236+ JinjavaInterpreter interpreter ,
237+ String inputTemplate ,
238+ String expectedOutput
239+ ) {
240+ try (var a = JinjavaInterpreter .closeablePushCurrent (interpreter ).get ()) {
241+ assertThat (a .value ().render (inputTemplate )).isEqualTo (expectedOutput );
242+ }
207243 }
208244
209245 public static boolean isDeferredExecutionMode () {
0 commit comments