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