1 // Copyright 2017 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "fxjs/xfa/cfxjse_engine.h"
6 #include "fxjs/xfa/cfxjse_value.h"
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "testing/xfa_js_embedder_test.h"
9 #include "xfa/fxfa/cxfa_eventparam.h"
10 
11 class CFXJSE_FormCalcContextEmbedderTest : public XFAJSEmbedderTest {
12  public:
13   CFXJSE_FormCalcContextEmbedderTest() = default;
14   ~CFXJSE_FormCalcContextEmbedderTest() override = default;
15 
16  protected:
ExecuteExpectNull(ByteStringView input)17   bool ExecuteExpectNull(ByteStringView input) {
18     return Execute(input) && GetValue()->IsNull();
19   }
20 };
21 
22 // TODO(dsinclair): Comment out tests are broken and need to be fixed.
23 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,TranslateEmpty)24 TEST_F(CFXJSE_FormCalcContextEmbedderTest, TranslateEmpty) {
25   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
26 
27   const char input[] = "";
28   EXPECT_TRUE(Execute(input));
29   // TODO(dsinclair): This should probably throw as a blank formcalc script
30   // is invalid.
31 }
32 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,TranslateNumber)33 TEST_F(CFXJSE_FormCalcContextEmbedderTest, TranslateNumber) {
34   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
35 
36   const char input[] = "123";
37   EXPECT_TRUE(Execute(input));
38 
39   CFXJSE_Value* value = GetValue();
40   EXPECT_TRUE(value->IsInteger());
41   EXPECT_EQ(123, value->ToInteger()) << "Program: " << input;
42 }
43 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Numeric)44 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Numeric) {
45   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
46 
47   struct {
48     const char* program;
49     int result;
50   } tests[] = {{"123 + 456", 579},
51                {"2 - 3 * 10 / 2 + 7", -6},
52                {"10 * 3 + 5 * 4", 50},
53                {"(5 - \"abc\") * 3", 15},
54                {"\"100\" / 10e1", 1},
55                {"5 + null + 3", 8},
56                // {"if (\"abc\") then\n"
57                //  "  10\n"
58                //  "else\n"
59                //  "  20\n"
60                //  "endif",
61                //  20},
62                // {"3 / 0 + 1", 0},
63                {"-(17)", -17},
64                {"-(-17)", 17},
65                {"+(17)", 17},
66                {"+(-17)", -17},
67                {"if (1 < 2) then\n1\nendif", 1},
68                {"if (\"abc\" > \"def\") then\n"
69                 "  1 and 0\n"
70                 "else\n"
71                 "  0\n"
72                 "endif",
73                 0}};
74 
75   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
76     EXPECT_TRUE(Execute(tests[i].program));
77 
78     CFXJSE_Value* value = GetValue();
79     EXPECT_TRUE(value->IsInteger());
80     EXPECT_EQ(tests[i].result, value->ToInteger())
81         << "Program: " << tests[i].program;
82   }
83 }
84 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Strings)85 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Strings) {
86   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
87 
88   struct {
89     const char* program;
90     const char* result;
91   } tests[] = {
92       {"\"abc\"", "abc"},
93       {"concat(\"The total is \", 2, \" dollars and \", 57, \" cents.\")",
94        "The total is 2 dollars and 57 cents."}};
95 
96   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
97     EXPECT_TRUE(Execute(tests[i].program));
98 
99     CFXJSE_Value* value = GetValue();
100     EXPECT_TRUE(value->IsString());
101     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
102         << "Program: " << tests[i].program << " Result: '" << value->ToString()
103         << "'";
104   }
105 }
106 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Booleans)107 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Booleans) {
108   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
109 
110   struct {
111     const char* program;
112     bool result;
113   } tests[] = {{"0 and 1 or 2 > 1", true},
114                {"2 < 3 not 1 == 1", false},
115                {"\"abc\" | 2", true},
116                {"1 or 0", true},
117                {"0 | 0", false},
118                {"0 or 1 | 0 or 0", true},
119                {"1 and 0", false},
120                // {"0 & 0", true},  // TODO(dsinclair) Confirm with Reader.
121                {"0 and 1 & 0 and 0", false},
122                {"not(\"true\")", true},
123                {"not(1)", false},
124                {"3 == 3", true},
125                {"3 <> 4", true},
126                {"\"abc\" eq \"def\"", false},
127                {"\"def\" ne \"abc\"", true},
128                {"5 + 5 == 10", true},
129                {"5 + 5 <> \"10\"", false},
130                {"3 < 3", false},
131                {"3 > 4", false},
132                {"\"abc\" <= \"def\"", true},
133                {"\"def\" > \"abc\"", true},
134                {"12 >= 12", true},
135                {"\"true\" < \"false\"", false}};
136 
137   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
138     EXPECT_TRUE(Execute(tests[i].program));
139 
140     CFXJSE_Value* value = GetValue();
141     EXPECT_TRUE(value->IsInteger()) << "Program: " << tests[i].program;
142     EXPECT_EQ(tests[i].result, value->ToBoolean())
143         << "Program: " << tests[i].program;
144   }
145 }
146 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Abs)147 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Abs) {
148   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
149 
150   struct {
151     const char* program;
152     float result;
153   } tests[] = {{"Abs(1.03)", 1.03f}, {"Abs(-1.03)", 1.03f}, {"Abs(0)", 0.0f}};
154 
155   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
156     EXPECT_TRUE(Execute(tests[i].program));
157 
158     CFXJSE_Value* value = GetValue();
159     EXPECT_TRUE(value->IsNumber());
160     EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat())
161         << "Program: " << tests[i].program;
162   }
163 }
164 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Avg)165 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Avg) {
166   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
167 
168   struct {
169     const char* program;
170     float result;
171   } tests[] = {{"Avg(0, 32, 16)", 16.0f}, {"Avg(2.5, 17, null)", 9.75f}};
172 
173   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
174     EXPECT_TRUE(Execute(tests[i].program));
175 
176     CFXJSE_Value* value = GetValue();
177     EXPECT_TRUE(value->IsNumber());
178     EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat())
179         << "Program: " << tests[i].program;
180   }
181 }
182 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Ceil)183 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Ceil) {
184   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
185 
186   struct {
187     const char* program;
188     int result;
189   } tests[] = {{"Ceil(2.5875)", 3}, {"Ceil(-5.9)", -5}, {"Ceil(\"abc\")", 0}};
190 
191   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
192     EXPECT_TRUE(Execute(tests[i].program));
193 
194     CFXJSE_Value* value = GetValue();
195     EXPECT_TRUE(value->IsInteger());
196     EXPECT_EQ(tests[i].result, value->ToInteger())
197         << "Program: " << tests[i].program;
198   }
199 }
200 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Count)201 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Count) {
202   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
203 
204   struct {
205     const char* program;
206     int result;
207   } tests[] = {{"Count(\"Tony\", \"Blue\", 41)", 3}};
208 
209   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
210     EXPECT_TRUE(Execute(tests[i].program));
211 
212     CFXJSE_Value* value = GetValue();
213     EXPECT_TRUE(value->IsInteger());
214     EXPECT_EQ(tests[i].result, value->ToInteger())
215         << "Program: " << tests[i].program;
216   }
217 }
218 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Floor)219 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Floor) {
220   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
221 
222   struct {
223     const char* program;
224     int result;
225   } tests[] = {{"Floor(21.3409873)", 21},
226                {"Floor(5.999965342)", 5},
227                {"Floor(3.2 * 15)", 48}};
228 
229   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
230     EXPECT_TRUE(Execute(tests[i].program));
231 
232     CFXJSE_Value* value = GetValue();
233     EXPECT_TRUE(value->IsInteger());
234     EXPECT_EQ(tests[i].result, value->ToInteger())
235         << "Program: " << tests[i].program;
236   }
237 }
238 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Max)239 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Max) {
240   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
241 
242   struct {
243     const char* program;
244     int result;
245   } tests[] = {{"Max(234, 15, 107)", 234},
246                {"Max(\"abc\", 15, \"Tony Blue\")", 15},
247                {"Max(\"abc\")", 0}};
248 
249   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
250     EXPECT_TRUE(Execute(tests[i].program));
251 
252     CFXJSE_Value* value = GetValue();
253     EXPECT_TRUE(value->IsInteger());
254     EXPECT_EQ(tests[i].result, value->ToInteger())
255         << "Program: " << tests[i].program;
256   }
257 }
258 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Min)259 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Min) {
260   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
261 
262   struct {
263     const char* program;
264     int result;
265   } tests[] = {{"Min(234, 15, 107)", 15},
266                // TODO(dsinclair): Verify with Reader; I believe this should
267                // have a return of 0.
268                // {"Min(\"abc\", 15, \"Tony Blue\")", 15},
269                {"Min(\"abc\")", 0}};
270 
271   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
272     EXPECT_TRUE(Execute(tests[i].program));
273 
274     CFXJSE_Value* value = GetValue();
275     EXPECT_TRUE(value->IsInteger());
276     EXPECT_EQ(tests[i].result, value->ToInteger())
277         << "Program: " << tests[i].program;
278   }
279 }
280 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Mod)281 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Mod) {
282   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
283 
284   struct {
285     const char* program;
286     int result;
287   } tests[] = {{"Mod(64, -3)", 1}, {"Mod(-13, 3)", -1}, {"Mod(\"abc\", 2)", 0}};
288 
289   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
290     EXPECT_TRUE(Execute(tests[i].program));
291 
292     CFXJSE_Value* value = GetValue();
293     EXPECT_TRUE(value->IsInteger());
294     EXPECT_EQ(tests[i].result, value->ToInteger())
295         << "Program: " << tests[i].program;
296   }
297 }
298 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Round)299 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Round) {
300   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
301 
302   struct {
303     const char* program;
304     float result;
305   } tests[] = {{"Round(12.389764537, 4)", 12.3898f},
306                {"Round(20/3, 2)", 6.67f},
307                {"Round(8.9897, \"abc\")", 9.0f},
308                {"Round(FV(400, 0.10/12, 30*12), 2)", 904195.17f}};
309 
310   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
311     EXPECT_TRUE(Execute(tests[i].program));
312 
313     CFXJSE_Value* value = GetValue();
314     EXPECT_TRUE(value->IsNumber()) << "Program: " << tests[i].program;
315     EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat())
316         << "Program: " << tests[i].program;
317   }
318 }
319 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Sum)320 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Sum) {
321   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
322 
323   struct {
324     const char* program;
325     int result;
326   } tests[] = {{"Sum(2, 4, 6, 8)", 20},
327                {"Sum(-2, 4, -6, 8)", 4},
328                {"Sum(4, 16, \"abc\", 19)", 39}};
329 
330   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
331     EXPECT_TRUE(Execute(tests[i].program));
332 
333     CFXJSE_Value* value = GetValue();
334     EXPECT_TRUE(value->IsInteger());
335     EXPECT_EQ(tests[i].result, value->ToInteger())
336         << "Program: " << tests[i].program;
337   }
338 }
339 
340 // TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Date) {
341 //   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
342 //
343 //   TODO(dsinclair): Make compatible with windows.
344 //   time_t seconds = time(nullptr);
345 //   int days = seconds / (60 * 60 * 24);
346 
347 //   EXPECT_TRUE(Execute("Date()"));
348 
349 //   CFXJSE_Value* value = GetValue();
350 //   EXPECT_TRUE(value->IsNumber());
351 //   EXPECT_EQ(days, value->ToInteger());
352 // }
353 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Date2Num)354 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Date2Num) {
355   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
356 
357   struct {
358     const char* program;
359     int result;
360   } tests[] = {
361       // {"Date2Num(\"Mar 15, 1996\")", 35138},
362       {"Date2Num(\"1/1/1900\", \"D/M/YYYY\")", 1},
363       {"Date2Num(\"03/15/96\", \"MM/DD/YY\")", 35138},
364       // {"Date2Num(\"Aug 1, 1996\", \"MMM D, YYYY\")", 35277},
365       {"Date2Num(\"96-08-20\", \"YY-MM-DD\", \"fr_FR\")", 35296},
366       {"Date2Num(\"1/3/00\", \"D/M/YY\") - Date2Num(\"1/2/00\", \"D/M/YY\")",
367        29}};
368 
369   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
370     EXPECT_TRUE(Execute(tests[i].program));
371 
372     CFXJSE_Value* value = GetValue();
373     EXPECT_TRUE(value->IsInteger());
374     EXPECT_EQ(tests[i].result, value->ToInteger())
375         << "Program: " << tests[i].program;
376   }
377 }
378 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DateFmt)379 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DateFmt) {
380   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
381 
382   struct {
383     const char* program;
384     const char* result;
385   } tests[] = {
386       // {"DateFmt(1)", "M/D/YY"},
387       // {"DateFmt(2, \"fr_CA\")", "YY-MM-DD"},
388       {"DateFmt(3, \"de_DE\")", "D. MMMM YYYY"},
389       // {"DateFmt(4, \"fr_FR\")", "EEE D' MMMM YYYY"}
390   };
391 
392   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
393     EXPECT_TRUE(Execute(tests[i].program));
394 
395     CFXJSE_Value* value = GetValue();
396     EXPECT_TRUE(value->IsString());
397     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
398         << "Program: " << tests[i].program << " Result: '" << value->ToString()
399         << "'";
400   }
401 }
402 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,IsoDate2Num)403 TEST_F(CFXJSE_FormCalcContextEmbedderTest, IsoDate2Num) {
404   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
405 
406   struct {
407     const char* program;
408     int result;
409   } tests[] = {{"IsoDate2Num(\"1900\")", 1},
410                {"IsoDate2Num(\"1900-01\")", 1},
411                {"IsoDate2Num(\"1900-01-01\")", 1},
412                {"IsoDate2Num(\"19960315T20:20:20\")", 35138},
413                {"IsoDate2Num(\"2000-03-01\") - IsoDate2Num(\"20000201\")", 29}};
414 
415   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
416     EXPECT_TRUE(Execute(tests[i].program));
417 
418     CFXJSE_Value* value = GetValue();
419     EXPECT_TRUE(value->IsInteger());
420     EXPECT_EQ(tests[i].result, value->ToInteger())
421         << "Program: " << tests[i].program;
422   }
423 }
424 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DISABLED_IsoTime2Num)425 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_IsoTime2Num) {
426   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
427 
428   struct {
429     const char* program;
430     int result;
431   } tests[] = {{"IsoTime2Num(\"00:00:00Z\")", 1}};
432 
433   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
434     EXPECT_TRUE(Execute(tests[i].program));
435 
436     CFXJSE_Value* value = GetValue();
437     EXPECT_TRUE(value->IsInteger());
438     EXPECT_EQ(tests[i].result, value->ToInteger())
439         << "Program: " << tests[i].program;
440   }
441 }
442 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,LocalDateFmt)443 TEST_F(CFXJSE_FormCalcContextEmbedderTest, LocalDateFmt) {
444   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
445 
446   struct {
447     const char* program;
448     const char* result;
449   } tests[] = {// {"LocalDateFmt(1, \"de_DE\")", "tt.MM.uu"},
450                // {"LocalDateFmt(2, \"fr_CA\")", "aa-MM-jj"},
451                {"LocalDateFmt(3, \"de_CH\")", "t. MMMM jjjj"},
452                {"LocalDateFmt(4, \"fr_FR\")", "EEEE j MMMM aaaa"}};
453 
454   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
455     EXPECT_TRUE(Execute(tests[i].program));
456 
457     CFXJSE_Value* value = GetValue();
458     EXPECT_TRUE(value->IsString());
459     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
460         << "Program: " << tests[i].program << " Result: '" << value->ToString()
461         << "'";
462   }
463 }
464 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DISABLED_LocalTimeFmt)465 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_LocalTimeFmt) {
466   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
467 
468   struct {
469     const char* program;
470     const char* result;
471   } tests[] = {{"LocalTimeFmt(1, \"de_DE\")", "HH:mm"},
472                {"LocalTimeFmt(2, \"fr_CA\")", "HH:mm::ss"},
473                {"LocalTimeFmt(3, \"de_CH\")", "HH:mm:ss z"},
474                {"LocalTimeFmt(4, \"fr_FR\")", "HH' h 'mm z"}};
475 
476   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
477     EXPECT_TRUE(Execute(tests[i].program));
478 
479     CFXJSE_Value* value = GetValue();
480     EXPECT_TRUE(value->IsString());
481     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
482         << "Program: " << tests[i].program << " Result: '" << value->ToString()
483         << "'";
484   }
485 }
486 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Num2Date)487 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Num2Date) {
488   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
489 
490   struct {
491     const char* program;
492     const char* result;
493   } tests[] = {
494       {"Num2Date(1, \"DD/MM/YYYY\")", "01/01/1900"},
495       {"Num2Date(35139, \"DD-MMM-YYYY\", \"de_DE\")", "16-Mrz-1996"},
496       // {"Num2Date(Date2Num(\"Mar 15, 2000\") - Date2Num(\"98-03-15\", "
497       //  "\"YY-MM-DD\", \"fr_CA\"))",
498       //  "Jan 1, 1902"}
499   };
500 
501   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
502     EXPECT_TRUE(Execute(tests[i].program));
503 
504     CFXJSE_Value* value = GetValue();
505     EXPECT_TRUE(value->IsString()) << "Program: " << tests[i].program;
506     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
507         << "Program: " << tests[i].program << " Result: '" << value->ToString()
508         << "'";
509   }
510 }
511 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DISABLED_Num2GMTime)512 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Num2GMTime) {
513   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
514 
515   struct {
516     const char* program;
517     const char* result;
518   } tests[] = {// Broken on Windows only.
519                {"Num2GMTime(1, \"HH:MM:SS\")", "00:00:00"},
520                // Below broken on other platforms.
521                {"Num2GMTime(65593001, \"HH:MM:SS Z\")", "18:13:13 GMT"},
522                {"Num2GMTime(43993001, TimeFmt(4, \"de_DE\"), \"de_DE\")",
523                 "12.13 Uhr GMT"}};
524 
525   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
526     EXPECT_TRUE(Execute(tests[i].program));
527 
528     CFXJSE_Value* value = GetValue();
529     EXPECT_TRUE(value->IsString());
530     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
531         << "Program: " << tests[i].program << " Result: '" << value->ToString()
532         << "'";
533   }
534 }
535 
536 // TODO(dsinclair): Broken on Mac ...
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DISABLED_Num2Time)537 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Num2Time) {
538   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
539 
540   struct {
541     const char* program;
542     const char* result;
543   } tests[] = {{"Num2Time(1, \"HH:MM:SS\")", "00:00:00"}};
544 
545   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
546     EXPECT_TRUE(Execute(tests[i].program));
547 
548     CFXJSE_Value* value = GetValue();
549     EXPECT_TRUE(value->IsString());
550     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
551         << "Program: " << tests[i].program << " Result: '" << value->ToString()
552         << "'";
553   }
554 }
555 
556 // TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Time) {
557 //   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
558 //   TODO(dsinclair): Make compatible with windows.
559 //   struct timeval tp;
560 //   gettimeofday(&tp, nullptr);
561 
562 //   EXPECT_TRUE(Execute("Time()"));
563 
564 //   CFXJSE_Value* value = GetValue();
565 //   EXPECT_TRUE(value->IsInteger());
566 //   EXPECT_EQ(tp.tv_sec * 1000L + tp.tv_usec / 1000, value->ToInteger())
567 //       << "Program: Time()";
568 // }
569 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Time2Num)570 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Time2Num) {
571   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
572 
573   struct {
574     const char* program;
575     int result;
576   } tests[] = {
577       // {"Time2Num(\"00:00:00 GMT\", \"HH:MM:SS Z\")", 1},
578       {"Time2Num(\"13:13:13 GMT\", \"HH:MM:SS Z\", \"fr_FR\")", 47593001}};
579 
580   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
581     EXPECT_TRUE(Execute(tests[i].program));
582 
583     CFXJSE_Value* value = GetValue();
584     EXPECT_TRUE(value->IsInteger());
585     EXPECT_EQ(tests[i].result, value->ToInteger())
586         << "Program: " << tests[i].program;
587   }
588 }
589 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,TimeFmt)590 TEST_F(CFXJSE_FormCalcContextEmbedderTest, TimeFmt) {
591   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
592 
593   struct {
594     const char* program;
595     const char* result;
596   } tests[] = {
597       // {"TimeFmt(1)", "h::MM A"},
598       {"TimeFmt(2, \"fr_CA\")", "HH:MM:SS"},
599       {"TimeFmt(3, \"fr_FR\")", "HH:MM:SS Z"},
600       // {"TimeFmt(4, \"de_DE\")", "H.MM' Uhr 'Z"}
601   };
602 
603   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
604     EXPECT_TRUE(Execute(tests[i].program));
605 
606     CFXJSE_Value* value = GetValue();
607     EXPECT_TRUE(value->IsString());
608     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
609         << "Program: " << tests[i].program << " Result: '" << value->ToString()
610         << "'";
611   }
612 }
613 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DISABLED_Apr)614 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Apr) {
615   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
616 
617   struct {
618     const char* program;
619     float result;
620   } tests[] = {{"Apr(35000, 269.50, 360)", 0.08515404566f},
621                {"Apr(210000 * 0.75, 850 + 110, 25 * 26)", 0.07161332404f}};
622 
623   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
624     EXPECT_TRUE(Execute(tests[i].program));
625 
626     CFXJSE_Value* value = GetValue();
627     EXPECT_TRUE(value->IsNumber());
628     EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat())
629         << "Program: " << tests[i].program;
630   }
631 }
632 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,CTerm)633 TEST_F(CFXJSE_FormCalcContextEmbedderTest, CTerm) {
634   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
635 
636   struct {
637     const char* program;
638     float result;
639   } tests[] = {
640       // {"CTerm(0.02, 1000, 100)", 116.2767474515f},
641       {"CTerm(0.10, 500000, 12000)", 39.13224648502f},
642       // {"CTerm(0.0275 + 0.0025, 1000000, 55000 * 0.10)", 176.02226044975f}
643   };
644 
645   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
646     EXPECT_TRUE(Execute(tests[i].program));
647 
648     CFXJSE_Value* value = GetValue();
649     EXPECT_TRUE(value->IsNumber());
650     EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat())
651         << "Program: " << tests[i].program;
652   }
653 }
654 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,FV)655 TEST_F(CFXJSE_FormCalcContextEmbedderTest, FV) {
656   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
657 
658   struct {
659     const char* program;
660     float result;
661   } tests[] = {{"FV(400, 0.10 / 12, 30 * 12)", 904195.16991842445f},
662                {"FV(1000, 0.075 / 4, 10 * 4)", 58791.96145535981f}};
663 
664   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
665     EXPECT_TRUE(Execute(tests[i].program));
666 
667     CFXJSE_Value* value = GetValue();
668     EXPECT_TRUE(value->IsNumber());
669     EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat())
670         << "Program: " << tests[i].program;
671   }
672 }
673 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,IPmt)674 TEST_F(CFXJSE_FormCalcContextEmbedderTest, IPmt) {
675   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
676 
677   struct {
678     const char* program;
679     float result;
680   } tests[] = {{"IPmt(30000, 0.085, 295.50, 7, 3)", 624.8839283142f},
681                {"IPmt(160000, 0.0475, 980, 24, 12)", 7103.80833569485f},
682                {"IPmt(15000, 0.065, 65.50, 15, 1)", 0.0f}};
683 
684   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
685     EXPECT_TRUE(Execute(tests[i].program));
686 
687     CFXJSE_Value* value = GetValue();
688     EXPECT_TRUE(value->IsNumber());
689     EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat())
690         << "Program: " << tests[i].program;
691   }
692 }
693 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DISABLED_NPV)694 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_NPV) {
695   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
696 
697   struct {
698     const char* program;
699     float result;
700   } tests[] = {{"NPV(0.065, 5000)", 4694.83568075117f},
701                {"NPV(0.10, 500, 1500, 4000, 10000)", 11529.60863329007f},
702                {"NPV(0.0275 / 12, 50, 60, 40, 100, 25)", 273.14193838457f}};
703 
704   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
705     EXPECT_TRUE(Execute(tests[i].program));
706 
707     CFXJSE_Value* value = GetValue();
708     EXPECT_TRUE(value->IsNumber()) << "Program: " << tests[i].program;
709     EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat())
710         << "Program: " << tests[i].program;
711   }
712 }
713 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Pmt)714 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Pmt) {
715   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
716 
717   struct {
718     const char* program;
719     float result;
720   } tests[] = {// {"Pmt(150000, 0.0475 / 12, 25 * 12)", 855.17604207164f},
721                {"Pmt(25000, 0.085, 12)", 3403.82145169876f}};
722 
723   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
724     EXPECT_TRUE(Execute(tests[i].program));
725 
726     CFXJSE_Value* value = GetValue();
727     EXPECT_TRUE(value->IsNumber());
728     EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat())
729         << "Program: " << tests[i].program;
730   }
731 }
732 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,PPmt)733 TEST_F(CFXJSE_FormCalcContextEmbedderTest, PPmt) {
734   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
735 
736   struct {
737     const char* program;
738     float result;
739   } tests[] = {
740       {"PPmt(30000, 0.085, 295.50, 7, 3)", 261.6160716858f},
741       {"PPmt(160000, 0.0475, 980, 24, 12)", 4656.19166430515f},
742       // {"PPmt(15000, 0.065, 65.50, 15, 1)", 0.0f}
743   };
744 
745   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
746     EXPECT_TRUE(Execute(tests[i].program));
747 
748     CFXJSE_Value* value = GetValue();
749     EXPECT_TRUE(value->IsNumber());
750     EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat())
751         << "Program: " << tests[i].program;
752   }
753 }
754 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,PV)755 TEST_F(CFXJSE_FormCalcContextEmbedderTest, PV) {
756   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
757 
758   struct {
759     const char* program;
760     float result;
761   } tests[] = {
762       {"PV(400, 0.10 / 12, 30 * 12)", 45580.32799074439f},
763       // {"PV(1000, 0.075 / 4, 10 * 4)", 58791.96145535981f}
764   };
765 
766   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
767     EXPECT_TRUE(Execute(tests[i].program));
768 
769     CFXJSE_Value* value = GetValue();
770     EXPECT_TRUE(value->IsNumber());
771     EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat())
772         << "Program: " << tests[i].program;
773   }
774 }
775 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DISABLED_Rate)776 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Rate) {
777   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
778 
779   struct {
780     const char* program;
781     float result;
782   } tests[] = {{"Rate(12000, 8000, 5)", 0.0844717712f},
783                {"Rate(10000, 0.25 * 5000, 4 * 12)", 0.04427378243f}};
784 
785   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
786     EXPECT_TRUE(Execute(tests[i].program));
787 
788     CFXJSE_Value* value = GetValue();
789     EXPECT_TRUE(value->IsNumber());
790     EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat())
791         << "Program: " << tests[i].program;
792   }
793 }
794 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Term)795 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Term) {
796   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
797 
798   struct {
799     const char* program;
800     float result;
801   } tests[] = {// {"Term(475, .05, 1500)", 3.00477517728f},
802                {"Term(2500, 0.0275 + 0.0025, 5000)", 1.97128786369f}};
803 
804   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
805     EXPECT_TRUE(Execute(tests[i].program));
806 
807     CFXJSE_Value* value = GetValue();
808     EXPECT_TRUE(value->IsNumber());
809     EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat())
810         << "Program: " << tests[i].program;
811   }
812 }
813 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Choose)814 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Choose) {
815   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
816 
817   struct {
818     const char* program;
819     const char* result;
820   } tests[] = {
821       {"Choose(3, \"Taxes\", \"Price\", \"Person\", \"Teller\")", "Person"},
822       {"Choose(2, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)", "9"},
823       {"Choose(20/3, \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\")",
824        "F"}};
825 
826   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
827     EXPECT_TRUE(Execute(tests[i].program));
828 
829     CFXJSE_Value* value = GetValue();
830     EXPECT_TRUE(value->IsString());
831     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
832         << "Program: " << tests[i].program << " Result: '" << value->ToString()
833         << "'";
834   }
835 }
836 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Exists)837 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Exists) {
838   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
839 
840   EXPECT_TRUE(Execute("Exists(\"hello world\")"));
841   CFXJSE_Value* value = GetValue();
842   EXPECT_TRUE(value->IsInteger());
843   EXPECT_FALSE(value->ToBoolean());
844 }
845 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,HasValue)846 TEST_F(CFXJSE_FormCalcContextEmbedderTest, HasValue) {
847   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
848 
849   struct {
850     const char* program;
851     bool result;
852   } tests[] = {{"HasValue(2)", true}, {"HasValue(\" \")", false}};
853 
854   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
855     EXPECT_TRUE(Execute(tests[i].program));
856 
857     CFXJSE_Value* value = GetValue();
858     EXPECT_TRUE(value->IsInteger()) << "Program: " << tests[i].program;
859     EXPECT_EQ(tests[i].result, value->ToBoolean())
860         << "Program: " << tests[i].program;
861   }
862 }
863 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Oneof)864 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Oneof) {
865   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
866 
867   struct {
868     const char* program;
869     bool result;
870   } tests[] = {
871       {"Oneof(3, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)", true},
872       {"Oneof(\"John\", \"Bill\", \"Gary\", \"Joan\", \"John\", \"Lisa\")",
873        true},
874       {"Oneof(3, 1, 25)", false},
875       {"Oneof(3, 3, null)", true},
876       {"Oneof(3, null, null)", false},
877   };
878 
879   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
880     EXPECT_TRUE(Execute(tests[i].program));
881 
882     CFXJSE_Value* value = GetValue();
883     EXPECT_TRUE(value->IsInteger()) << "Program: " << tests[i].program;
884     EXPECT_EQ(tests[i].result, value->ToBoolean())
885         << "Program: " << tests[i].program;
886   }
887 }
888 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Within)889 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Within) {
890   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
891 
892   struct {
893     const char* program;
894     bool result;
895   } tests[] = {{"Within(\"C\", \"A\", \"D\")", true},
896                {"Within(1.5, 0, 2)", true},
897                {"Within(-1, 0, 2)", false}};
898 
899   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
900     EXPECT_TRUE(Execute(tests[i].program));
901 
902     CFXJSE_Value* value = GetValue();
903     EXPECT_TRUE(value->IsInteger()) << "Program: " << tests[i].program;
904     EXPECT_EQ(tests[i].result, value->ToBoolean())
905         << "Program: " << tests[i].program;
906   }
907 }
908 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DISABLED_Eval)909 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Eval) {
910   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
911 
912   struct {
913     const char* program;
914     int result;
915   } tests[] = {{"eval(\"10*3+5*4\")", 50}};
916 
917   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
918     EXPECT_TRUE(Execute(tests[i].program));
919 
920     CFXJSE_Value* value = GetValue();
921     EXPECT_TRUE(value->IsInteger());
922     EXPECT_EQ(tests[i].result, value->ToInteger())
923         << "Program: " << tests[i].program;
924   }
925 }
926 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DISABLED_Null)927 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Null) {
928   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
929 
930   struct {
931     const char* program;
932     const char* result;
933   } tests[] = {{"Null()", "null"},
934                {"Concat(\"ABC\", Null(), \"DEF\")", "ABCDEF"}};
935 
936   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
937     EXPECT_TRUE(Execute(tests[i].program));
938 
939     CFXJSE_Value* value = GetValue();
940     EXPECT_TRUE(value->IsString());
941     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
942         << "Program: " << tests[i].program << " Result: '" << value->ToString()
943         << "'";
944   }
945 
946   EXPECT_TRUE(Execute("Null() + 5"));
947 
948   CFXJSE_Value* value = GetValue();
949   EXPECT_TRUE(value->IsInteger());
950   EXPECT_EQ(5, value->ToInteger());
951 }
952 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Ref)953 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Ref) {
954   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
955 
956   struct {
957     const char* program;
958     const char* result;
959   } tests[] = {{"Ref(\"10*3+5*4\")", "10*3+5*4"}, {"Ref(\"hello\")", "hello"}};
960 
961   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
962     EXPECT_TRUE(Execute(tests[i].program));
963 
964     CFXJSE_Value* value = GetValue();
965     EXPECT_TRUE(value->IsString());
966     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
967         << "Program: " << tests[i].program << " Result: '" << value->ToString()
968         << "'";
969   }
970 }
971 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,UnitType)972 TEST_F(CFXJSE_FormCalcContextEmbedderTest, UnitType) {
973   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
974 
975   struct {
976     const char* program;
977     const char* result;
978   } tests[] = {{"UnitType(\"36 in\")", "in"},
979                {"UnitType(\"2.54centimeters\")", "cm"},
980                {"UnitType(\"picas\")", "pt"},
981                {"UnitType(\"2.cm\")", "cm"},
982                {"UnitType(\"2.zero cm\")", "in"},
983                {"UnitType(\"kilometers\")", "in"}};
984 
985   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
986     EXPECT_TRUE(Execute(tests[i].program));
987 
988     CFXJSE_Value* value = GetValue();
989     EXPECT_TRUE(value->IsString());
990     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
991         << "Program: " << tests[i].program << " Result: '" << value->ToString()
992         << "'";
993   }
994 }
995 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,UnitValue)996 TEST_F(CFXJSE_FormCalcContextEmbedderTest, UnitValue) {
997   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
998 
999   struct {
1000     const char* program;
1001     float result;
1002   } tests[] = {
1003       {"UnitValue(\"2in\")", 2.0f}, {"UnitValue(\"2in\", \"cm\")", 5.08f},
1004       // {"UnitValue(\"6\", \"pt\")", 432f},
1005       // {"UnitType(\"A\", \"cm\")", 0.0f},
1006       // {"UnitType(\"5.08cm\", \"kilograms\")", 2.0f}
1007   };
1008 
1009   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1010     EXPECT_TRUE(Execute(tests[i].program));
1011 
1012     CFXJSE_Value* value = GetValue();
1013     EXPECT_TRUE(value->IsNumber());
1014     EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat())
1015         << "Program: " << tests[i].program;
1016   }
1017 }
1018 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,At)1019 TEST_F(CFXJSE_FormCalcContextEmbedderTest, At) {
1020   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1021 
1022   struct {
1023     const char* program;
1024     int result;
1025   } tests[] = {{"At(\"ABCDEFGH\", \"AB\")", 1},
1026                {"At(\"ABCDEFGH\", \"F\")", 6},
1027                {"At(23412931298471, 29)", 5}};
1028 
1029   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1030     EXPECT_TRUE(Execute(tests[i].program));
1031 
1032     CFXJSE_Value* value = GetValue();
1033     EXPECT_TRUE(value->IsInteger());
1034     EXPECT_EQ(tests[i].result, value->ToInteger())
1035         << "Program: " << tests[i].program;
1036   }
1037 }
1038 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Concat)1039 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Concat) {
1040   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1041 
1042   struct {
1043     const char* program;
1044     const char* result;
1045   } tests[] = {{"Concat(\"ABC\", \"DEF\")", "ABCDEF"},
1046                {"Concat(\"Tony\", Space(1), \"Blue\")", "Tony Blue"},
1047                {"Concat(\"You owe \", WordNum(1154.67, 2), \".\")",
1048                 "You owe One Thousand One Hundred Fifty-four Dollars And "
1049                 "Sixty-seven Cents."}};
1050 
1051   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1052     EXPECT_TRUE(Execute(tests[i].program));
1053 
1054     CFXJSE_Value* value = GetValue();
1055     EXPECT_TRUE(value->IsString());
1056     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1057         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1058         << "'";
1059   }
1060 }
1061 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Decode)1062 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Decode) {
1063   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1064 
1065   struct {
1066     const char* program;
1067     const char* result;
1068   } tests[] = {
1069       // HTML
1070       {R"(Decode("", "html"))", ""},
1071       {R"(Decode("abc&Acirc;xyz", "html"))", "abc\xC3\x82xyz"},
1072       {R"(Decode("abc&NoneSuchButVeryLongIndeed;", "html"))", "abc"},
1073       {R"(Decode("&#x0041;&AElig;&Aacute;", "html"))", "A\xC3\x86\xC3\x81"},
1074       {R"(Decode("xyz&#", "html"))", "xyz"},
1075       {R"(Decode("|&zzzzzz;|", "html"))", "||"},
1076 
1077       // XML
1078       {R"(Decode("", "xml"))", ""},
1079       {R"(Decode("~!@#$%%^&amp;*()_+|`", "xml"))", "~!@#$%%^&*()_+|`"},
1080       {R"(Decode("abc&nonesuchbutverylongindeed;", "xml"))", "abc"},
1081       {R"(Decode("&quot;&#x45;&lt;&gt;[].&apos;", "xml"))", "\"E<>[].'"},
1082       {R"(Decode("xyz&#", "xml"))", "xyz"},
1083       {R"(Decode("|&zzzzzz;|", "xml"))", "||"},
1084 
1085       // URL
1086       {R"(Decode("", "url"))", ""},
1087       {R"(Decode("~%26^&*()_+|`{", "url"))", "~&^&*()_+|`{"},
1088       {R"(Decode("~%26^&*()_+|`{", "mbogo"))", "~&^&*()_+|`{"},
1089       {R"(Decode("~%26^&*()_+|`{"))", "~&^&*()_+|`{"},
1090       {R"(Decode("~%~~"))", ""},
1091       {R"(Decode("?%~"))", ""},
1092       {R"(Decode("?%"))", "?"},
1093   };
1094 
1095   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1096     EXPECT_TRUE(Execute(tests[i].program));
1097     CFXJSE_Value* value = GetValue();
1098     EXPECT_TRUE(value->IsString());
1099     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1100         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1101         << "'";
1102   }
1103 }
1104 
1105 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Encode) {
1106   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1107 
1108   struct {
1109     const char* program;
1110     const char* result;
1111   } tests[] = {
1112     {"Encode(\"X/~&^*<=>?|\")", "X%2f%7e%26%5e*%3c%3d%3e%3f%7c"},
1113     {"Encode(\"X/~&^*<=>?|\", \"mbogo\")", "X%2f%7e%26%5e*%3c%3d%3e%3f%7c"},
1114     {"Encode(\"X/~&^*<=>?|\", \"url\")", "X%2f%7e%26%5e*%3c%3d%3e%3f%7c"},
1115     {"Encode(\"X/~&^*<=>?|\", \"xml\")", "X/~&amp;^*&lt;=&gt;?|"},
1116     {"Encode(\"X/~&^*<=>?|\", \"html\")", "X/~&amp;^*&lt;=&gt;?|"},
1117 
1118     {"Encode(\"\\u0022\\u00f5\\ufed0\", \"url\")", "%22%f5%fe%d0"},
1119     {"Encode(\"\\u0022\\u00f4\\ufed0\", \"xml\")", "&quot;&#xf4;&#xfed0;"},
1120     {"Encode(\"\\u0022\\u00f5\\ufed0\", \"html\")", "&quot;&otilde;&#xfed0;"},
1121 
1122 #if !defined(OS_WIN)
1123     // Windows wchar_t isn't wide enough to handle these anyways.
1124     // TODO(tsepez): fix surrogate encodings.
1125     {"Encode(\"\\uD83D\\uDCA9\", \"url\")", "%01%f4%a9"},
1126     {"Encode(\"\\uD83D\\uDCA9\", \"xml\")", ""},
1127     {"Encode(\"\\uD83D\\uDCA9\", \"html\")", ""},
1128 #endif  // !defined(OS_WIN)
1129   };
1130 
1131   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1132     EXPECT_TRUE(Execute(tests[i].program));
1133 
1134     CFXJSE_Value* value = GetValue();
1135     EXPECT_TRUE(value->IsString());
1136     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1137         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1138         << "'";
1139   }
1140 }
1141 
1142 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Format) {
1143   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1144 
1145   struct {
1146     const char* program;
1147     const char* result;
1148   } tests[] = {{"Format(\"MMM D, YYYY\", \"20020901\")", "Sep 1, 2002"},
1149                {"Format(\"$9,999,999.99\", 1234567.89)", "$1,234,567.89"}};
1150 
1151   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1152     EXPECT_TRUE(Execute(tests[i].program));
1153 
1154     CFXJSE_Value* value = GetValue();
1155     EXPECT_TRUE(value->IsString());
1156     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1157         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1158         << "'";
1159   }
1160 }
1161 
1162 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Left) {
1163   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1164 
1165   struct {
1166     const char* program;
1167     const char* result;
1168   } tests[] = {{"Left(\"ABCDEFGH\", 3)", "ABC"},
1169                {"Left(\"Tony Blue\", 5)", "Tony "}};
1170 
1171   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1172     EXPECT_TRUE(Execute(tests[i].program));
1173 
1174     CFXJSE_Value* value = GetValue();
1175     EXPECT_TRUE(value->IsString());
1176     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1177         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1178         << "'";
1179   }
1180 }
1181 
1182 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Len) {
1183   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1184 
1185   struct {
1186     const char* program;
1187     int result;
1188   } tests[] = {
1189       {"Len(\"ABCDEFGH\")", 8}, {"Len(4)", 1}, {"Len(Str(4.532, 6, 4))", 6}};
1190 
1191   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1192     EXPECT_TRUE(Execute(tests[i].program));
1193 
1194     CFXJSE_Value* value = GetValue();
1195     EXPECT_TRUE(value->IsInteger());
1196     EXPECT_EQ(tests[i].result, value->ToInteger())
1197         << "Program: " << tests[i].program;
1198   }
1199 }
1200 
1201 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Lower) {
1202   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1203 
1204   struct {
1205     const char* program;
1206     const char* result;
1207   } tests[] = {{"Lower(\"ABC\")", "abc"},
1208                {"Lower(\"21 Main St.\")", "21 main st."},
1209                {"Lower(15)", "15"}};
1210 
1211   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1212     EXPECT_TRUE(Execute(tests[i].program));
1213 
1214     CFXJSE_Value* value = GetValue();
1215     EXPECT_TRUE(value->IsString());
1216     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1217         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1218         << "'";
1219   }
1220 }
1221 
1222 // This is testing for an OOB read, so will likely only fail under ASAN.
1223 TEST_F(CFXJSE_FormCalcContextEmbedderTest, bug_854623) {
1224   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1225 
1226   const uint8_t test_string[] = {
1227       0x4c, 0x6f, 0x77, 0x65, 0x72, 0x28, 0x22, 0xc3,
1228       0x85, 0xc3, 0x85, 0xc3, 0x85, 0x22, 0x29};  // Lower("ÅÅÅ")
1229   Execute(ByteString(test_string, sizeof(test_string)).AsStringView());
1230 }
1231 
1232 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Ltrim) {
1233   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1234 
1235   struct {
1236     const char* program;
1237     const char* result;
1238   } tests[] = {{"Ltrim(\"   ABCD\")", "ABCD"},
1239                {"Ltrim(Rtrim(\"    Tony Blue    \"))", "Tony Blue"}};
1240 
1241   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1242     EXPECT_TRUE(Execute(tests[i].program));
1243 
1244     CFXJSE_Value* value = GetValue();
1245     EXPECT_TRUE(value->IsString());
1246     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1247         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1248         << "'";
1249   }
1250 }
1251 
1252 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Parse) {
1253   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1254 
1255   struct {
1256     const char* program;
1257     const char* result;
1258   } tests[] = {{"Parse(\"MMM D, YYYY\", \"Sep 1, 2002\")", "2002-09-01"}};
1259 
1260   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1261     EXPECT_TRUE(Execute(tests[i].program));
1262 
1263     CFXJSE_Value* value = GetValue();
1264     EXPECT_TRUE(value->IsString());
1265     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1266         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1267         << "'";
1268   }
1269 
1270   EXPECT_TRUE(Execute("Parse(\"$9,999,999.99\", \"$1,234,567.89\")"));
1271   CFXJSE_Value* value = GetValue();
1272   EXPECT_TRUE(value->IsNumber());
1273   EXPECT_FLOAT_EQ(1234567.89f, value->ToFloat());
1274 }
1275 
1276 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Replace) {
1277   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1278 
1279   struct {
1280     const char* program;
1281     const char* result;
1282   } tests[] = {{"Replace(\"Tony Blue\", \"Tony\", \"Chris\")", "Chris Blue"},
1283                {"Replace(\"ABCDEFGH\", \"D\")", "ABCEFGH"},
1284                {"Replace(\"ABCDEFGH\", \"d\")", "ABCDEFGH"}};
1285 
1286   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1287     EXPECT_TRUE(Execute(tests[i].program));
1288 
1289     CFXJSE_Value* value = GetValue();
1290     EXPECT_TRUE(value->IsString());
1291     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1292         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1293         << "'";
1294   }
1295 }
1296 
1297 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Right) {
1298   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1299 
1300   struct {
1301     const char* program;
1302     const char* result;
1303   } tests[] = {{"Right(\"ABCDEFGH\", 3)", "FGH"},
1304                {"Right(\"Tony Blue\", 5)", " Blue"}};
1305 
1306   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1307     EXPECT_TRUE(Execute(tests[i].program));
1308 
1309     CFXJSE_Value* value = GetValue();
1310     EXPECT_TRUE(value->IsString());
1311     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1312         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1313         << "'";
1314   }
1315 }
1316 
1317 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Rtrim) {
1318   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1319 
1320   struct {
1321     const char* program;
1322     const char* result;
1323   } tests[] = {{"Rtrim(\"ABCD   \")", "ABCD"},
1324                {"Rtrim(\"Tony Blue      \t\")", "Tony Blue"}};
1325 
1326   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1327     EXPECT_TRUE(Execute(tests[i].program));
1328 
1329     CFXJSE_Value* value = GetValue();
1330     EXPECT_TRUE(value->IsString());
1331     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1332         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1333         << "'";
1334   }
1335 }
1336 
1337 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Space) {
1338   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1339 
1340   struct {
1341     const char* program;
1342     const char* result;
1343   } tests[] = {{"Space(5)", "     "},
1344                {"Concat(\"Tony\", Space(1), \"Blue\")", "Tony Blue"}};
1345 
1346   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1347     EXPECT_TRUE(Execute(tests[i].program));
1348 
1349     CFXJSE_Value* value = GetValue();
1350     EXPECT_TRUE(value->IsString());
1351     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1352         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1353         << "'";
1354   }
1355 }
1356 
1357 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Str) {
1358   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1359 
1360   struct {
1361     const char* program;
1362     const char* result;
1363   } tests[] = {{"Str(2.456)", "         2"},
1364                {"Str(4.532, 6, 4)", "4.5320"},
1365                {"Str(234.458, 4)", " 234"},
1366                {"Str(31.2345, 4, 2)", "****"}};
1367 
1368   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1369     EXPECT_TRUE(Execute(tests[i].program));
1370 
1371     CFXJSE_Value* value = GetValue();
1372     EXPECT_TRUE(value->IsString());
1373     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1374         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1375         << "'";
1376   }
1377 }
1378 
1379 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Stuff) {
1380   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1381 
1382   struct {
1383     const char* program;
1384     const char* result;
1385   } tests[] = {{"Stuff(\"TonyBlue\", 5, 0, \" \")", "Tony Blue"},
1386                {"Stuff(\"ABCDEFGH\", 4, 2)", "ABCFGH"},
1387                {"Stuff(\"members-list@myweb.com\", 0, 0, \"cc:\")",
1388                 "cc:members-list@myweb.com"}};
1389 
1390   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1391     EXPECT_TRUE(Execute(tests[i].program));
1392 
1393     CFXJSE_Value* value = GetValue();
1394     EXPECT_TRUE(value->IsString());
1395     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1396         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1397         << "'";
1398   }
1399 }
1400 
1401 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Substr) {
1402   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1403 
1404   // Test wrong number of parameters.
1405   EXPECT_FALSE(Execute("Substr()"));
1406   EXPECT_FALSE(Execute("Substr(1)"));
1407   EXPECT_FALSE(Execute("Substr(1, 2)"));
1408   EXPECT_FALSE(Execute("Substr(1, 2, 3, 4)"));
1409 
1410   // Test null input.
1411   EXPECT_TRUE(ExecuteExpectNull("Substr(null, 0, 4)"));
1412   EXPECT_TRUE(ExecuteExpectNull("Substr(\"ABCDEFG\", null, 4)"));
1413   EXPECT_TRUE(ExecuteExpectNull("Substr(\"ABCDEFG\", 0, null)"));
1414   EXPECT_TRUE(ExecuteExpectNull("Substr(null, null, 4)"));
1415   EXPECT_TRUE(ExecuteExpectNull("Substr(null, 0, null)"));
1416   EXPECT_TRUE(ExecuteExpectNull("Substr(\"ABCDEFG\", null, null)"));
1417   EXPECT_TRUE(ExecuteExpectNull("Substr(null, null, null)"));
1418 
1419   struct {
1420     const char* program;
1421     const char* result;
1422   } static const kTests[] = {{"Substr(\"ABCDEFG\", -1, 4)", "ABCD"},
1423                              {"Substr(\"ABCDEFG\", 0, 4)", "ABCD"},
1424                              {"Substr(\"ABCDEFG\", 3, 4)", "CDEF"},
1425                              {"Substr(\"ABCDEFG\", 4, 4)", "DEFG"},
1426                              {"Substr(\"ABCDEFG\", 5, 4)", "EFG"},
1427                              {"Substr(\"ABCDEFG\", 6, 4)", "FG"},
1428                              {"Substr(\"ABCDEFG\", 7, 4)", "G"},
1429                              {"Substr(\"ABCDEFG\", 8, 4)", ""},
1430                              {"Substr(\"ABCDEFG\", 5, -1)", ""},
1431                              {"Substr(\"ABCDEFG\", 5, 0)", ""},
1432                              {"Substr(\"ABCDEFG\", 5, 1)", "E"},
1433                              {"Substr(\"abcdefghi\", 5, 3)", "efg"},
1434                              {"Substr(3214, 2, 1)", "2"},
1435                              {"Substr(\"21 Waterloo St.\", 4, 5)", "Water"}};
1436 
1437   for (const auto& test : kTests) {
1438     EXPECT_TRUE(Execute(test.program));
1439 
1440     CFXJSE_Value* value = GetValue();
1441     EXPECT_TRUE(value->IsString());
1442     EXPECT_STREQ(test.result, value->ToString().c_str())
1443         << "Program: " << test.program << " Result: '" << value->ToString()
1444         << "'";
1445   }
1446 }
1447 
1448 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Uuid) {
1449   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1450 
1451   EXPECT_TRUE(Execute("Uuid()"));
1452 
1453   CFXJSE_Value* value = GetValue();
1454   EXPECT_TRUE(value->IsString());
1455 }
1456 
1457 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Upper) {
1458   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1459 
1460   struct {
1461     const char* program;
1462     const char* result;
1463   } tests[] = {{"Upper(\"abc\")", "ABC"},
1464                {"Upper(\"21 Main St.\")", "21 MAIN ST."},
1465                {"Upper(15)", "15"}};
1466 
1467   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1468     EXPECT_TRUE(Execute(tests[i].program));
1469 
1470     CFXJSE_Value* value = GetValue();
1471     EXPECT_TRUE(value->IsString());
1472     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1473         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1474         << "'";
1475   }
1476 }
1477 
1478 TEST_F(CFXJSE_FormCalcContextEmbedderTest, WordNum) {
1479   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1480 
1481   struct {
1482     const char* program;
1483     const char* result;
1484   } tests[] = {
1485       // {"WordNum(123.45)",
1486       //  "One Hundred and Twenty-three"},  // This looks like it's wrong in the
1487       //                                    // Formcalc document.
1488       // {"WordNum(123.45, 1)", "One Hundred and Twenty-three Dollars"},
1489       {"WordNum(1154.67, 2)",
1490        "One Thousand One Hundred Fifty-four Dollars And Sixty-seven Cents"},
1491       {"WordNum(43, 2)", "Forty-three Dollars And Zero Cents"}};
1492 
1493   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1494     EXPECT_TRUE(Execute(tests[i].program));
1495 
1496     CFXJSE_Value* value = GetValue();
1497     EXPECT_TRUE(value->IsString());
1498     EXPECT_STREQ(tests[i].result, value->ToString().c_str())
1499         << "Program: " << tests[i].program << " Result: '" << value->ToString()
1500         << "'";
1501   }
1502 }
1503 
1504 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Get) {
1505   // TODO(dsinclair): Is this supported?
1506 }
1507 
1508 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Post) {
1509   // TODO(dsinclair): Is this supported?
1510 }
1511 
1512 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Put) {
1513   // TODO(dsinclair): Is this supported?
1514 }
1515 
1516 TEST_F(CFXJSE_FormCalcContextEmbedderTest, InvalidFunctions) {
1517   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1518 
1519   const char* const tests[] = {
1520       "F()",
1521       "()",
1522       "()()()",
1523       "Round(2.0)()",
1524   };
1525 
1526   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
1527     EXPECT_FALSE(ExecuteSilenceFailure(tests[i]));
1528   }
1529 }
1530 
1531 TEST_F(CFXJSE_FormCalcContextEmbedderTest, MethodCall) {
1532   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1533 
1534   const char test[] = {"$form.form1.TextField11.getAttribute(\"h\")"};
1535   EXPECT_TRUE(Execute(test));
1536 
1537   CFXJSE_Value* value = GetValue();
1538   EXPECT_TRUE(value->IsString());
1539   EXPECT_STREQ("12.7mm", value->ToString().c_str());
1540 }
1541 
1542 TEST_F(CFXJSE_FormCalcContextEmbedderTest, GetXFAEventChange) {
1543   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1544 
1545   CXFA_EventParam params;
1546   params.m_wsChange = L"changed";
1547 
1548   CFXJSE_Engine* context = GetScriptContext();
1549   context->SetEventParam(&params);
1550 
1551   const char test[] = {"xfa.event.change"};
1552   EXPECT_TRUE(Execute(test));
1553 
1554   CFXJSE_Value* value = GetValue();
1555   EXPECT_TRUE(value->IsString());
1556   EXPECT_STREQ("changed", value->ToString().c_str());
1557   context->SetEventParam(nullptr);
1558 }
1559 
1560 TEST_F(CFXJSE_FormCalcContextEmbedderTest, SetXFAEventChange) {
1561   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1562 
1563   CXFA_EventParam params;
1564   CFXJSE_Engine* context = GetScriptContext();
1565   context->SetEventParam(&params);
1566 
1567   const char test[] = {"xfa.event.change = \"changed\""};
1568   EXPECT_TRUE(Execute(test));
1569   EXPECT_EQ(L"changed", params.m_wsChange);
1570   context->SetEventParam(nullptr);
1571 }
1572 
1573 TEST_F(CFXJSE_FormCalcContextEmbedderTest, SetXFAEventFullTextFails) {
1574   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1575 
1576   CXFA_EventParam params;
1577   params.m_wsFullText = L"Original Full Text";
1578 
1579   CFXJSE_Engine* context = GetScriptContext();
1580   context->SetEventParam(&params);
1581 
1582   const char test[] = {"xfa.event.fullText = \"Changed Full Text\""};
1583   EXPECT_TRUE(Execute(test));
1584   EXPECT_EQ(L"Original Full Text", params.m_wsFullText);
1585   context->SetEventParam(nullptr);
1586 }
1587 
1588 TEST_F(CFXJSE_FormCalcContextEmbedderTest, EventChangeSelection) {
1589   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1590 
1591   CXFA_EventParam params;
1592   params.m_wsPrevText = L"1234";
1593   params.m_iSelStart = 1;
1594   params.m_iSelEnd = 3;
1595 
1596   CFXJSE_Engine* context = GetScriptContext();
1597   context->SetEventParam(&params);
1598 
1599   // Moving end to start works fine.
1600   EXPECT_TRUE(Execute("xfa.event.selEnd = \"1\""));
1601   EXPECT_EQ(1, params.m_iSelStart);
1602   EXPECT_EQ(1, params.m_iSelEnd);
1603 
1604   // Moving end before end, forces start to move in response.
1605   EXPECT_TRUE(Execute("xfa.event.selEnd = \"0\""));
1606   EXPECT_EQ(0, params.m_iSelStart);
1607   EXPECT_EQ(0, params.m_iSelEnd);
1608 
1609   // Negatives not allowed
1610   EXPECT_TRUE(Execute("xfa.event.selEnd = \"-1\""));
1611   EXPECT_EQ(0, params.m_iSelStart);
1612   EXPECT_EQ(0, params.m_iSelEnd);
1613 
1614   // Negatives not allowed
1615   EXPECT_TRUE(Execute("xfa.event.selStart = \"-1\""));
1616   EXPECT_EQ(0, params.m_iSelStart);
1617   EXPECT_EQ(0, params.m_iSelEnd);
1618 
1619   params.m_iSelEnd = 1;
1620 
1621   // Moving start to end works fine.
1622   EXPECT_TRUE(Execute("xfa.event.selStart = \"1\""));
1623   EXPECT_EQ(1, params.m_iSelStart);
1624   EXPECT_EQ(1, params.m_iSelEnd);
1625 
1626   // Moving start after end moves end.
1627   EXPECT_TRUE(Execute("xfa.event.selStart = \"2\""));
1628   EXPECT_EQ(2, params.m_iSelStart);
1629   EXPECT_EQ(2, params.m_iSelEnd);
1630 
1631   // Setting End past end of string clamps to string length;
1632   EXPECT_TRUE(Execute("xfa.event.selEnd = \"20\""));
1633   EXPECT_EQ(2, params.m_iSelStart);
1634   EXPECT_EQ(4, params.m_iSelEnd);
1635 
1636   // Setting Start past end of string clamps to string length;
1637   EXPECT_TRUE(Execute("xfa.event.selStart = \"20\""));
1638   EXPECT_EQ(4, params.m_iSelStart);
1639   EXPECT_EQ(4, params.m_iSelEnd);
1640 
1641   context->SetEventParam(nullptr);
1642 }
1643 
1644 TEST_F(CFXJSE_FormCalcContextEmbedderTest, XFAEventCancelAction) {
1645   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1646 
1647   CXFA_EventParam params;
1648   params.m_bCancelAction = false;
1649 
1650   CFXJSE_Engine* context = GetScriptContext();
1651   context->SetEventParam(&params);
1652 
1653   EXPECT_TRUE(Execute("xfa.event.cancelAction"));
1654 
1655   CFXJSE_Value* value = GetValue();
1656   EXPECT_TRUE(value->IsBoolean());
1657   EXPECT_FALSE(value->ToBoolean());
1658 
1659   EXPECT_TRUE(Execute("xfa.event.cancelAction = \"true\""));
1660   EXPECT_TRUE(params.m_bCancelAction);
1661 
1662   context->SetEventParam(nullptr);
1663 }
1664 
1665 TEST_F(CFXJSE_FormCalcContextEmbedderTest, ComplexTextChangeEvent) {
1666   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1667 
1668   CXFA_EventParam params;
1669   params.m_wsChange = L"g";
1670   params.m_wsPrevText = L"abcd";
1671   params.m_iSelStart = 1;
1672   params.m_iSelEnd = 3;
1673 
1674   CFXJSE_Engine* context = GetScriptContext();
1675   context->SetEventParam(&params);
1676 
1677   EXPECT_EQ(L"abcd", params.m_wsPrevText);
1678   EXPECT_EQ(L"agd", params.GetNewText());
1679   EXPECT_EQ(L"g", params.m_wsChange);
1680   EXPECT_EQ(1, params.m_iSelStart);
1681   EXPECT_EQ(3, params.m_iSelEnd);
1682 
1683   const char change_event[] = {"xfa.event.change = \"xyz\""};
1684   EXPECT_TRUE(Execute(change_event));
1685 
1686   EXPECT_EQ(L"abcd", params.m_wsPrevText);
1687   EXPECT_EQ(L"xyz", params.m_wsChange);
1688   EXPECT_EQ(L"axyzd", params.GetNewText());
1689   EXPECT_EQ(1, params.m_iSelStart);
1690   EXPECT_EQ(3, params.m_iSelEnd);
1691 
1692   const char sel_event[] = {"xfa.event.selEnd = \"1\""};
1693   EXPECT_TRUE(Execute(sel_event));
1694 
1695   EXPECT_EQ(L"abcd", params.m_wsPrevText);
1696   EXPECT_EQ(L"xyz", params.m_wsChange);
1697   EXPECT_EQ(L"axyzbcd", params.GetNewText());
1698   EXPECT_EQ(1, params.m_iSelStart);
1699   EXPECT_EQ(1, params.m_iSelEnd);
1700 
1701   context->SetEventParam(nullptr);
1702 }
1703 
1704 // Should not crash.
1705 TEST_F(CFXJSE_FormCalcContextEmbedderTest, BUG_1223) {
1706   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1707 
1708   EXPECT_FALSE(Execute("!.somExpression=0"));
1709 }
1710