19d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki/*
29d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki * Copyright (C) 2016 The Android Open Source Project
39d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki *
49d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki * Licensed under the Apache License, Version 2.0 (the "License");
59d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki * you may not use this file except in compliance with the License.
69d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki * You may obtain a copy of the License at
79d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki *
89d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki *      http://www.apache.org/licenses/LICENSE-2.0
99d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki *
109d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki * Unless required by applicable law or agreed to in writing, software
119d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki * distributed under the License is distributed on an "AS IS" BASIS,
129d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki * See the License for the specific language governing permissions and
149d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki * limitations under the License
159d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki */
169d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onukipackage com.android.providers.contacts.sqlite;
179d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
189d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onukiimport android.test.AndroidTestCase;
199d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onukiimport android.test.MoreAsserts;
209d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
219d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onukiimport com.android.providers.contacts.sqlite.SqlChecker.InvalidSqlException;
229d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
239d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onukiimport java.util.ArrayList;
249d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onukiimport java.util.Arrays;
259d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onukiimport java.util.List;
269d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
279d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onukipublic class SqlCheckerTest extends AndroidTestCase {
289d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    private ArrayList<String> getTokens(String sql) {
299d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        final ArrayList<String> tokens = new ArrayList<>();
309d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
319d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        SqlChecker.findTokens(sql, SqlChecker.OPTION_NONE,  token -> tokens.add(token));
329d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
339d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        return tokens;
349d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
359d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
369d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    private void checkTokens(String sql, String spaceSeparatedExpectedTokens) {
379d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        final List<String> expected = spaceSeparatedExpectedTokens == null
389d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki                ? new ArrayList<>()
399d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki                : Arrays.asList(spaceSeparatedExpectedTokens.split(" +"));
409d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
419d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertEquals(expected, getTokens(sql));
429d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
439d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
449d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    private void assertInvalidSql(String sql, String message) {
459d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        try {
469d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki            getTokens(sql);
479d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki            fail("Didn't throw InvalidSqlException");
489d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        } catch (InvalidSqlException e) {
499d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki            MoreAsserts.assertContainsRegex(message, e.getMessage());
509d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        }
519d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
529d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
539d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    public void testWhitespaces() {
549d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("  select  \t\r\n a\n\n  ", "select a");
559d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a b", "a b");
569d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
579d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
589d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    public void testComment() {
599d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("--\n", null);
609d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a--\n", "a");
619d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a--abcdef\n", "a");
629d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a--abcdef\nx", "a x");
639d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a--\nx", "a x");
649d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("a--abcdef", "Unterminated comment");
659d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("a--abcdef\ndef--", "Unterminated comment");
669d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
679d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("/**/", null);
689d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("/*", "Unterminated comment");
699d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("/*/", "Unterminated comment");
709d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("/*\n* /*a", "Unterminated comment");
719d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a/**/", "a");
729d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("/**/b", "b");
739d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a/**/b", "a b");
749d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a/* -- \n* /* **/b", "a b");
759d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
769d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
779d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    public void testStrings() {
789d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("'", "Unterminated quote");
799d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("a'", "Unterminated quote");
809d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("a'''", "Unterminated quote");
819d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("a''' ", "Unterminated quote");
829d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("''", null);
839d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("''''", null);
849d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a''''b", "a b");
859d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a' '' 'b", "a b");
869d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("'abc'", null);
879d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("'abc\ndef'", null);
889d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a'abc\ndef'", "a");
899d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("'abc\ndef'b", "b");
909d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a'abc\ndef'b", "a b");
919d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a'''abc\nd''ef'''b", "a b");
929d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
939d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
949d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    public void testDoubleQuotes() {
959d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("\"", "Unterminated quote");
969d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("a\"", "Unterminated quote");
979d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("a\"\"\"", "Unterminated quote");
989d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("a\"\"\" ", "Unterminated quote");
999d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("\"\"", "");
1009d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("\"\"\"\"", "\"");
1019d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a\"\"\"\"b", "a \" b");
1029d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a\"\t\"\"\t\"b", "a  \t\"\t  b");
1039d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("\"abc\"", "abc");
1049d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("\"abc\ndef\"", "abc\ndef");
1059d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a\"abc\ndef\"", "a abc\ndef");
1069d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("\"abc\ndef\"b", "abc\ndef b");
1079d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a\"abc\ndef\"b", "a abc\ndef b");
1089d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a\"\"\"abc\nd\"\"ef\"\"\"b", "a \"abc\nd\"ef\" b");
1099d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
1109d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
1119d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    public void testBackQuotes() {
1129d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("`", "Unterminated quote");
1139d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("a`", "Unterminated quote");
1149d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("a```", "Unterminated quote");
1159d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("a``` ", "Unterminated quote");
1169d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("``", "");
1179d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("````", "`");
1189d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a````b", "a ` b");
1199d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a`\t``\t`b", "a  \t`\t  b");
1209d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("`abc`", "abc");
1219d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("`abc\ndef`", "abc\ndef");
1229d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a`abc\ndef`", "a abc\ndef");
1239d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("`abc\ndef`b", "abc\ndef b");
1249d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a`abc\ndef`b", "a abc\ndef b");
1259d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a```abc\nd``ef```b", "a `abc\nd`ef` b");
1269d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
1279d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
1289d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    public void testBrackets() {
1299d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("[", "Unterminated quote");
1309d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("a[", "Unterminated quote");
1319d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("a[ ", "Unterminated quote");
1329d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("a[[ ", "Unterminated quote");
1339d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("[]", "");
1349d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("[[]", "[");
1359d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a[[]b", "a [ b");
1369d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a[\t[\t]b", "a  \t[\t  b");
1379d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("[abc]", "abc");
1389d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("[abc\ndef]", "abc\ndef");
1399d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a[abc\ndef]", "a abc\ndef");
1409d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("[abc\ndef]b", "abc\ndef b");
1419d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a[abc\ndef]b", "a abc\ndef b");
1429d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a[[abc\nd[ef[]b", "a [abc\nd[ef[ b");
1439d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
1449d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
1459d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    public void testSemicolons() {
1469d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql(";", "Semicolon is not allowed");
1479d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("  ;", "Semicolon is not allowed");
1489d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql(";  ", "Semicolon is not allowed");
1499d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        assertInvalidSql("-;-", "Semicolon is not allowed");
1509d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("--;\n", null);
1519d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("/*;*/", null);
1529d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("';'", null);
1539d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("[;]", ";");
1549d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("`;`", ";");
1559d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
1569d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
1579d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    public void testTokens() {
1589d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a,abc,a00b,_1,_123,abcdef", "a abc a00b _1 _123 abcdef");
1599d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkTokens("a--\nabc/**/a00b''_1'''ABC'''`_123`abc[d]\"e\"f",
1609d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki                "a abc a00b _1 _123 abc d e f");
1619d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
1629d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
1639d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    private SqlChecker getChecker(String... tokens) {
1649d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        return new SqlChecker(Arrays.asList(tokens));
1659d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
1669d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
1679d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    private void checkEnsureNoInvalidTokens(boolean ok, String sql, String... tokens) {
1689d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        if (ok) {
1699d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki            getChecker(tokens).ensureNoInvalidTokens(sql);
1709d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        } else {
1719d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki            try {
1729d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki                getChecker(tokens).ensureNoInvalidTokens(sql);
1739d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki                fail("Should have thrown");
1749d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki            } catch (InvalidSqlException e) {
1759d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki                // okay
1769d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki            }
1779d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        }
1789d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
1799d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
1809d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    public void testEnsureNoInvalidTokens() {
1819d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureNoInvalidTokens(true, "a b c", "Select");
1829d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
1839d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureNoInvalidTokens(false, "a b ;c", "Select");
1849d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureNoInvalidTokens(false, "a b seLeCt", "Select");
1859d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
1869d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureNoInvalidTokens(true, "a b select", "x");
1879d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
1889d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureNoInvalidTokens(false, "A b select", "x", "a");
1899d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureNoInvalidTokens(false, "A b select", "a", "x");
1909d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
1919d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureNoInvalidTokens(true, "a /*select*/ b c ", "select");
1929d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureNoInvalidTokens(true, "a 'select' b c ", "select");
1939d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
1949d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureNoInvalidTokens(true, "a b ';' c");
1959d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureNoInvalidTokens(true, "a b /*;*/ c");
196e2e9ac275e487ce558579ee65ff8f122cf498b07Makoto Onuki
197e2e9ac275e487ce558579ee65ff8f122cf498b07Makoto Onuki        checkEnsureNoInvalidTokens(false, "a b x_ c");
198e2e9ac275e487ce558579ee65ff8f122cf498b07Makoto Onuki        checkEnsureNoInvalidTokens(false, "a b [X_OK] c");
199e2e9ac275e487ce558579ee65ff8f122cf498b07Makoto Onuki        checkEnsureNoInvalidTokens(true, "a b 'x_' c");
200e2e9ac275e487ce558579ee65ff8f122cf498b07Makoto Onuki        checkEnsureNoInvalidTokens(true, "a b /*x_*/ c");
2019d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
2029d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
2039d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    private void checkEnsureSingleTokenOnly(boolean ok, String sql, String... tokens) {
2049d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        if (ok) {
2059d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki            getChecker(tokens).ensureSingleTokenOnly(sql);
2069d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        } else {
2079d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki            try {
2089d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki                getChecker(tokens).ensureSingleTokenOnly(sql);
2099d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki                fail("Should have thrown");
2109d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki            } catch (InvalidSqlException e) {
2119d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki                // okay
2129d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki            }
2139d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        }
2149d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
2159d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
2169d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    public void testEnsureSingleTokenOnly() {
2179d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(true, "a", "select");
2189d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(true, "ab", "select");
2199d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(true, "selec", "select");
2209d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(true, "selectx", "select");
2219d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
2229d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "select", "select");
2239d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "select", "a", "select");
2249d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "select", "select", "b");
2259d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "select", "a", "select", "b");
2269d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
2279d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
2289d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(true, "`a`", "select");
2299d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(true, "[a]", "select");
2309d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(true, "\"a\"", "select");
2319d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
2329d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "'a'", "select");
2339d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
2349d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "b`a`", "select");
2359d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "b[a]", "select");
2369d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "b\"a\"", "select");
2379d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "b'a'", "select");
2389d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
2399d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "`a`c", "select");
2409d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "[a]c", "select");
2419d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "\"a\"c", "select");
2429d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "'a'c", "select");
2439d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki
2449d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "", "select");
2459d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "--", "select");
2469d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "/**/", "select");
2479d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "  \n", "select");
2489d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "a--", "select");
2499d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "a/**/", "select");
2509d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki        checkEnsureSingleTokenOnly(false, "a  \n", "select");
2519d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki    }
2529d70f53e0d2eda1356af27b2a083c96257ff872eMakoto Onuki}
253