1 // Copyright 2015 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 <cmath>
6 #include <vector>
7 
8 #include "core/fxcrt/fx_string.h"
9 #include "fpdfsdk/cpdfsdk_helpers.h"
10 #include "fxjs/cjs_event_context.h"
11 #include "fxjs/cjs_publicmethods.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "testing/js_embedder_test.h"
14 
15 namespace {
16 
RoundDownDate(double date)17 double RoundDownDate(double date) {
18   return date - fmod(date, 86400000);
19 }
20 
21 }  // namespace
22 
23 class CJS_PublicMethodsEmbedderTest : public JSEmbedderTest {};
24 
TEST_F(CJS_PublicMethodsEmbedderTest,ParseDateUsingFormat)25 TEST_F(CJS_PublicMethodsEmbedderTest, ParseDateUsingFormat) {
26   v8::Isolate::Scope isolate_scope(isolate());
27   v8::HandleScope handle_scope(isolate());
28   v8::Context::Scope context_scope(GetV8Context());
29   bool bWrongFormat;
30   double date;
31 
32   // 1968
33   bWrongFormat = false;
34   date = CJS_PublicMethods::ParseDateUsingFormat(L"06/25/1968", L"mm/dd/yyyy",
35                                                  &bWrongFormat);
36   date = RoundDownDate(date);
37   EXPECT_DOUBLE_EQ(-47865600000, date);
38   EXPECT_FALSE(bWrongFormat);
39 
40   // 1968
41   bWrongFormat = false;
42   date = CJS_PublicMethods::ParseDateUsingFormat(L"25061968", L"ddmmyyyy",
43                                                  &bWrongFormat);
44   date = RoundDownDate(date);
45   EXPECT_DOUBLE_EQ(-47865600000, date);
46   EXPECT_FALSE(bWrongFormat);
47 
48   // 1968
49   bWrongFormat = false;
50   date = CJS_PublicMethods::ParseDateUsingFormat(L"19680625", L"yyyymmdd",
51                                                  &bWrongFormat);
52   date = RoundDownDate(date);
53   EXPECT_DOUBLE_EQ(-47865600000, date);
54   EXPECT_FALSE(bWrongFormat);
55 
56   // 1985
57   bWrongFormat = false;
58   date = CJS_PublicMethods::ParseDateUsingFormat(L"31121985", L"ddmmyyyy",
59                                                  &bWrongFormat);
60   date = RoundDownDate(date);
61   EXPECT_DOUBLE_EQ(504835200000.0, date);
62   EXPECT_FALSE(bWrongFormat);
63 
64   // 2085, the other '85.
65   bWrongFormat = false;
66   date = CJS_PublicMethods::ParseDateUsingFormat(L"311285", L"ddmmyy",
67                                                  &bWrongFormat);
68   date = RoundDownDate(date);
69   EXPECT_DOUBLE_EQ(3660595200000.0, date);
70   EXPECT_FALSE(bWrongFormat);
71 
72   // 1995
73   bWrongFormat = false;
74   date = CJS_PublicMethods::ParseDateUsingFormat(L"01021995", L"ddmmyyyy",
75                                                  &bWrongFormat);
76   date = RoundDownDate(date);
77   EXPECT_DOUBLE_EQ(791596800000.0, date);
78   EXPECT_FALSE(bWrongFormat);
79 
80   // 2095, the other '95.
81   bWrongFormat = false;
82   date = CJS_PublicMethods::ParseDateUsingFormat(L"010295", L"ddmmyy",
83                                                  &bWrongFormat);
84   date = RoundDownDate(date);
85   EXPECT_DOUBLE_EQ(3947356800000.0, date);
86   EXPECT_FALSE(bWrongFormat);
87 
88   // 2005
89   bWrongFormat = false;
90   date = CJS_PublicMethods::ParseDateUsingFormat(L"01022005", L"ddmmyyyy",
91                                                  &bWrongFormat);
92   date = RoundDownDate(date);
93   EXPECT_DOUBLE_EQ(1107216000000.0, date);
94   EXPECT_FALSE(bWrongFormat);
95 
96   // 2005
97   bWrongFormat = false;
98   date = CJS_PublicMethods::ParseDateUsingFormat(L"010205", L"ddmmyy",
99                                                  &bWrongFormat);
100   date = RoundDownDate(date);
101   EXPECT_DOUBLE_EQ(1107216000000.0, date);
102   EXPECT_FALSE(bWrongFormat);
103 
104   // 2005 in a different format. https://crbug.com/436572
105   bWrongFormat = false;
106   date = CJS_PublicMethods::ParseDateUsingFormat(L"050201", L"yymmdd",
107                                                  &bWrongFormat);
108   date = RoundDownDate(date);
109   EXPECT_DOUBLE_EQ(1107216000000.0, date);
110   EXPECT_FALSE(bWrongFormat);
111 }
112 
TEST_F(CJS_PublicMethodsEmbedderTest,PrintDateUsingFormat)113 TEST_F(CJS_PublicMethodsEmbedderTest, PrintDateUsingFormat) {
114   v8::Isolate::Scope isolate_scope(isolate());
115   v8::HandleScope handle_scope(isolate());
116   v8::Context::Scope context_scope(GetV8Context());
117   WideString formatted_date;
118 
119   // 1968-06-25
120   formatted_date =
121       CJS_PublicMethods::PrintDateUsingFormat(-47952000000, L"ddmmyy");
122   EXPECT_STREQ(L"250668", formatted_date.c_str());
123   formatted_date =
124       CJS_PublicMethods::PrintDateUsingFormat(-47952000000, L"yy/mm/dd");
125   EXPECT_STREQ(L"68/06/25", formatted_date.c_str());
126 
127   // 1969-12-31
128   formatted_date = CJS_PublicMethods::PrintDateUsingFormat(-0.0001, L"ddmmyy");
129   EXPECT_STREQ(L"311269", formatted_date.c_str());
130   formatted_date = CJS_PublicMethods::PrintDateUsingFormat(-0.0001, L"yy!mmdd");
131   EXPECT_STREQ(L"69!1231", formatted_date.c_str());
132 
133   // 1970-01-01
134   formatted_date = CJS_PublicMethods::PrintDateUsingFormat(0, L"ddmmyy");
135   EXPECT_STREQ(L"010170", formatted_date.c_str());
136   formatted_date = CJS_PublicMethods::PrintDateUsingFormat(0, L"mm-yyyy-dd");
137   EXPECT_STREQ(L"01-1970-01", formatted_date.c_str());
138 
139   // 1985-12-31
140   formatted_date =
141       CJS_PublicMethods::PrintDateUsingFormat(504835200000.0, L"ddmmyy");
142   EXPECT_STREQ(L"311285", formatted_date.c_str());
143   formatted_date =
144       CJS_PublicMethods::PrintDateUsingFormat(504835200000.0, L"yymmdd");
145   EXPECT_STREQ(L"851231", formatted_date.c_str());
146 
147   // 1995-02-01
148   formatted_date =
149       CJS_PublicMethods::PrintDateUsingFormat(791596800000.0, L"ddmmyy");
150   EXPECT_STREQ(L"010295", formatted_date.c_str());
151   formatted_date =
152       CJS_PublicMethods::PrintDateUsingFormat(791596800000.0, L"yyyymmdd");
153   EXPECT_STREQ(L"19950201", formatted_date.c_str());
154 
155   // 2005-02-01
156   formatted_date =
157       CJS_PublicMethods::PrintDateUsingFormat(1107216000000.0, L"ddmmyy");
158   EXPECT_STREQ(L"010205", formatted_date.c_str());
159   formatted_date =
160       CJS_PublicMethods::PrintDateUsingFormat(1107216000000.0, L"yyyyddmm");
161   EXPECT_STREQ(L"20050102", formatted_date.c_str());
162 
163   // 2085-12-31
164   formatted_date =
165       CJS_PublicMethods::PrintDateUsingFormat(3660595200000.0, L"ddmmyy");
166   EXPECT_STREQ(L"311285", formatted_date.c_str());
167   formatted_date =
168       CJS_PublicMethods::PrintDateUsingFormat(3660595200000.0, L"yyyydd");
169   EXPECT_STREQ(L"208531", formatted_date.c_str());
170 
171   // 2095-02-01
172   formatted_date =
173       CJS_PublicMethods::PrintDateUsingFormat(3947356800000.0, L"ddmmyy");
174   EXPECT_STREQ(L"010295", formatted_date.c_str());
175   formatted_date =
176       CJS_PublicMethods::PrintDateUsingFormat(3947356800000.0, L"mmddyyyy");
177   EXPECT_STREQ(L"02012095", formatted_date.c_str());
178 }
179 
TEST_F(CJS_PublicMethodsEmbedderTest,AFSimple_CalculateSum)180 TEST_F(CJS_PublicMethodsEmbedderTest, AFSimple_CalculateSum) {
181   v8::Isolate::Scope isolate_scope(isolate());
182   v8::HandleScope handle_scope(isolate());
183   v8::Context::Scope context_scope(GetV8Context());
184 
185   EXPECT_TRUE(OpenDocument("calculate.pdf"));
186   auto* page = LoadPage(0);
187   ASSERT_TRUE(page);
188 
189   CJS_Runtime runtime(
190       CPDFSDKFormFillEnvironmentFromFPDFFormHandle(form_handle()));
191   runtime.NewEventContext();
192 
193   WideString result;
194   runtime.GetCurrentEventContext()->GetEventRecorder()->SetValueForTest(
195       &result);
196 
197   auto ary = runtime.NewArray();
198   runtime.PutArrayElement(ary, 0, runtime.NewString("Calc1_A"));
199   runtime.PutArrayElement(ary, 1, runtime.NewString("Calc1_B"));
200 
201   std::vector<v8::Local<v8::Value>> params;
202   params.push_back(runtime.NewString("SUM"));
203   params.push_back(ary);
204 
205   CJS_Result ret = CJS_PublicMethods::AFSimple_Calculate(&runtime, params);
206   UnloadPage(page);
207 
208   runtime.GetCurrentEventContext()->GetEventRecorder()->SetValueForTest(
209       nullptr);
210 
211   ASSERT_TRUE(!ret.HasError());
212   ASSERT_TRUE(!ret.HasReturn());
213   ASSERT_EQ(L"7", result);
214 }
215 
TEST_F(CJS_PublicMethodsEmbedderTest,AFNumber_Keystroke)216 TEST_F(CJS_PublicMethodsEmbedderTest, AFNumber_Keystroke) {
217   v8::Isolate::Scope isolate_scope(isolate());
218   v8::HandleScope handle_scope(isolate());
219   v8::Context::Scope context_scope(GetV8Context());
220 
221   EXPECT_TRUE(OpenDocument("calculate.pdf"));
222   auto* page = LoadPage(0);
223   ASSERT_TRUE(page);
224 
225   CJS_Runtime runtime(
226       CPDFSDKFormFillEnvironmentFromFPDFFormHandle(form_handle()));
227   runtime.NewEventContext();
228 
229   auto* handler = runtime.GetCurrentEventContext()->GetEventRecorder();
230 
231   bool valid = true;
232   WideString result = L"-10";
233   WideString change = L"";
234 
235   handler->SetValueForTest(&result);
236   handler->SetRCForTest(&valid);
237   handler->SetStrChangeForTest(&change);
238 
239   handler->ResetWillCommitForTest();
240   handler->SetSelStart(0);
241   handler->SetSelEnd(0);
242 
243   std::vector<v8::Local<v8::Value>> params;
244   params.push_back(runtime.NewString("-10"));
245   params.push_back(runtime.NewString(""));
246 
247   CJS_Result ret = CJS_PublicMethods::AFNumber_Keystroke(&runtime, params);
248   EXPECT_TRUE(valid);
249   EXPECT_TRUE(!ret.HasError());
250   EXPECT_TRUE(!ret.HasReturn());
251 
252   UnloadPage(page);
253 
254   // Keep the *SAN bots happy. One of these is an UnownedPtr, another seems to
255   // used during destruction. Clear them all to be safe and consistent.
256   handler->SetValueForTest(nullptr);
257   handler->SetRCForTest(nullptr);
258   handler->SetStrChangeForTest(nullptr);
259 }
260