1// Copyright 2014 The Chromium 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 "config.h" 6#include "core/css/parser/MediaQueryTokenizer.h" 7 8#include "core/css/parser/MediaQueryBlockWatcher.h" 9#include "wtf/PassOwnPtr.h" 10#include <gtest/gtest.h> 11 12namespace WebCore { 13 14typedef struct { 15 const char* input; 16 const char* output; 17} TestCase; 18 19typedef struct { 20 const char* input; 21 const unsigned maxLevel; 22 const unsigned finalLevel; 23} BlockTestCase; 24 25TEST(MediaQueryTokenizerTest, Basic) 26{ 27 TestCase testCases[] = { 28 { "(max-width: 50px)", "(max-width: 50px)" }, 29 { "(max-width: 1e+2px)", "(max-width: 100px)" }, 30 { "(max-width: 1e2px)", "(max-width: 100px)" }, 31 { "(max-width: 1000e-1px)", "(max-width: 100px)" }, 32 { "(max-width: 50\\70\\78)", "(max-width: 50px)" }, 33 { "(max-width: /* comment */50px)", "(max-width: 50px)" }, 34 { "(max-width: /** *commen*t */60px)", "(max-width: 60px)" }, 35 { "(max-width: /** *commen*t **/70px)", "(max-width: 70px)" }, 36 { "(max-width: /** *commen*t **//**/80px)", "(max-width: 80px)" }, 37 { "(max-width: /*/ **/90px)", "(max-width: 90px)" }, 38 { "(max-width: /*/ **/*100px)", "(max-width: '*'100px)" }, 39 { "(max-width: 110px/*)", "(max-width: 110px" }, 40 { "(max-width: 120px)/*", "(max-width: 120px)" }, 41 { "(max-width: 130px)/**", "(max-width: 130px)" }, 42 { "(max-width: /***/140px)/**/", "(max-width: 140px)" }, 43 { "(max-width: '40px')", "(max-width: 40px)" }, 44 { "(max-width: '40px", "(max-width: 40px" }, 45 { "(max-width: '40px\n", "(max-width: " }, 46 { "(max-width: '40px\\", "(max-width: 40px" }, 47 { "(max-width: '40px\\\n", "(max-width: 40px" }, 48 { "(max-width: '40px\\\n')", "(max-width: 40px)" }, 49 { "(max-width: '40\\70\\78')", "(max-width: 40px)" }, 50 { "(max-width: '40\\\npx')", "(max-width: 40px)" }, 51 { "(max-aspect-ratio: 5)", "(max-aspect-ratio: 5)" }, 52 { "(max-aspect-ratio: +5)", "(max-aspect-ratio: 5)" }, 53 { "(max-aspect-ratio: -5)", "(max-aspect-ratio: -5)" }, 54 { "(max-aspect-ratio: -+5)", "(max-aspect-ratio: '-'5)" }, 55 { "(max-aspect-ratio: +-5)", "(max-aspect-ratio: '+'-5)" }, 56 { "(max-aspect-ratio: +bla5)", "(max-aspect-ratio: '+'bla5)" }, 57 { "(max-aspect-ratio: +5bla)", "(max-aspect-ratio: 5other)" }, 58 { "(max-aspect-ratio: -bla)", "(max-aspect-ratio: -bla)" }, 59 { "(max-aspect-ratio: --bla)", "(max-aspect-ratio: '-'-bla)" }, 60 { 0, 0 } // Do not remove the terminator line. 61 }; 62 63 for (int i = 0; testCases[i].input; ++i) { 64 Vector<MediaQueryToken> tokens; 65 MediaQueryTokenizer::tokenize(testCases[i].input, tokens); 66 StringBuilder output; 67 for (size_t j = 0; j < tokens.size(); ++j) 68 output.append(tokens[j].textForUnitTests()); 69 ASSERT_STREQ(testCases[i].output, output.toString().ascii().data()); 70 } 71} 72 73TEST(MediaQueryTokenizerBlockTest, Basic) 74{ 75 BlockTestCase testCases[] = { 76 {"(max-width: 800px()), (max-width: 800px)", 2, 0}, 77 {"(max-width: 900px(()), (max-width: 900px)", 3, 1}, 78 {"(max-width: 600px(())))), (max-width: 600px)", 3, 0}, 79 {"(max-width: 500px(((((((((())))), (max-width: 500px)", 11, 6}, 80 {"(max-width: 800px[]), (max-width: 800px)", 2, 0}, 81 {"(max-width: 900px[[]), (max-width: 900px)", 3, 2}, 82 {"(max-width: 600px[[]]]]), (max-width: 600px)", 3, 0}, 83 {"(max-width: 500px[[[[[[[[[[]]]]), (max-width: 500px)", 11, 7}, 84 {"(max-width: 800px{}), (max-width: 800px)", 2, 0}, 85 {"(max-width: 900px{{}), (max-width: 900px)", 3, 2}, 86 {"(max-width: 600px{{}}}}), (max-width: 600px)", 3, 0}, 87 {"(max-width: 500px{{{{{{{{{{}}}}), (max-width: 500px)", 11, 7}, 88 {"[(), (max-width: 400px)", 2, 1}, 89 {"[{}, (max-width: 500px)", 2, 1}, 90 {"[{]}], (max-width: 900px)", 2, 0}, 91 {"[{[]{}{{{}}}}], (max-width: 900px)", 5, 0}, 92 {"[{[}], (max-width: 900px)", 3, 2}, 93 {"[({)}], (max-width: 900px)", 3, 2}, 94 {"[]((), (max-width: 900px)", 2, 1}, 95 {"((), (max-width: 900px)", 2, 1}, 96 {"(foo(), (max-width: 900px)", 2, 1}, 97 {"[](()), (max-width: 900px)", 2, 0}, 98 {"all an[isdfs bla())(i())]icalc(i)(()), (max-width: 400px)", 3, 0}, 99 {"all an[isdfs bla())(]icalc(i)(()), (max-width: 500px)", 4, 2}, 100 {"all an[isdfs bla())(]icalc(i)(())), (max-width: 600px)", 4, 1}, 101 {"all an[isdfs bla())(]icalc(i)(()))], (max-width: 800px)", 4, 0}, 102 {0, 0, 0} // Do not remove the terminator line. 103 }; 104 for (int i = 0; testCases[i].input; ++i) { 105 Vector<MediaQueryToken> tokens; 106 MediaQueryTokenizer::tokenize(testCases[i].input, tokens); 107 MediaQueryBlockWatcher blockWatcher; 108 109 unsigned maxLevel = 0; 110 unsigned level = 0; 111 for (size_t j = 0; j < tokens.size(); ++j) { 112 blockWatcher.handleToken(tokens[j]); 113 level = blockWatcher.blockLevel(); 114 maxLevel = std::max(level, maxLevel); 115 } 116 ASSERT_EQ(testCases[i].maxLevel, maxLevel); 117 ASSERT_EQ(testCases[i].finalLevel, level); 118 } 119} 120 121void testToken(UChar c, MediaQueryTokenType tokenType) 122{ 123 Vector<MediaQueryToken> tokens; 124 StringBuilder input; 125 input.append(c); 126 MediaQueryTokenizer::tokenize(input.toString(), tokens); 127 ASSERT_EQ(tokens[0].type(), tokenType); 128} 129 130TEST(MediaQueryTokenizerCodepointsTest, Basic) 131{ 132 for (UChar c = 0; c <= 1000; ++c) { 133 if (isASCIIDigit(c)) 134 testToken(c, NumberToken); 135 else if (isASCIIAlpha(c)) 136 testToken(c, IdentToken); 137 else if (c == '_') 138 testToken(c, IdentToken); 139 else if (c == '\r' || c == ' ' || c == '\n' || c == '\t' || c == '\f') 140 testToken(c, WhitespaceToken); 141 else if (c == '(') 142 testToken(c, LeftParenthesisToken); 143 else if (c == ')') 144 testToken(c, RightParenthesisToken); 145 else if (c == '[') 146 testToken(c, LeftBracketToken); 147 else if (c == ']') 148 testToken(c, RightBracketToken); 149 else if (c == '{') 150 testToken(c, LeftBraceToken); 151 else if (c == '}') 152 testToken(c, RightBraceToken); 153 else if (c == '.' || c == '+' || c == '-' || c == '/' || c == '\\') 154 testToken(c, DelimiterToken); 155 else if (c == '\'' || c == '"') 156 testToken(c, StringToken); 157 else if (c == ',') 158 testToken(c, CommaToken); 159 else if (c == ':') 160 testToken(c, ColonToken); 161 else if (c == ';') 162 testToken(c, SemicolonToken); 163 else if (!c) 164 testToken(c, EOFToken); 165 else if (c > SCHAR_MAX) 166 testToken(c, IdentToken); 167 else 168 testToken(c, DelimiterToken); 169 } 170 testToken(USHRT_MAX, IdentToken); 171} 172 173} // namespace 174