LCOV - code coverage report
Current view: top level - test/unittests/asmjs - asm-scanner-unittest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 240 240 100.0 %
Date: 2019-02-19 Functions: 41 58 70.7 %

          Line data    Source code
       1             : // Copyright 2017 the V8 project 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 "src/asmjs/asm-scanner.h"
       6             : #include "src/objects.h"
       7             : #include "src/parsing/scanner-character-streams.h"
       8             : #include "src/parsing/scanner.h"
       9             : #include "testing/gtest/include/gtest/gtest.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : 
      14             : #define TOK(t) AsmJsScanner::kToken_##t
      15             : 
      16          48 : class AsmJsScannerTest : public ::testing::Test {
      17             :  protected:
      18          16 :   void SetupScanner(const char* source) {
      19          32 :     stream = ScannerStream::ForTesting(source);
      20          16 :     scanner.reset(new AsmJsScanner(stream.get()));
      21          16 :   }
      22             : 
      23         109 :   void Skip(AsmJsScanner::token_t t) {
      24         109 :     CHECK_EQ(t, scanner->Token());
      25         109 :     scanner->Next();
      26         109 :   }
      27             : 
      28           3 :   void SkipGlobal() {
      29           3 :     CHECK(scanner->IsGlobal());
      30           3 :     scanner->Next();
      31           3 :   }
      32             : 
      33           1 :   void SkipLocal() {
      34           1 :     CHECK(scanner->IsLocal());
      35           1 :     scanner->Next();
      36           1 :   }
      37             : 
      38          26 :   void CheckForEnd() { CHECK_EQ(scanner->Token(), AsmJsScanner::kEndOfInput); }
      39             : 
      40           3 :   void CheckForParseError() {
      41           3 :     CHECK_EQ(scanner->Token(), AsmJsScanner::kParseError);
      42           3 :   }
      43             : 
      44             :   std::unique_ptr<Utf16CharacterStream> stream;
      45             :   std::unique_ptr<AsmJsScanner> scanner;
      46             : };
      47             : 
      48       15188 : TEST_F(AsmJsScannerTest, SimpleFunction) {
      49           1 :   SetupScanner("function foo() { return; }");
      50           1 :   Skip(TOK(function));
      51             :   DCHECK_EQ("foo", scanner->GetIdentifierString());
      52           1 :   SkipGlobal();
      53           1 :   Skip('(');
      54           1 :   Skip(')');
      55           1 :   Skip('{');
      56             :   // clang-format off
      57           1 :   Skip(TOK(return));
      58             :   // clang-format on
      59           1 :   Skip(';');
      60           1 :   Skip('}');
      61           1 :   CheckForEnd();
      62           1 : }
      63             : 
      64       15188 : TEST_F(AsmJsScannerTest, JSKeywords) {
      65             :   SetupScanner(
      66             :       "arguments break case const continue\n"
      67             :       "default do else eval for function\n"
      68           1 :       "if new return switch var while\n");
      69           1 :   Skip(TOK(arguments));
      70           1 :   Skip(TOK(break));
      71           1 :   Skip(TOK(case));
      72           1 :   Skip(TOK(const));
      73           1 :   Skip(TOK(continue));
      74           1 :   Skip(TOK(default));
      75           1 :   Skip(TOK(do));
      76           1 :   Skip(TOK(else));
      77           1 :   Skip(TOK(eval));
      78           1 :   Skip(TOK(for));
      79           1 :   Skip(TOK(function));
      80           1 :   Skip(TOK(if));
      81           1 :   Skip(TOK(new));
      82             :   // clang-format off
      83           1 :   Skip(TOK(return));
      84             :   // clang-format on
      85           1 :   Skip(TOK(switch));
      86           1 :   Skip(TOK(var));
      87           1 :   Skip(TOK(while));
      88           1 :   CheckForEnd();
      89           1 : }
      90             : 
      91       15188 : TEST_F(AsmJsScannerTest, JSOperatorsSpread) {
      92             :   SetupScanner(
      93             :       "+ - * / % & | ^ ~ << >> >>>\n"
      94           1 :       "< > <= >= == !=\n");
      95           1 :   Skip('+');
      96           1 :   Skip('-');
      97           1 :   Skip('*');
      98           1 :   Skip('/');
      99           1 :   Skip('%');
     100           1 :   Skip('&');
     101           1 :   Skip('|');
     102           1 :   Skip('^');
     103           1 :   Skip('~');
     104           1 :   Skip(TOK(SHL));
     105           1 :   Skip(TOK(SAR));
     106           1 :   Skip(TOK(SHR));
     107           1 :   Skip('<');
     108           1 :   Skip('>');
     109           1 :   Skip(TOK(LE));
     110           1 :   Skip(TOK(GE));
     111           1 :   Skip(TOK(EQ));
     112           1 :   Skip(TOK(NE));
     113           1 :   CheckForEnd();
     114           1 : }
     115             : 
     116       15188 : TEST_F(AsmJsScannerTest, JSOperatorsTight) {
     117             :   SetupScanner(
     118             :       "+-*/%&|^~<<>> >>>\n"
     119           1 :       "<><=>= ==!=\n");
     120           1 :   Skip('+');
     121           1 :   Skip('-');
     122           1 :   Skip('*');
     123           1 :   Skip('/');
     124           1 :   Skip('%');
     125           1 :   Skip('&');
     126           1 :   Skip('|');
     127           1 :   Skip('^');
     128           1 :   Skip('~');
     129           1 :   Skip(TOK(SHL));
     130           1 :   Skip(TOK(SAR));
     131           1 :   Skip(TOK(SHR));
     132           1 :   Skip('<');
     133           1 :   Skip('>');
     134           1 :   Skip(TOK(LE));
     135           1 :   Skip(TOK(GE));
     136           1 :   Skip(TOK(EQ));
     137           1 :   Skip(TOK(NE));
     138           1 :   CheckForEnd();
     139           1 : }
     140             : 
     141       15188 : TEST_F(AsmJsScannerTest, UsesOfAsm) {
     142           1 :   SetupScanner("'use asm' \"use asm\"\n");
     143           1 :   Skip(TOK(UseAsm));
     144           1 :   Skip(TOK(UseAsm));
     145           1 :   CheckForEnd();
     146           1 : }
     147             : 
     148       15188 : TEST_F(AsmJsScannerTest, DefaultGlobalScope) {
     149           1 :   SetupScanner("var x = x + x;");
     150           1 :   Skip(TOK(var));
     151           2 :   CHECK_EQ("x", scanner->GetIdentifierString());
     152           1 :   AsmJsScanner::token_t x = scanner->Token();
     153           1 :   SkipGlobal();
     154           1 :   Skip('=');
     155           1 :   Skip(x);
     156           1 :   Skip('+');
     157           1 :   Skip(x);
     158           1 :   Skip(';');
     159           1 :   CheckForEnd();
     160           1 : }
     161             : 
     162       15188 : TEST_F(AsmJsScannerTest, GlobalScope) {
     163           1 :   SetupScanner("var x = x + x;");
     164             :   scanner->EnterGlobalScope();
     165           1 :   Skip(TOK(var));
     166           2 :   CHECK_EQ("x", scanner->GetIdentifierString());
     167           1 :   AsmJsScanner::token_t x = scanner->Token();
     168           1 :   SkipGlobal();
     169           1 :   Skip('=');
     170           1 :   Skip(x);
     171           1 :   Skip('+');
     172           1 :   Skip(x);
     173           1 :   Skip(';');
     174           1 :   CheckForEnd();
     175           1 : }
     176             : 
     177       15188 : TEST_F(AsmJsScannerTest, LocalScope) {
     178           1 :   SetupScanner("var x = x + x;");
     179             :   scanner->EnterLocalScope();
     180           1 :   Skip(TOK(var));
     181           2 :   CHECK_EQ("x", scanner->GetIdentifierString());
     182           1 :   AsmJsScanner::token_t x = scanner->Token();
     183           1 :   SkipLocal();
     184           1 :   Skip('=');
     185           1 :   Skip(x);
     186           1 :   Skip('+');
     187           1 :   Skip(x);
     188           1 :   Skip(';');
     189           1 :   CheckForEnd();
     190           1 : }
     191             : 
     192       15188 : TEST_F(AsmJsScannerTest, Numbers) {
     193           1 :   SetupScanner("1 1.2 0x1F 1.e3");
     194             : 
     195           1 :   CHECK(scanner->IsUnsigned());
     196           1 :   CHECK_EQ(1, scanner->AsUnsigned());
     197           1 :   scanner->Next();
     198             : 
     199           1 :   CHECK(scanner->IsDouble());
     200           1 :   CHECK_EQ(1.2, scanner->AsDouble());
     201           1 :   scanner->Next();
     202             : 
     203           1 :   CHECK(scanner->IsUnsigned());
     204           1 :   CHECK_EQ(31, scanner->AsUnsigned());
     205           1 :   scanner->Next();
     206             : 
     207           1 :   CHECK(scanner->IsDouble());
     208           1 :   CHECK_EQ(1.0e3, scanner->AsDouble());
     209           1 :   scanner->Next();
     210             : 
     211           1 :   CheckForEnd();
     212           1 : }
     213             : 
     214       15188 : TEST_F(AsmJsScannerTest, UnsignedNumbers) {
     215           1 :   SetupScanner("0x7FFFFFFF 0x80000000 0xFFFFFFFF 0x100000000");
     216             : 
     217           1 :   CHECK(scanner->IsUnsigned());
     218           1 :   CHECK_EQ(0x7FFFFFFF, scanner->AsUnsigned());
     219           1 :   scanner->Next();
     220             : 
     221           1 :   CHECK(scanner->IsUnsigned());
     222           1 :   CHECK_EQ(0x80000000, scanner->AsUnsigned());
     223           1 :   scanner->Next();
     224             : 
     225           1 :   CHECK(scanner->IsUnsigned());
     226           1 :   CHECK_EQ(0xFFFFFFFF, scanner->AsUnsigned());
     227           1 :   scanner->Next();
     228             : 
     229             :   // Numeric "unsigned" literals with a payload of more than 32-bit are rejected
     230             :   // by asm.js in all contexts, we hence consider `0x100000000` to be an error.
     231           1 :   CheckForParseError();
     232           1 : }
     233             : 
     234       15188 : TEST_F(AsmJsScannerTest, BadNumber) {
     235           1 :   SetupScanner(".123fe");
     236           1 :   Skip('.');
     237           1 :   CheckForParseError();
     238           1 : }
     239             : 
     240       15188 : TEST_F(AsmJsScannerTest, Rewind1) {
     241           1 :   SetupScanner("+ - * /");
     242           1 :   Skip('+');
     243           1 :   scanner->Rewind();
     244           1 :   Skip('+');
     245           1 :   Skip('-');
     246           1 :   scanner->Rewind();
     247           1 :   Skip('-');
     248           1 :   Skip('*');
     249           1 :   scanner->Rewind();
     250           1 :   Skip('*');
     251           1 :   Skip('/');
     252           1 :   scanner->Rewind();
     253           1 :   Skip('/');
     254           1 :   CheckForEnd();
     255           1 : }
     256             : 
     257       15188 : TEST_F(AsmJsScannerTest, Comments) {
     258             :   SetupScanner(
     259             :       "var // This is a test /* */ eval\n"
     260             :       "var /* test *** test */ eval\n"
     261           1 :       "function /* this */ ^");
     262           1 :   Skip(TOK(var));
     263           1 :   Skip(TOK(var));
     264           1 :   Skip(TOK(eval));
     265           1 :   Skip(TOK(function));
     266           1 :   Skip('^');
     267           1 :   CheckForEnd();
     268           1 : }
     269             : 
     270       15188 : TEST_F(AsmJsScannerTest, TrailingCComment) {
     271           1 :   SetupScanner("var /* test\n");
     272           1 :   Skip(TOK(var));
     273           1 :   CheckForParseError();
     274           1 : }
     275             : 
     276       15188 : TEST_F(AsmJsScannerTest, Seeking) {
     277           1 :   SetupScanner("var eval do arguments function break\n");
     278           1 :   Skip(TOK(var));
     279           1 :   size_t old_pos = scanner->Position();
     280           1 :   Skip(TOK(eval));
     281           1 :   Skip(TOK(do));
     282           1 :   Skip(TOK(arguments));
     283           1 :   scanner->Rewind();
     284           1 :   Skip(TOK(arguments));
     285           1 :   scanner->Rewind();
     286           1 :   scanner->Seek(old_pos);
     287           1 :   Skip(TOK(eval));
     288           1 :   Skip(TOK(do));
     289           1 :   Skip(TOK(arguments));
     290           1 :   Skip(TOK(function));
     291           1 :   Skip(TOK(break));
     292           1 :   CheckForEnd();
     293           1 : }
     294             : 
     295       15188 : TEST_F(AsmJsScannerTest, Newlines) {
     296             :   SetupScanner(
     297             :       "var x = 1\n"
     298           1 :       "var y = 2\n");
     299           1 :   Skip(TOK(var));
     300           1 :   scanner->Next();
     301           1 :   Skip('=');
     302           1 :   scanner->Next();
     303           1 :   CHECK(scanner->IsPrecededByNewline());
     304           1 :   Skip(TOK(var));
     305           1 :   scanner->Next();
     306           1 :   Skip('=');
     307           1 :   scanner->Next();
     308           1 :   CHECK(scanner->IsPrecededByNewline());
     309           1 :   CheckForEnd();
     310           1 : }
     311             : 
     312             : }  // namespace internal
     313        9111 : }  // namespace v8

Generated by: LCOV version 1.10