Home | History | Annotate | Download | only in fm2js
      1 // Copyright 2016 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 "xfa/fxfa/fm2js/cxfa_fmlexer.h"
      6 
      7 #include <vector>
      8 
      9 #include "testing/gtest/include/gtest/gtest.h"
     10 #include "testing/test_support.h"
     11 #include "third_party/base/ptr_util.h"
     12 
     13 TEST(CXFA_FMLexerTest, EmptyString) {
     14   CXFA_FMLexer lexer(L"");
     15   std::unique_ptr<CXFA_FMToken> token = lexer.NextToken();
     16   EXPECT_EQ(TOKeof, token->m_type);
     17 }
     18 
     19 TEST(CXFA_FMLexerTest, Numbers) {
     20   auto lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"-12");
     21   std::unique_ptr<CXFA_FMToken> token = lexer->NextToken();
     22   // TODO(dsinclair): Should this return -12 instead of two tokens?
     23   EXPECT_EQ(TOKminus, token->m_type);
     24   token = lexer->NextToken();
     25   EXPECT_EQ(L"12", token->m_string);
     26   token = lexer->NextToken();
     27   EXPECT_EQ(TOKeof, token->m_type);
     28 
     29   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"1.5362");
     30   token = lexer->NextToken();
     31   EXPECT_EQ(TOKnumber, token->m_type);
     32   EXPECT_EQ(L"1.5362", token->m_string);
     33 
     34   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"0.875");
     35   token = lexer->NextToken();
     36   EXPECT_EQ(TOKnumber, token->m_type);
     37   EXPECT_EQ(L"0.875", token->m_string);
     38 
     39   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"5.56e-2");
     40   token = lexer->NextToken();
     41   EXPECT_EQ(TOKnumber, token->m_type);
     42   EXPECT_EQ(L"5.56e-2", token->m_string);
     43 
     44   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"1.234E10");
     45   token = lexer->NextToken();
     46   EXPECT_EQ(TOKnumber, token->m_type);
     47   EXPECT_EQ(L"1.234E10", token->m_string);
     48 
     49   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"123456789.012345678");
     50   token = lexer->NextToken();
     51   EXPECT_EQ(TOKnumber, token->m_type);
     52   // TODO(dsinclair): This should round as per IEEE 64-bit values.
     53   // EXPECT_EQ(L"123456789.01234567", token->m_string);
     54   EXPECT_EQ(L"123456789.012345678", token->m_string);
     55 
     56   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"99999999999999999");
     57   token = lexer->NextToken();
     58   EXPECT_EQ(TOKnumber, token->m_type);
     59   // TODO(dsinclair): This is spec'd as rounding when > 16 significant digits
     60   // prior to the exponent.
     61   // EXPECT_EQ(L"100000000000000000", token->m_string);
     62   EXPECT_EQ(L"99999999999999999", token->m_string);
     63 }
     64 
     65 // The quotes are stripped in CXFA_FMStringExpression::ToJavaScript.
     66 TEST(CXFA_FMLexerTest, Strings) {
     67   auto lexer =
     68       pdfium::MakeUnique<CXFA_FMLexer>(L"\"The cat jumped over the fence.\"");
     69   std::unique_ptr<CXFA_FMToken> token = lexer->NextToken();
     70   EXPECT_EQ(TOKstring, token->m_type);
     71   EXPECT_EQ(L"\"The cat jumped over the fence.\"", token->m_string);
     72 
     73   token = lexer->NextToken();
     74   EXPECT_EQ(TOKeof, token->m_type);
     75 
     76   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"\"\"");
     77   token = lexer->NextToken();
     78   EXPECT_EQ(TOKstring, token->m_type);
     79   EXPECT_EQ(L"\"\"", token->m_string);
     80 
     81   lexer = pdfium::MakeUnique<CXFA_FMLexer>(
     82       L"\"The message reads: \"\"Warning: Insufficient Memory\"\"\"");
     83   token = lexer->NextToken();
     84   EXPECT_EQ(TOKstring, token->m_type);
     85   EXPECT_EQ(L"\"The message reads: \"\"Warning: Insufficient Memory\"\"\"",
     86             token->m_string);
     87 
     88   lexer = pdfium::MakeUnique<CXFA_FMLexer>(
     89       L"\"\\u0047\\u006f\\u0066\\u0069\\u0073\\u0068\\u0021\\u000d\\u000a\"");
     90   token = lexer->NextToken();
     91   EXPECT_EQ(TOKstring, token->m_type);
     92   EXPECT_EQ(
     93       L"\"\\u0047\\u006f\\u0066\\u0069\\u0073\\u0068\\u0021\\u000d\\u000a\"",
     94       token->m_string);
     95 }
     96 
     97 // Note, 'this' is a keyword but is not matched by the lexer.
     98 TEST(CXFA_FMLexerTest, OperatorsAndKeywords) {
     99   struct {
    100     const wchar_t* op;
    101     XFA_FM_TOKEN token;
    102   } op[] = {{L"+", TOKplus},
    103             {L"/", TOKdiv},
    104             {L"-", TOKminus},
    105             {L"&", TOKand},
    106             {L"|", TOKor},
    107             {L"*", TOKmul},
    108             {L"<", TOKlt},
    109             {L">", TOKgt},
    110             {L"==", TOKeq},
    111             {L"<>", TOKne},
    112             {L"<=", TOKle},
    113             {L">=", TOKge},
    114             {L"and", TOKksand},
    115             {L"break", TOKbreak},
    116             {L"continue", TOKcontinue},
    117             {L"do", TOKdo},
    118             {L"downto", TOKdownto},
    119             {L"else", TOKelse},
    120             {L"elseif", TOKelseif},
    121             {L"end", TOKend},
    122             {L"endfor", TOKendfor},
    123             {L"endfunc", TOKendfunc},
    124             {L"endif", TOKendif},
    125             {L"endwhile", TOKendwhile},
    126             {L"eq", TOKkseq},
    127             {L"exit", TOKexit},
    128             {L"for", TOKfor},
    129             {L"foreach", TOKforeach},
    130             {L"func", TOKfunc},
    131             {L"ge", TOKksge},
    132             {L"gt", TOKksgt},
    133             {L"if", TOKif},
    134             {L"in", TOKin},
    135             {L"infinity", TOKinfinity},
    136             {L"le", TOKksle},
    137             {L"lt", TOKkslt},
    138             {L"nan", TOKnan},
    139             {L"ne", TOKksne},
    140             {L"not", TOKksnot},
    141             {L"null", TOKnull},
    142             {L"or", TOKksor},
    143             {L"return", TOKreturn},
    144             {L"step", TOKstep},
    145             {L"then", TOKthen},
    146             {L"throw", TOKthrow},
    147             {L"upto", TOKupto},
    148             {L"var", TOKvar},
    149             {L"while", TOKwhile},
    150 
    151             // The following are defined but aren't in the spec.
    152             {L"(", TOKlparen},
    153             {L")", TOKrparen},
    154             {L",", TOKcomma},
    155             {L".", TOKdot},
    156             {L"[", TOKlbracket},
    157             {L"]", TOKrbracket},
    158             {L"..", TOKdotdot},
    159             {L".#", TOKdotscream},
    160             {L".*", TOKdotstar}};
    161 
    162   for (size_t i = 0; i < FX_ArraySize(op); ++i) {
    163     auto lexer = pdfium::MakeUnique<CXFA_FMLexer>(op[i].op);
    164     std::unique_ptr<CXFA_FMToken> token = lexer->NextToken();
    165     EXPECT_EQ(op[i].token, token->m_type);
    166   }
    167 }
    168 
    169 TEST(CXFA_FMLexerTest, Comments) {
    170   auto lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"// Empty.");
    171   std::unique_ptr<CXFA_FMToken> token = lexer->NextToken();
    172   EXPECT_EQ(TOKeof, token->m_type);
    173 
    174   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"//");
    175   token = lexer->NextToken();
    176   EXPECT_EQ(TOKeof, token->m_type);
    177 
    178   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"123 // Empty.\n\"str\"");
    179   token = lexer->NextToken();
    180   EXPECT_EQ(TOKnumber, token->m_type);
    181   EXPECT_EQ(L"123", token->m_string);
    182 
    183   token = lexer->NextToken();
    184   EXPECT_EQ(TOKstring, token->m_type);
    185   EXPECT_EQ(L"\"str\"", token->m_string);
    186 
    187   token = lexer->NextToken();
    188   EXPECT_EQ(TOKeof, token->m_type);
    189 
    190   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L";");
    191   token = lexer->NextToken();
    192   EXPECT_EQ(TOKeof, token->m_type);
    193 
    194   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"; Empty.");
    195   token = lexer->NextToken();
    196   EXPECT_EQ(TOKeof, token->m_type);
    197 
    198   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"123 ;Empty.\n\"str\"");
    199   token = lexer->NextToken();
    200   EXPECT_EQ(TOKnumber, token->m_type);
    201   EXPECT_EQ(L"123", token->m_string);
    202 
    203   token = lexer->NextToken();
    204   EXPECT_EQ(TOKstring, token->m_type);
    205   EXPECT_EQ(L"\"str\"", token->m_string);
    206 
    207   token = lexer->NextToken();
    208   EXPECT_EQ(TOKeof, token->m_type);
    209 }
    210 
    211 TEST(CXFA_FMLexerTest, ValidIdentifiers) {
    212   std::vector<const wchar_t*> identifiers = {
    213       L"a", L"an_identifier", L"_ident", L"$ident", L"!ident", L"GetAddr"};
    214   for (const auto* ident : identifiers) {
    215     auto lexer = pdfium::MakeUnique<CXFA_FMLexer>(ident);
    216     std::unique_ptr<CXFA_FMToken> token = lexer->NextToken();
    217     EXPECT_EQ(TOKidentifier, token->m_type);
    218     EXPECT_EQ(ident, token->m_string);
    219   }
    220 }
    221 
    222 TEST(CXFA_FMLexerTest, InvalidIdentifiers) {
    223   auto lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"#a");
    224   EXPECT_EQ(nullptr, lexer->NextToken());
    225 
    226   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"1a");
    227   EXPECT_EQ(nullptr, lexer->NextToken());
    228 
    229   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"an@identifier");
    230   EXPECT_NE(nullptr, lexer->NextToken());
    231   EXPECT_EQ(nullptr, lexer->NextToken());
    232   EXPECT_EQ(nullptr, lexer->NextToken());
    233 
    234   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"_ident@");
    235   EXPECT_NE(nullptr, lexer->NextToken());
    236   EXPECT_EQ(nullptr, lexer->NextToken());
    237 }
    238 
    239 TEST(CXFA_FMLexerTest, Whitespace) {
    240   auto lexer = pdfium::MakeUnique<CXFA_FMLexer>(L" \t\xc\x9\xb");
    241   std::unique_ptr<CXFA_FMToken> token = lexer->NextToken();
    242   EXPECT_EQ(TOKeof, token->m_type);
    243 
    244   lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"123 \t\xc\x9\xb 456");
    245   token = lexer->NextToken();
    246   EXPECT_EQ(TOKnumber, token->m_type);
    247   EXPECT_EQ(L"123", token->m_string);
    248 
    249   token = lexer->NextToken();
    250   EXPECT_EQ(TOKnumber, token->m_type);
    251   EXPECT_EQ(L"456", token->m_string);
    252 
    253   token = lexer->NextToken();
    254   EXPECT_EQ(TOKeof, token->m_type);
    255 }
    256