xref: /aosp_15_r20/external/pdfium/fxjs/xfa/cfxjse_formcalc_context_embeddertest.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2017 The PDFium Authors
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 <math.h>
6 
7 #include "fxjs/fxv8.h"
8 #include "fxjs/xfa/cfxjse_engine.h"
9 #include "fxjs/xfa/cfxjse_isolatetracker.h"
10 #include "fxjs/xfa/cfxjse_value.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "testing/scoped_set_tz.h"
13 #include "testing/xfa_js_embedder_test.h"
14 #include "xfa/fxfa/cxfa_eventparam.h"
15 
16 class CFXJSE_FormCalcContextEmbedderTest : public XFAJSEmbedderTest {
17  public:
18   CFXJSE_FormCalcContextEmbedderTest() = default;
19   ~CFXJSE_FormCalcContextEmbedderTest() override = default;
20 
21  protected:
GetJseContext()22   CFXJSE_Context* GetJseContext() {
23     return GetScriptContext()->GetJseContextForTest();
24   }
25 
ExecuteExpectError(ByteStringView input)26   void ExecuteExpectError(ByteStringView input) {
27     EXPECT_FALSE(Execute(input)) << "Program: " << input;
28   }
29 
ExecuteExpectNull(ByteStringView input)30   void ExecuteExpectNull(ByteStringView input) {
31     EXPECT_TRUE(Execute(input)) << "Program: " << input;
32 
33     CFXJSE_ScopeUtil_IsolateHandleContext scope(GetJseContext());
34     EXPECT_TRUE(fxv8::IsNull(GetValue())) << "Program: " << input;
35   }
36 
ExecuteExpectBool(ByteStringView input,bool expected)37   void ExecuteExpectBool(ByteStringView input, bool expected) {
38     EXPECT_TRUE(Execute(input)) << "Program: " << input;
39 
40     CFXJSE_ScopeUtil_IsolateHandleContext scope(GetJseContext());
41     v8::Local<v8::Value> value = GetValue();
42 
43     // Yes, bools might be integers, somehow.
44     EXPECT_TRUE(fxv8::IsBoolean(value) || fxv8::IsInteger(value))
45         << "Program: " << input;
46     EXPECT_EQ(expected, fxv8::ReentrantToBooleanHelper(isolate(), value))
47         << "Program: " << input;
48   }
49 
ExecuteExpectInt32(ByteStringView input,int32_t expected)50   void ExecuteExpectInt32(ByteStringView input, int32_t expected) {
51     EXPECT_TRUE(Execute(input)) << "Program: " << input;
52 
53     CFXJSE_ScopeUtil_IsolateHandleContext scope(GetJseContext());
54     v8::Local<v8::Value> value = GetValue();
55     EXPECT_TRUE(fxv8::IsInteger(value)) << "Program: " << input;
56     EXPECT_EQ(expected, fxv8::ReentrantToInt32Helper(isolate(), value))
57         << "Program: " << input;
58   }
59 
ExecuteExpectFloat(ByteStringView input,float expected)60   void ExecuteExpectFloat(ByteStringView input, float expected) {
61     EXPECT_TRUE(Execute(input)) << "Program: " << input;
62 
63     CFXJSE_ScopeUtil_IsolateHandleContext scope(GetJseContext());
64     v8::Local<v8::Value> value = GetValue();
65     EXPECT_TRUE(fxv8::IsNumber(value));
66     EXPECT_FLOAT_EQ(expected, fxv8::ReentrantToFloatHelper(isolate(), value))
67         << "Program: " << input;
68   }
69 
ExecuteExpectFloatNear(ByteStringView input,float expected)70   void ExecuteExpectFloatNear(ByteStringView input, float expected) {
71     constexpr float kPrecision = 0.000001f;
72 
73     EXPECT_TRUE(Execute(input)) << "Program: " << input;
74 
75     CFXJSE_ScopeUtil_IsolateHandleContext scope(GetJseContext());
76     v8::Local<v8::Value> value = GetValue();
77     EXPECT_TRUE(fxv8::IsNumber(value));
78     EXPECT_NEAR(expected, fxv8::ReentrantToFloatHelper(isolate(), value),
79                 kPrecision)
80         << "Program: " << input;
81   }
82 
ExecuteExpectNaN(ByteStringView input)83   void ExecuteExpectNaN(ByteStringView input) {
84     EXPECT_TRUE(Execute(input)) << "Program: " << input;
85 
86     CFXJSE_ScopeUtil_IsolateHandleContext scope(GetJseContext());
87     v8::Local<v8::Value> value = GetValue();
88     EXPECT_TRUE(fxv8::IsNumber(value));
89     EXPECT_TRUE(isnan(fxv8::ReentrantToDoubleHelper(isolate(), value)));
90   }
91 
ExecuteExpectString(ByteStringView input,const char * expected)92   void ExecuteExpectString(ByteStringView input, const char* expected) {
93     EXPECT_TRUE(Execute(input)) << "Program: " << input;
94 
95     CFXJSE_ScopeUtil_IsolateHandleContext scope(GetJseContext());
96     v8::Local<v8::Value> value = GetValue();
97     EXPECT_TRUE(fxv8::IsString(value));
98     EXPECT_STREQ(expected,
99                  fxv8::ReentrantToByteStringHelper(isolate(), value).c_str())
100         << "Program: " << input;
101   }
102 };
103 
104 // TODO(dsinclair): Comment out tests are broken and need to be fixed.
105 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,TranslateEmpty)106 TEST_F(CFXJSE_FormCalcContextEmbedderTest, TranslateEmpty) {
107   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
108 
109   const char input[] = "";
110   EXPECT_TRUE(Execute(input));
111   // TODO(dsinclair): This should probably throw as a blank formcalc script
112   // is invalid.
113 }
114 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,TranslateNumber)115 TEST_F(CFXJSE_FormCalcContextEmbedderTest, TranslateNumber) {
116   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
117   ExecuteExpectInt32("123", 123);
118 }
119 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Numeric)120 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Numeric) {
121   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
122 
123   ExecuteExpectInt32("123 + 456", 579);
124   ExecuteExpectInt32("2 - 3 * 10 / 2 + 7", -6);
125   ExecuteExpectInt32("10 * 3 + 5 * 4", 50);
126   ExecuteExpectInt32("(5 - \"abc\") * 3", 15);
127   ExecuteExpectInt32("\"100\" / 10e1", 1);
128   ExecuteExpectInt32("5 + null + 3", 8);
129 #if 0
130   // TODO(thestig): Investigate these cases.
131   ExecuteExpectInt32(
132       "if (\"abc\") then\n"
133       "  10\n"
134       "else\n"
135       "  20\n"
136       "endif",
137       20);
138   ExecuteExpectInt32("3 / 0 + 1", 0);
139 #endif
140   ExecuteExpectInt32("-(17)", -17);
141   ExecuteExpectInt32("-(-17)", 17);
142   ExecuteExpectInt32("+(17)", 17);
143   ExecuteExpectInt32("+(-17)", -17);
144   ExecuteExpectInt32("if (1 < 2) then\n1\nendif", 1);
145   ExecuteExpectInt32(
146       "if (\"abc\" > \"def\") then\n"
147       "  1 and 0\n"
148       "else\n"
149       "  0\n"
150       "endif",
151       0);
152 }
153 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Strings)154 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Strings) {
155   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
156 
157   ExecuteExpectString("\"abc\"", "abc");
158   ExecuteExpectString(
159       "concat(\"The total is \", 2, \" dollars and \", 57, \" cents.\")",
160       "The total is 2 dollars and 57 cents.");
161 }
162 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Booleans)163 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Booleans) {
164   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
165 
166   ExecuteExpectBool("0 and 1 or 2 > 1", true);
167   ExecuteExpectBool("2 < 3 not 1 == 1", false);
168   ExecuteExpectBool("\"abc\" | 2", true);
169   ExecuteExpectBool("1 or 0", true);
170   ExecuteExpectBool("0 | 0", false);
171   ExecuteExpectBool("0 or 1 | 0 or 0", true);
172   ExecuteExpectBool("1 and 0", false);
173   ExecuteExpectBool("0 and 1 & 0 and 0", false);
174   ExecuteExpectBool("not(\"true\")", true);
175   ExecuteExpectBool("not(1)", false);
176   ExecuteExpectBool("3 == 3", true);
177   ExecuteExpectBool("3 <> 4", true);
178   ExecuteExpectBool("\"abc\" eq \"def\"", false);
179   ExecuteExpectBool("\"def\" ne \"abc\"", true);
180   ExecuteExpectBool("5 + 5 == 10", true);
181   ExecuteExpectBool("5 + 5 <> \"10\"", false);
182   ExecuteExpectBool("3 < 3", false);
183   ExecuteExpectBool("3 > 4", false);
184   ExecuteExpectBool("\"abc\" <= \"def\"", true);
185   ExecuteExpectBool("\"def\" > \"abc\"", true);
186   ExecuteExpectBool("12 >= 12", true);
187   ExecuteExpectBool("\"true\" < \"false\"", false);
188 #if 0
189   // TODO(thestig): Investigate this case.
190   // Confirm with Reader.
191   ExecuteExpectBool("0 & 0", true);
192 #endif
193 }
194 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Abs)195 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Abs) {
196   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
197 
198   ExecuteExpectFloat("Abs(1.03)", 1.03f);
199   ExecuteExpectFloat("Abs(-1.03)", 1.03f);
200   ExecuteExpectFloat("Abs(0)", 0.0f);
201 }
202 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Avg)203 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Avg) {
204   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
205 
206   ExecuteExpectFloat("Avg(0, 32, 16)", 16.0f);
207   ExecuteExpectFloat("Avg(2.5, 17, null)", 9.75f);
208 }
209 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Ceil)210 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Ceil) {
211   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
212 
213   ExecuteExpectInt32("Ceil(2.5875)", 3);
214   ExecuteExpectInt32("Ceil(-5.9)", -5);
215   ExecuteExpectInt32("Ceil(\"abc\")", 0);
216 }
217 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Count)218 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Count) {
219   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
220 
221   ExecuteExpectInt32("Count(\"Tony\", \"Blue\", 41)", 3);
222 }
223 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Floor)224 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Floor) {
225   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
226 
227   ExecuteExpectInt32("Floor(21.3409873)", 21);
228   ExecuteExpectInt32("Floor(5.999965342)", 5);
229   ExecuteExpectInt32("Floor(3.2 * 15)", 48);
230 }
231 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Max)232 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Max) {
233   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
234 
235   ExecuteExpectInt32("Max(234, 15, 107)", 234);
236   ExecuteExpectInt32("Max(\"abc\", 15, \"Tony Blue\")", 15);
237   ExecuteExpectInt32("Max(\"abc\")", 0);
238 }
239 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Min)240 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Min) {
241   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
242 
243   ExecuteExpectInt32("Min(234, 15, 107)", 15);
244 #if 0
245   // TODO(thestig): Investigate these cases.
246   // Verify with Reader; This should have a return value of 0.
247   ExecuteExpectInt32("Min(\"abc\", 15, \"Tony Blue\")", 15);
248 #endif
249   ExecuteExpectInt32("Min(\"abc\")", 0);
250 }
251 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Mod)252 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Mod) {
253   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
254 
255   ExecuteExpectInt32("Mod(64, -3)", 1);
256   ExecuteExpectInt32("Mod(-13, 3)", -1);
257   ExecuteExpectInt32("Mod(\"abc\", 2)", 0);
258 
259   ExecuteExpectNaN("Mod(10, NaN)");
260   ExecuteExpectNaN("Mod(10, Infinity)");
261 }
262 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Round)263 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Round) {
264   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
265 
266   ExecuteExpectFloat("Round(12.389764537, 4)", 12.3898f);
267   ExecuteExpectFloat("Round(20/3, 2)", 6.67f);
268   ExecuteExpectFloat("Round(8.9897, \"abc\")", 9.0f);
269   ExecuteExpectFloat("Round(FV(400, 0.10/12, 30*12), 2)", 904195.17f);
270 }
271 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Sum)272 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Sum) {
273   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
274 
275   ExecuteExpectInt32("Sum(2, 4, 6, 8)", 20);
276   ExecuteExpectInt32("Sum(-2, 4, -6, 8)", 4);
277   ExecuteExpectInt32("Sum(4, 16, \"abc\", 19)", 39);
278 }
279 
280 // TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Date) {
281 //   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
282 //
283 //   TODO(dsinclair): Make compatible with windows.
284 //   time_t seconds = time(nullptr);
285 //   int days = seconds / (60 * 60 * 24);
286 
287 //   EXPECT_TRUE(Execute("Date()"));
288 
289 //   v8::Local<v8::Value> value = GetValue();
290 //   EXPECT_TRUE(value->IsNumber());
291 //   EXPECT_EQ(days, value->ToInteger());
292 // }
293 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Date2Num)294 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Date2Num) {
295   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
296 
297   ExecuteExpectInt32("Date2Num(\"1/1/1900\", \"D/M/YYYY\")", 1);
298   ExecuteExpectInt32("Date2Num(\"03/15/96\", \"MM/DD/YY\")", 35138);
299   ExecuteExpectInt32("Date2Num(\"96-08-20\", \"YY-MM-DD\", \"fr_FR\")", 35296);
300   ExecuteExpectInt32(
301       "Date2Num(\"1/3/00\", \"D/M/YY\") - Date2Num(\"1/2/00\", \"D/M/YY\")",
302       29);
303 #if 0
304   // TODO(thestig): Investigate these cases.
305   ExecuteExpectInt32("Date2Num(\"Mar 15, 1996\")", 35138);
306   ExecuteExpectInt32("Date2Num(\"Aug 1, 1996\", \"MMM D, YYYY\")", 35277);
307 #endif
308 }
309 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DateFmt)310 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DateFmt) {
311   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
312 
313   ExecuteExpectString("DateFmt(3, \"de_DE\")", "D. MMMM YYYY");
314 #if 0
315   // TODO(thestig): Investigate these cases.
316   ExecuteExpectString("DateFmt(1)", "M/D/YY");
317   ExecuteExpectString("DateFmt(2, \"fr_CA\")", "YY-MM-DD");
318   ExecuteExpectString("DateFmt(4, \"fr_FR\")", "EEE D' MMMM YYYY");
319 #endif
320 }
321 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,IsoDate2Num)322 TEST_F(CFXJSE_FormCalcContextEmbedderTest, IsoDate2Num) {
323   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
324 
325   ExecuteExpectInt32("IsoDate2Num(\"1900\")", 1);
326   ExecuteExpectInt32("IsoDate2Num(\"1900-01\")", 1);
327   ExecuteExpectInt32("IsoDate2Num(\"1900-01-01\")", 1);
328   ExecuteExpectInt32("IsoDate2Num(\"19960315T20:20:20\")", 35138);
329   ExecuteExpectInt32("IsoDate2Num(\"2000-03-01\") - IsoDate2Num(\"20000201\")",
330                      29);
331 }
332 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DISABLED_IsoTime2Num)333 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_IsoTime2Num) {
334   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
335 
336   ExecuteExpectInt32("IsoTime2Num(\"00:00:00Z\")", 1);
337 }
338 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,LocalDateFmt)339 TEST_F(CFXJSE_FormCalcContextEmbedderTest, LocalDateFmt) {
340   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
341 
342   ExecuteExpectString("LocalDateFmt(3, \"de_CH\")", "t. MMMM jjjj");
343   ExecuteExpectString("LocalDateFmt(4, \"fr_FR\")", "EEEE j MMMM aaaa");
344 #if 0
345   // TODO(thestig): Investigate these cases.
346   ExecuteExpectString("LocalDateFmt(1, \"de_DE\")", "tt.MM.uu");
347   ExecuteExpectString("LocalDateFmt(2, \"fr_CA\")", "aa-MM-jj");
348 #endif
349 }
350 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DISABLED_LocalTimeFmt)351 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_LocalTimeFmt) {
352   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
353 
354   ExecuteExpectString("LocalTimeFmt(1, \"de_DE\")", "HH:mm");
355   ExecuteExpectString("LocalTimeFmt(2, \"fr_CA\")", "HH:mm::ss");
356   ExecuteExpectString("LocalTimeFmt(3, \"de_CH\")", "HH:mm:ss z");
357   ExecuteExpectString("LocalTimeFmt(4, \"fr_FR\")", "HH' h 'mm z");
358 }
359 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Num2Date)360 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Num2Date) {
361   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
362 
363   ExecuteExpectString("Num2Date(1, \"DD/MM/YYYY\")", "01/01/1900");
364   ExecuteExpectString("Num2Date(35139, \"DD-MMM-YYYY\", \"de_DE\")",
365                       "16-Mrz-1996");
366 #if 0
367   // TODO(thestig): Investigate this case.
368   ExecuteExpectString(
369       "Num2Date(Date2Num(\"Mar 15, 2000\") - Date2Num(\"98-03-15\", "
370       "\"YY-MM-DD\", \"fr_CA\"))",
371       "Jan 1, 1902");
372 #endif
373 }
374 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DISABLED_Num2GMTime)375 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Num2GMTime) {
376   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
377 
378   // Broken on Windows only.
379   ExecuteExpectString("Num2GMTime(1, \"HH:MM:SS\")", "00:00:00");
380   // Below broken on other platforms.
381   ExecuteExpectString("Num2GMTime(65593001, \"HH:MM:SS Z\")", "18:13:13 GMT");
382   ExecuteExpectString("Num2GMTime(43993001, TimeFmt(4, \"de_DE\"), \"de_DE\")",
383                       "12.13 Uhr GMT");
384 }
385 
386 // TODO(dsinclair): Broken on Mac ...
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DISABLED_Num2Time)387 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Num2Time) {
388   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
389 
390   ExecuteExpectString("Num2Time(1, \"HH:MM:SS\")", "00:00:00");
391 }
392 
393 // TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Time) {
394 //   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
395 //   TODO(dsinclair): Make compatible with windows.
396 //   struct timeval tp;
397 //   gettimeofday(&tp, nullptr);
398 
399 //   EXPECT_TRUE(Execute("Time()"));
400 
401 //   v8::Local<v8::Value> value = GetValue();
402 //   EXPECT_TRUE(value->IsInteger());
403 //   EXPECT_EQ(tp.tv_sec * 1000L + tp.tv_usec / 1000, value->ToInteger())
404 //       << "Program: Time()";
405 // }
406 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Time2Num)407 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Time2Num) {
408   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
409 
410   ExecuteExpectInt32("Time2Num(\"00:00:00 GMT\", \"HH:MM:SS Z\")", 1);
411   ExecuteExpectInt32("Time2Num(\"00:00:01 GMT\", \"HH:MM:SS Z\")", 1001);
412   ExecuteExpectInt32("Time2Num(\"00:01:00 GMT\", \"HH:MM:SS Z\")", 60001);
413   ExecuteExpectInt32("Time2Num(\"01:00:00 GMT\", \"HH:MM:SS Z\")", 3600001);
414   ExecuteExpectInt32("Time2Num(\"23:59:59 GMT\", \"HH:MM:SS Z\")", 86399001);
415   // https://crbug.com/pdfium/1257
416   ExecuteExpectInt32("Time2Num(\"\", \"\", 1)", 0);
417   ExecuteExpectInt32("Time2Num(\"13:13:13 GMT\", \"HH:MM:SS Z\", \"fr_FR\")",
418                      47593001);
419 }
420 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Time2NumWithTZ)421 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Time2NumWithTZ) {
422   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
423 
424   static constexpr const char* kTimeZones[] = {
425       "UTC+14",   "UTC-14",   "UTC+9:30", "UTC-0:30",
426       "UTC+0:30", "UTC-0:01", "UTC+0:01"};
427   for (const char* tz : kTimeZones) {
428     ScopedSetTZ scoped_set_tz(tz);
429     ExecuteExpectInt32("Time2Num(\"00:00:00 GMT\", \"HH:MM:SS Z\")", 1);
430     ExecuteExpectInt32("Time2Num(\"11:59:59 GMT\", \"HH:MM:SS Z\")", 43199001);
431     ExecuteExpectInt32("Time2Num(\"12:00:00 GMT\", \"HH:MM:SS Z\")", 43200001);
432     ExecuteExpectInt32("Time2Num(\"23:59:59 GMT\", \"HH:MM:SS Z\")", 86399001);
433   }
434   {
435     ScopedSetTZ scoped_set_tz("UTC-3:00");
436     ExecuteExpectInt32("Time2Num(\"1:13:13 PM\")", 36793001);
437     ExecuteExpectInt32(
438         "Time2Num(\"13:13:13 GMT\", \"HH:MM:SS Z\") - "
439         "Time2Num(\"13:13:13\", \"HH:MM:SS\")",
440         10800000);
441   }
442 }
443 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,TimeFmt)444 TEST_F(CFXJSE_FormCalcContextEmbedderTest, TimeFmt) {
445   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
446 
447   ExecuteExpectString("TimeFmt(2, \"fr_CA\")", "HH:MM:SS");
448   ExecuteExpectString("TimeFmt(3, \"fr_FR\")", "HH:MM:SS Z");
449 #if 0
450   // TODO(thestig): Investigate these cases.
451   ExecuteExpectString("TimeFmt(1)", "h::MM A");
452   ExecuteExpectString("TimeFmt(4, \"de_DE\")", "H.MM' Uhr 'Z");
453 #endif
454 }
455 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Apr)456 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Apr) {
457   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
458 
459   ExecuteExpectFloatNear("Apr(35000, 269.50, 360)", 0.08515404566f);
460   ExecuteExpectFloatNear("Apr(210000 * 0.75, 850 + 110, 25 * 26)",
461                          0.07161332404f);
462 
463   ExecuteExpectError("Apr(2, 2, 2147483648)");
464 }
465 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,CTerm)466 TEST_F(CFXJSE_FormCalcContextEmbedderTest, CTerm) {
467   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
468 
469   ExecuteExpectFloat("CTerm(0.10, 500000, 12000)", 39.13224648502f);
470 #if 0
471   // TODO(thestig): Investigate these cases.
472   ExecuteExpectFloat("CTerm(0.02, 1000, 100)", 116.2767474515f);
473   ExecuteExpectFloat("CTerm(0.0275 + 0.0025, 1000000, 55000 * 0.10)",
474                      176.02226044975f);
475 #endif
476 }
477 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,FV)478 TEST_F(CFXJSE_FormCalcContextEmbedderTest, FV) {
479   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
480 
481   ExecuteExpectFloat("FV(400, 0.10 / 12, 30 * 12)", 904195.16991842445f);
482   ExecuteExpectFloat("FV(1000, 0.075 / 4, 10 * 4)", 58791.96145535981f);
483 
484   ExecuteExpectError("FV(2, 2, 2147483648)");
485 }
486 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,IPmt)487 TEST_F(CFXJSE_FormCalcContextEmbedderTest, IPmt) {
488   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
489 
490   ExecuteExpectFloat("IPmt(30000, 0.085, 295.50, 7, 3)", 624.8839283142f);
491   ExecuteExpectFloat("IPmt(160000, 0.0475, 980, 24, 12)", 7103.80833569485f);
492   ExecuteExpectFloat("IPmt(15000, 0.065, 65.50, 15, 1)", 0.0f);
493 }
494 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,NPV)495 TEST_F(CFXJSE_FormCalcContextEmbedderTest, NPV) {
496   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
497 
498   ExecuteExpectFloat("NPV(0.065, 5000)", 4694.83568075117f);
499   ExecuteExpectFloat("NPV(0.10, 500, 1500, 4000, 10000)", 11529.60863329007f);
500   ExecuteExpectFloat("NPV(0.0275 / 12, 50, 60, 40, 100, 25)", 273.14193838457f);
501 }
502 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Pmt)503 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Pmt) {
504   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
505 
506   ExecuteExpectFloat("Pmt(25000, 0.085, 12)", 3403.82145169876f);
507   ExecuteExpectFloat("Pmt(5000, 0.01, 1)", 5050);
508   ExecuteExpectFloat("Pmt(5000, 0.01, 1.5)", 5050);
509   ExecuteExpectFloat("Pmt(30000.00, .085 / 12, 12 * 12)", 333.01666929435f);
510   ExecuteExpectFloat("Pmt(10000, .08 / 12, 10)", 1037.03208935916f);
511   ExecuteExpectFloat("Pmt(150000, 0.0475 / 12, 25 * 12)", 855.17604207164f);
512 
513   // https://crbug.com/1293179
514   ExecuteExpectError("Pmt(2, 2, 99999997952)");
515 }
516 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,PPmt)517 TEST_F(CFXJSE_FormCalcContextEmbedderTest, PPmt) {
518   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
519 
520   ExecuteExpectFloat("PPmt(30000, 0.085, 295.50, 7, 3)", 261.6160716858f);
521   ExecuteExpectFloat("PPmt(160000, 0.0475, 980, 24, 12)", 4656.19166430515f);
522 #if 0
523   // TODO(thestig): Investigate this case.
524   ExecuteExpectFloat("PPmt(15000, 0.065, 65.50, 15, 1)", 0.0f);
525 #endif
526 }
527 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,PV)528 TEST_F(CFXJSE_FormCalcContextEmbedderTest, PV) {
529   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
530 
531   ExecuteExpectFloat("PV(400, 0.10 / 12, 30 * 12)", 45580.32799074439f);
532   ExecuteExpectFloat("PV(1000, 0.075 / 4, 10 * 4)", 27964.88770467326f);
533 
534   // https://crbug.com/1296840
535   ExecuteExpectError("PV(2, 2, 2147483648)");
536 }
537 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Rate)538 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Rate) {
539   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
540 
541   ExecuteExpectFloatNear("Rate(12000, 8000, 5)", 0.0844717712f);
542   ExecuteExpectFloatNear("Rate(10000, 0.25 * 5000, 4 * 12)", 0.04427378243f);
543 
544   ExecuteExpectError("Rate(2, 2, 2147483648)");
545 }
546 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Term)547 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Term) {
548   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
549 
550   ExecuteExpectFloat("Term(2500, 0.0275 + 0.0025, 5000)", 1.97128786369f);
551 #if 0
552   // TODO(thestig): Investigate this case.
553   ExecuteExpectFloat("Term(475, .05, 1500)", 3.00477517728f);
554 #endif
555 }
556 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Choose)557 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Choose) {
558   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
559 
560   ExecuteExpectString("Choose(3, \"Taxes\", \"Price\", \"Person\", \"Teller\")",
561                       "Person");
562   ExecuteExpectString("Choose(2, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)", "9");
563   ExecuteExpectString(
564       "Choose(20/3, \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\")",
565       "F");
566 }
567 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Exists)568 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Exists) {
569   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
570   ExecuteExpectBool("Exists(\"hello world\")", false);
571 }
572 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,HasValue)573 TEST_F(CFXJSE_FormCalcContextEmbedderTest, HasValue) {
574   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
575 
576   ExecuteExpectBool("HasValue(2)", true);
577   ExecuteExpectBool("HasValue(\" \")", false);
578 }
579 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Oneof)580 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Oneof) {
581   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
582 
583   ExecuteExpectBool("Oneof(3, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)", true);
584   ExecuteExpectBool(
585       "Oneof(\"John\", \"Bill\", \"Gary\", \"Joan\", \"John\", \"Lisa\")",
586       true);
587   ExecuteExpectBool("Oneof(3, 1, 25)", false);
588   ExecuteExpectBool("Oneof(3, 3, null)", true);
589   ExecuteExpectBool("Oneof(3, null, null)", false);
590 }
591 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Within)592 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Within) {
593   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
594 
595   ExecuteExpectBool("Within(\"C\", \"A\", \"D\")", true);
596   ExecuteExpectBool("Within(1.5, 0, 2)", true);
597   ExecuteExpectBool("Within(-1, 0, 2)", false);
598 }
599 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Eval)600 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Eval) {
601   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
602 
603   ExecuteExpectInt32("eval(\"10*3+5*4\")", 50);
604 }
605 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,DISABLED_Null)606 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Null) {
607   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
608 
609   ExecuteExpectString("Null()", "null");
610   ExecuteExpectString("Concat(\"ABC\", Null(), \"DEF\")", "ABCDEF");
611   ExecuteExpectInt32("Null() + 5", 5);
612 }
613 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Ref)614 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Ref) {
615   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
616 
617   ExecuteExpectString("Ref(\"10*3+5*4\")", "10*3+5*4");
618   ExecuteExpectString("Ref(\"hello\")", "hello");
619 }
620 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,UnitType)621 TEST_F(CFXJSE_FormCalcContextEmbedderTest, UnitType) {
622   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
623 
624   ExecuteExpectString("UnitType(\"36 in\")", "in");
625   ExecuteExpectString("UnitType(\"2.54centimeters\")", "cm");
626   ExecuteExpectString("UnitType(\"picas\")", "pt");
627   ExecuteExpectString("UnitType(\"2.cm\")", "cm");
628   ExecuteExpectString("UnitType(\"2.zero cm\")", "in");
629   ExecuteExpectString("UnitType(\"kilometers\")", "in");
630 }
631 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,UnitValue)632 TEST_F(CFXJSE_FormCalcContextEmbedderTest, UnitValue) {
633   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
634 
635   ExecuteExpectFloat("UnitValue(\"2in\")", 2.0f);
636   ExecuteExpectFloat("UnitValue(\"2in\", \"cm\")", 5.08f);
637 #if 0
638   // TODO(thestig): Investigate these cases.
639   // Should the UnitType cases move into the UnitType test case?
640   ExecuteExpectFloat("UnitValue(\"6\", \"pt\")", 432f);
641   ExecuteExpectFloat("UnitType(\"A\", \"cm\")", 0.0f);
642   ExecuteExpectFloat("UnitType(\"5.08cm\", \"kilograms\")", 2.0f);
643 #endif
644 }
645 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,At)646 TEST_F(CFXJSE_FormCalcContextEmbedderTest, At) {
647   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
648 
649   ExecuteExpectInt32("At(\"ABCDEFGH\", \"AB\")", 1);
650   ExecuteExpectInt32("At(\"ABCDEFGH\", \"F\")", 6);
651   ExecuteExpectInt32("At(23412931298471, 29)", 5);
652 }
653 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Concat)654 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Concat) {
655   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
656 
657   ExecuteExpectString("Concat(\"ABC\", \"DEF\")", "ABCDEF");
658   ExecuteExpectString("Concat(\"Tony\", Space(1), \"Blue\")", "Tony Blue");
659   ExecuteExpectString("Concat(\"You owe \", WordNum(1154.67, 2), \".\")",
660                       "You owe One Thousand One Hundred Fifty-four Dollars And "
661                       "Sixty-seven Cents.");
662 }
663 
TEST_F(CFXJSE_FormCalcContextEmbedderTest,Decode)664 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Decode) {
665   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
666 
667   // HTML
668   ExecuteExpectString(R"(Decode("", "html"))", "");
669   ExecuteExpectString(R"(Decode("abc&Acirc;xyz", "html"))", "abc\xC3\x82xyz");
670   ExecuteExpectString(R"(Decode("abc&NoneSuchButVeryLongIndeed;", "html"))",
671                       "abc");
672   ExecuteExpectString(R"(Decode("&#x0041;&AElig;&Aacute;", "html"))",
673                       "A\xC3\x86\xC3\x81");
674   ExecuteExpectString(R"(Decode("xyz&#", "html"))", "xyz");
675   ExecuteExpectString(R"(Decode("|&zzzzzz;|", "html"))", "||");
676 
677   // XML
678   ExecuteExpectString(R"(Decode("", "xml"))", "");
679   ExecuteExpectString(R"(Decode("~!@#$%%^&amp;*()_+|`", "xml"))",
680                       "~!@#$%%^&*()_+|`");
681   ExecuteExpectString(R"(Decode("abc&nonesuchbutverylongindeed;", "xml"))",
682                       "abc");
683   ExecuteExpectString(R"(Decode("&quot;&#x45;&lt;&gt;[].&apos;", "xml"))",
684                       "\"E<>[].'");
685   ExecuteExpectString(R"(Decode("xyz&#", "xml"))", "xyz");
686   ExecuteExpectString(R"(Decode("|&zzzzzz;|", "xml"))", "||");
687 
688   // URL
689   ExecuteExpectString(R"(Decode("", "url"))", "");
690   ExecuteExpectString(R"(Decode("~%26^&*()_+|`{", "url"))", "~&^&*()_+|`{");
691   ExecuteExpectString(R"(Decode("~%26^&*()_+|`{", "mbogo"))", "~&^&*()_+|`{");
692   ExecuteExpectString(R"(Decode("~%26^&*()_+|`{"))", "~&^&*()_+|`{");
693   ExecuteExpectString(R"(Decode("~%~~"))", "");
694   ExecuteExpectString(R"(Decode("?%~"))", "");
695   ExecuteExpectString(R"(Decode("?%"))", "?");
696 }
697 
698 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Encode) {
699   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
700 
701   ExecuteExpectString("Encode(\"X/~&^*<=>?|\")",
702                       "X%2f%7e%26%5e*%3c%3d%3e%3f%7c");
703   ExecuteExpectString("Encode(\"X/~&^*<=>?|\", \"mbogo\")",
704                       "X%2f%7e%26%5e*%3c%3d%3e%3f%7c");
705   ExecuteExpectString("Encode(\"X/~&^*<=>?|\", \"url\")",
706                       "X%2f%7e%26%5e*%3c%3d%3e%3f%7c");
707   ExecuteExpectString("Encode(\"X/~&^*<=>?|\", \"xml\")",
708                       "X/~&amp;^*&lt;=&gt;?|");
709   ExecuteExpectString("Encode(\"X/~&^*<=>?|\", \"html\")",
710                       "X/~&amp;^*&lt;=&gt;?|");
711 
712   ExecuteExpectString("Encode(\"\\u0022\\u00f5\\ufed0\", \"url\")",
713                       "%22%f5%fe%d0");
714   ExecuteExpectString("Encode(\"\\u0022\\u00f4\\ufed0\", \"xml\")",
715                       "&quot;&#xf4;&#xfed0;");
716   ExecuteExpectString("Encode(\"\\u0022\\u00f5\\ufed0\", \"html\")",
717                       "&quot;&otilde;&#xfed0;");
718 
719   ExecuteExpectString("Encode(\"\\uD83D\\uDCA9\", \"url\")", "%01%f4%a9");
720   ExecuteExpectString("Encode(\"\\uD83D\\uDCA9\", \"xml\")", "");
721   ExecuteExpectString("Encode(\"\\uD83D\\uDCA9\", \"html\")", "");
722 }
723 
724 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Format) {
725   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
726 
727   ExecuteExpectString("Format(\"MMM D, YYYY\", \"20020901\")", "Sep 1, 2002");
728   ExecuteExpectString("Format(\"$9,999,999.99\", 1234567.89)", "$1,234,567.89");
729 }
730 
731 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Left) {
732   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
733 
734   ExecuteExpectString("Left(\"ABCDEFGH\", 3)", "ABC");
735   ExecuteExpectString("Left(\"Tony Blue\", 5)", "Tony ");
736 }
737 
738 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Len) {
739   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
740 
741   ExecuteExpectInt32("Len(\"ABCDEFGH\")", 8);
742   ExecuteExpectInt32("Len(4)", 1);
743   ExecuteExpectInt32("Len(Str(4.532, 6, 4))", 6);
744 }
745 
746 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Lower) {
747   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
748 
749   ExecuteExpectString("Lower(\"ABC\")", "abc");
750   ExecuteExpectString("Lower(\"21 Main St.\")", "21 main st.");
751   ExecuteExpectString("Lower(15)", "15");
752 }
753 
754 // This is testing for an OOB read, so will likely only fail under ASAN.
755 TEST_F(CFXJSE_FormCalcContextEmbedderTest, bug_854623) {
756   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
757 
758   const uint8_t test_string[] = {
759       0x4c, 0x6f, 0x77, 0x65, 0x72, 0x28, 0x22, 0xc3,
760       0x85, 0xc3, 0x85, 0xc3, 0x85, 0x22, 0x29};  // Lower("ÅÅÅ")
761   Execute(ByteString(test_string, sizeof(test_string)).AsStringView());
762 }
763 
764 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Ltrim) {
765   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
766 
767   ExecuteExpectString("Ltrim(\"   ABCD\")", "ABCD");
768   ExecuteExpectString("Ltrim(Rtrim(\"    Tony Blue    \"))", "Tony Blue");
769 }
770 
771 TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Parse) {
772   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
773 
774   ExecuteExpectString("Parse(\"MMM D, YYYY\", \"Sep 1, 2002\")", "2002-09-01");
775   ExecuteExpectFloat("Parse(\"$9,999,999.99\", \"$1,234,567.89\")",
776                      1234567.89f);
777 }
778 
779 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Replace) {
780   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
781 
782   ExecuteExpectString("Replace(\"Tony Blue\", \"Tony\", \"Chris\")",
783                       "Chris Blue");
784   ExecuteExpectString("Replace(\"ABCDEFGH\", \"D\")", "ABCEFGH");
785   ExecuteExpectString("Replace(\"ABCDEFGH\", \"d\")", "ABCDEFGH");
786 }
787 
788 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Right) {
789   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
790 
791   ExecuteExpectString("Right(\"ABCDEFGH\", 3)", "FGH");
792   ExecuteExpectString("Right(\"Tony Blue\", 5)", " Blue");
793 }
794 
795 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Rtrim) {
796   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
797 
798   ExecuteExpectString("Rtrim(\"ABCD   \")", "ABCD");
799   ExecuteExpectString("Rtrim(\"Tony Blue      \t\")", "Tony Blue");
800 }
801 
802 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Space) {
803   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
804 
805   ExecuteExpectString("Space(5)", "     ");
806   ExecuteExpectString("Concat(\"Tony\", Space(1), \"Blue\")", "Tony Blue");
807 
808   // Error cases.
809   ExecuteExpectError("Space(15654909)");
810   ExecuteExpectError("Space(99999999)");
811   ExecuteExpectError("Space()");
812   ExecuteExpectError("Space(1, 2)");
813   ExecuteExpectNull("Space( $)");
814 }
815 
816 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Str) {
817   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
818 
819   ExecuteExpectString("Str(2.456)", "         2");
820   ExecuteExpectString("Str(4.532, 6, 4)", "4.5320");
821   ExecuteExpectString("Str(234.458, 4)", " 234");
822   ExecuteExpectString("Str(31.2345, 4, 2)", "****");
823 
824   // Test maximum "n3" precision value.
825   ExecuteExpectString("Str(-765, 19, 14)", "-765.00000000000000");
826   ExecuteExpectString("Str(-765, 20, 15)", "-765.000000000000000");
827   ExecuteExpectString("Str(-765, 21, 16)", " -765.000000000000000");
828 
829   // Error cases.
830   ExecuteExpectError("Str()");
831   ExecuteExpectError("Str(1, 2, 3, 4)");
832   ExecuteExpectError("Str(42, 15654909)");
833   ExecuteExpectNull("Str( $)");
834 }
835 
836 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Stuff) {
837   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
838 
839   // Test wrong number of parameters.
840   ExecuteExpectError("Stuff(1, 2)");
841   ExecuteExpectError("Stuff(1, 2, 3, 4, 5)");
842 
843   // Test null arguments.
844   ExecuteExpectNull("Stuff(null, 0, 4)");
845   ExecuteExpectNull("Stuff(\"ABCDEFG\", null, 4)");
846   ExecuteExpectNull("Stuff(\"ABCDEFG\", 0, null)");
847 
848   // Insertions.
849   ExecuteExpectString("Stuff(\"\", 0, 0, \"clams\")", "clams");
850   ExecuteExpectString("Stuff(\"TonyBlue\", 5, 0, \" \")", "Tony Blue");
851 
852   // Deletions.
853   ExecuteExpectString("Stuff(\"A\", 1, 0)", "A");
854   ExecuteExpectString("Stuff(\"A\", 1, 1)", "");
855   ExecuteExpectString("Stuff(\"ABCDEFGH\", 4, 2)", "ABCFGH");
856   ExecuteExpectString("Stuff(\"ABCDEFGH\", 7, 2)", "ABCDEF");
857 
858   // Test index clamping.
859   ExecuteExpectString("Stuff(\"ABCDEFGH\", -400, 400)", "");
860 
861   // Need significant amount of text to test start + count overflow due to
862   // intermediate float representation of count not being able to hold
863   // INT_MAX.
864   ExecuteExpectString(
865       "Stuff(\""
866       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678900"
867       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678900"
868       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678900"
869       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678900"
870       "\", 133, 2147483520)",
871       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678900"
872       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678900"
873       "abcd");
874 }
875 
876 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Substr) {
877   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
878 
879   // Test wrong number of parameters.
880   ExecuteExpectError("Substr()");
881   ExecuteExpectError("Substr(1)");
882   ExecuteExpectError("Substr(1, 2)");
883   ExecuteExpectError("Substr(1, 2, 3, 4)");
884 
885   // Test null input.
886   ExecuteExpectNull("Substr(null, 0, 4)");
887   ExecuteExpectNull("Substr(\"ABCDEFG\", null, 4)");
888   ExecuteExpectNull("Substr(\"ABCDEFG\", 0, null)");
889   ExecuteExpectNull("Substr(null, null, 4)");
890   ExecuteExpectNull("Substr(null, 0, null)");
891   ExecuteExpectNull("Substr(\"ABCDEFG\", null, null)");
892   ExecuteExpectNull("Substr(null, null, null)");
893 
894   ExecuteExpectString("Substr(\"ABCDEFG\", -1, 4)", "ABCD");
895   ExecuteExpectString("Substr(\"ABCDEFG\", 0, 4)", "ABCD");
896   ExecuteExpectString("Substr(\"ABCDEFG\", 3, 4)", "CDEF");
897   ExecuteExpectString("Substr(\"ABCDEFG\", 4, 4)", "DEFG");
898   ExecuteExpectString("Substr(\"ABCDEFG\", 5, 4)", "EFG");
899   ExecuteExpectString("Substr(\"ABCDEFG\", 6, 4)", "FG");
900   ExecuteExpectString("Substr(\"ABCDEFG\", 7, 4)", "G");
901   ExecuteExpectString("Substr(\"ABCDEFG\", 8, 4)", "");
902   ExecuteExpectString("Substr(\"ABCDEFG\", 5, -1)", "");
903   ExecuteExpectString("Substr(\"ABCDEFG\", 5, 0)", "");
904   ExecuteExpectString("Substr(\"ABCDEFG\", 5, 1)", "E");
905   ExecuteExpectString("Substr(\"abcdefghi\", 5, 3)", "efg");
906   ExecuteExpectString("Substr(3214, 2, 1)", "2");
907   ExecuteExpectString("Substr(\"21 Waterloo St.\", 4, 5)", "Water");
908 }
909 
910 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Uuid) {
911   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
912   EXPECT_TRUE(Execute("Uuid()"));
913 
914   CFXJSE_ScopeUtil_IsolateHandleContext scope(GetJseContext());
915   v8::Local<v8::Value> value = GetValue();
916   EXPECT_TRUE(fxv8::IsString(value));
917 }
918 
919 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Upper) {
920   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
921 
922   ExecuteExpectString("Upper(\"abc\")", "ABC");
923   ExecuteExpectString("Upper(\"21 Main St.\")", "21 MAIN ST.");
924   ExecuteExpectString("Upper(15)", "15");
925 }
926 
927 TEST_F(CFXJSE_FormCalcContextEmbedderTest, WordNum) {
928   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
929 
930   // Wrong number of parameters.
931   ExecuteExpectError("WordNum()");
932   ExecuteExpectError("WordNum(1, 2, 3, 4)");
933 
934   // Normal format codes.
935   ExecuteExpectString("WordNum(123.45)", "One Hundred Twenty-three");
936   ExecuteExpectString("WordNum(123.45, 0)", "One Hundred Twenty-three");
937   ExecuteExpectString("WordNum(123.45, 1)", "One Hundred Twenty-three Dollars");
938   ExecuteExpectString("WordNum(123.45, 2)",
939                       "One Hundred Twenty-three Dollars And Forty-five Cents");
940 
941   // Invalid format code.
942   ExecuteExpectString("WordNum(123.45, -1)", "");
943   ExecuteExpectString("WordNum(123.45, 3)", "");
944 
945   // Locale string is ignored.
946   ExecuteExpectString("WordNum(123.45, 0, \"zh_CN\")",
947                       "One Hundred Twenty-three");
948 
949   // Zero (and near zero) values.
950   ExecuteExpectString("WordNum(0, 0)", "Zero");
951   ExecuteExpectString("WordNum(0, 1)", "Zero Dollars");
952   ExecuteExpectString("WordNum(0, 2)", "Zero Dollars And Zero Cents");
953   ExecuteExpectString("WordNum(0.12, 0)", "Zero");
954   ExecuteExpectString("WordNum(0.12, 1)", "Zero Dollars");
955   ExecuteExpectString("WordNum(0.12, 2)", "Zero Dollars And Twelve Cents");
956 
957   // Negative values.
958   ExecuteExpectString("WordNum(-1, 0)", "*");
959   ExecuteExpectString("WordNum(-1, 1)", "*");
960   ExecuteExpectString("WordNum(-1, 2)", "*");
961 
962   // Test larger values
963   // TODO(tsepez): check on "Thousand Zero"
964   ExecuteExpectString("WordNum(1.234e+6)",
965                       "One Million Two Hundred Thirty-four Thousand Zero");
966 
967   // TODO(tsepez): check on "Zero Thousand Zero"
968   ExecuteExpectString(
969       "WordNum(1.234e+9)",
970       "One Billion Two Hundred Thirty-four Million Zero Thousand Zero");
971 
972   // TODO(tsepez): check on "Zero Million"
973   ExecuteExpectString(
974       "WordNum(1.234e+12)",
975       "One Trillion Two Hundred Thirty-four Billion Zero Million Nineteen "
976       "Thousand Four Hundred Fifty-six");
977 
978   ExecuteExpectString(
979       "WordNum(1.234e+15)",
980       "One Thousand Two Hundred Thirty-three Trillion Nine Hundred Ninety-nine "
981       "Billion Nine Hundred Thirty-eight Million Seven Hundred Fifteen "
982       "Thousand "
983       "Six Hundred Forty-eight");
984 
985   // Out-of-range.
986   ExecuteExpectString("WordNum(1.234e+18)", "*");
987   ExecuteExpectString("WordNum(1.234e+21)", "*");
988   ExecuteExpectString("WordNum(1.234e+24)", "*");
989   ExecuteExpectString("WordNum(1.234e+30)", "*");
990 }
991 
992 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Get) {
993   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
994   ExecuteExpectString("Get(\"https://example.com\")", "<body>secrets</body>");
995 }
996 
997 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Post) {
998   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
999   ExecuteExpectString(
1000       "Post(\"http://example.com\", \"secret stuff\", \"text/plain\")",
1001       "posted");
1002 }
1003 
1004 TEST_F(CFXJSE_FormCalcContextEmbedderTest, Put) {
1005   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1006   ExecuteExpectString("Put(\"http://example.com\", \"secret stuff\")", "");
1007 }
1008 
1009 TEST_F(CFXJSE_FormCalcContextEmbedderTest, InvalidFunctions) {
1010   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1011 
1012   EXPECT_FALSE(ExecuteSilenceFailure("F()"));
1013   EXPECT_FALSE(ExecuteSilenceFailure("()"));
1014   EXPECT_FALSE(ExecuteSilenceFailure("()()()"));
1015   EXPECT_FALSE(ExecuteSilenceFailure("Round(2.0)()"));
1016 }
1017 
1018 TEST_F(CFXJSE_FormCalcContextEmbedderTest, MethodCall) {
1019   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1020 
1021   const char test[] = {"$form.form1.TextField11.getAttribute(\"h\")"};
1022   ExecuteExpectString(test, "12.7mm");
1023 }
1024 
1025 TEST_F(CFXJSE_FormCalcContextEmbedderTest, GetXFAEventChange) {
1026   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1027 
1028   CXFA_EventParam params;
1029   params.m_wsChange = L"changed";
1030 
1031   CFXJSE_Engine* context = GetScriptContext();
1032   CFXJSE_Engine::EventParamScope event_scope(context, nullptr, &params);
1033 
1034   const char test[] = {"xfa.event.change"};
1035   ExecuteExpectString(test, "changed");
1036 }
1037 
1038 TEST_F(CFXJSE_FormCalcContextEmbedderTest, SetXFAEventChange) {
1039   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1040 
1041   CXFA_EventParam params;
1042   CFXJSE_Engine* context = GetScriptContext();
1043   CFXJSE_Engine::EventParamScope event_scope(context, nullptr, &params);
1044 
1045   const char test[] = {"xfa.event.change = \"changed\""};
1046   EXPECT_TRUE(Execute(test));
1047   EXPECT_EQ(L"changed", params.m_wsChange);
1048 }
1049 
1050 TEST_F(CFXJSE_FormCalcContextEmbedderTest, SetXFAEventFullTextFails) {
1051   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1052 
1053   CXFA_EventParam params;
1054   params.m_wsFullText = L"Original Full Text";
1055 
1056   CFXJSE_Engine* context = GetScriptContext();
1057   CFXJSE_Engine::EventParamScope event_scope(context, nullptr, &params);
1058 
1059   const char test[] = {"xfa.event.fullText = \"Changed Full Text\""};
1060   EXPECT_TRUE(Execute(test));
1061   EXPECT_EQ(L"Original Full Text", params.m_wsFullText);
1062 }
1063 
1064 TEST_F(CFXJSE_FormCalcContextEmbedderTest, EventChangeSelection) {
1065   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1066 
1067   CXFA_EventParam params;
1068   params.m_wsPrevText = L"1234";
1069   params.m_iSelStart = 1;
1070   params.m_iSelEnd = 3;
1071 
1072   CFXJSE_Engine* context = GetScriptContext();
1073   CFXJSE_Engine::EventParamScope event_scope(context, nullptr, &params);
1074 
1075   // Moving end to start works fine.
1076   EXPECT_TRUE(Execute("xfa.event.selEnd = \"1\""));
1077   EXPECT_EQ(1, params.m_iSelStart);
1078   EXPECT_EQ(1, params.m_iSelEnd);
1079 
1080   // Moving end before end, forces start to move in response.
1081   EXPECT_TRUE(Execute("xfa.event.selEnd = \"0\""));
1082   EXPECT_EQ(0, params.m_iSelStart);
1083   EXPECT_EQ(0, params.m_iSelEnd);
1084 
1085   // Negatives not allowed
1086   EXPECT_TRUE(Execute("xfa.event.selEnd = \"-1\""));
1087   EXPECT_EQ(0, params.m_iSelStart);
1088   EXPECT_EQ(0, params.m_iSelEnd);
1089 
1090   // Negatives not allowed
1091   EXPECT_TRUE(Execute("xfa.event.selStart = \"-1\""));
1092   EXPECT_EQ(0, params.m_iSelStart);
1093   EXPECT_EQ(0, params.m_iSelEnd);
1094 
1095   params.m_iSelEnd = 1;
1096 
1097   // Moving start to end works fine.
1098   EXPECT_TRUE(Execute("xfa.event.selStart = \"1\""));
1099   EXPECT_EQ(1, params.m_iSelStart);
1100   EXPECT_EQ(1, params.m_iSelEnd);
1101 
1102   // Moving start after end moves end.
1103   EXPECT_TRUE(Execute("xfa.event.selStart = \"2\""));
1104   EXPECT_EQ(2, params.m_iSelStart);
1105   EXPECT_EQ(2, params.m_iSelEnd);
1106 
1107   // Setting End past end of string clamps to string length;
1108   EXPECT_TRUE(Execute("xfa.event.selEnd = \"20\""));
1109   EXPECT_EQ(2, params.m_iSelStart);
1110   EXPECT_EQ(4, params.m_iSelEnd);
1111 
1112   // Setting Start past end of string clamps to string length;
1113   EXPECT_TRUE(Execute("xfa.event.selStart = \"20\""));
1114   EXPECT_EQ(4, params.m_iSelStart);
1115   EXPECT_EQ(4, params.m_iSelEnd);
1116 }
1117 
1118 TEST_F(CFXJSE_FormCalcContextEmbedderTest, XFAEventCancelAction) {
1119   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1120 
1121   CXFA_EventParam params;
1122   params.m_bCancelAction = false;
1123 
1124   CFXJSE_Engine* context = GetScriptContext();
1125   CFXJSE_Engine::EventParamScope event_scope(context, nullptr, &params);
1126   ExecuteExpectBool("xfa.event.cancelAction", false);
1127   EXPECT_TRUE(Execute("xfa.event.cancelAction = \"true\""));
1128   EXPECT_TRUE(params.m_bCancelAction);
1129 }
1130 
1131 TEST_F(CFXJSE_FormCalcContextEmbedderTest, ComplexTextChangeEvent) {
1132   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1133 
1134   CXFA_EventParam params;
1135   params.m_wsChange = L"g";
1136   params.m_wsPrevText = L"abcd";
1137   params.m_iSelStart = 1;
1138   params.m_iSelEnd = 3;
1139 
1140   CFXJSE_Engine* context = GetScriptContext();
1141   CFXJSE_Engine::EventParamScope event_scope(context, nullptr, &params);
1142 
1143   EXPECT_EQ(L"abcd", params.m_wsPrevText);
1144   EXPECT_EQ(L"agd", params.GetNewText());
1145   EXPECT_EQ(L"g", params.m_wsChange);
1146   EXPECT_EQ(1, params.m_iSelStart);
1147   EXPECT_EQ(3, params.m_iSelEnd);
1148 
1149   const char change_event[] = {"xfa.event.change = \"xyz\""};
1150   EXPECT_TRUE(Execute(change_event));
1151 
1152   EXPECT_EQ(L"abcd", params.m_wsPrevText);
1153   EXPECT_EQ(L"xyz", params.m_wsChange);
1154   EXPECT_EQ(L"axyzd", params.GetNewText());
1155   EXPECT_EQ(1, params.m_iSelStart);
1156   EXPECT_EQ(3, params.m_iSelEnd);
1157 
1158   const char sel_event[] = {"xfa.event.selEnd = \"1\""};
1159   EXPECT_TRUE(Execute(sel_event));
1160 
1161   EXPECT_EQ(L"abcd", params.m_wsPrevText);
1162   EXPECT_EQ(L"xyz", params.m_wsChange);
1163   EXPECT_EQ(L"axyzbcd", params.GetNewText());
1164   EXPECT_EQ(1, params.m_iSelStart);
1165   EXPECT_EQ(1, params.m_iSelEnd);
1166 }
1167 
1168 // Should not crash.
1169 TEST_F(CFXJSE_FormCalcContextEmbedderTest, BUG_1223) {
1170   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1171   EXPECT_TRUE(Execute("!.somExpression=0"));
1172 }
1173