• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 package com.android.providers.contacts.sqlite;
17 
18 import android.test.MoreAsserts;
19 
20 import com.android.providers.contacts.FixedAndroidTestCase;
21 import com.android.providers.contacts.sqlite.SqlChecker.InvalidSqlException;
22 
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.List;
26 
27 public class SqlCheckerTest extends FixedAndroidTestCase {
getTokens(String sql)28     private ArrayList<String> getTokens(String sql) {
29         final ArrayList<String> tokens = new ArrayList<>();
30 
31         SqlChecker.findTokens(sql, SqlChecker.OPTION_NONE,  token -> tokens.add(token));
32 
33         return tokens;
34     }
35 
checkTokens(String sql, String spaceSeparatedExpectedTokens)36     private void checkTokens(String sql, String spaceSeparatedExpectedTokens) {
37         final List<String> expected = spaceSeparatedExpectedTokens == null
38                 ? new ArrayList<>()
39                 : Arrays.asList(spaceSeparatedExpectedTokens.split(" +"));
40 
41         assertEquals(expected, getTokens(sql));
42     }
43 
assertInvalidSql(String sql, String message)44     private void assertInvalidSql(String sql, String message) {
45         try {
46             getTokens(sql);
47             fail("Didn't throw InvalidSqlException");
48         } catch (InvalidSqlException e) {
49             MoreAsserts.assertContainsRegex(message, e.getMessage());
50         }
51     }
52 
testWhitespaces()53     public void testWhitespaces() {
54         checkTokens("  select  \t\r\n a\n\n  ", "select a");
55         checkTokens("a b", "a b");
56     }
57 
testComment()58     public void testComment() {
59         checkTokens("--\n", null);
60         checkTokens("a--\n", "a");
61         checkTokens("a--abcdef\n", "a");
62         checkTokens("a--abcdef\nx", "a x");
63         checkTokens("a--\nx", "a x");
64         assertInvalidSql("a--abcdef", "Unterminated comment");
65         assertInvalidSql("a--abcdef\ndef--", "Unterminated comment");
66 
67         checkTokens("/**/", null);
68         assertInvalidSql("/*", "Unterminated comment");
69         assertInvalidSql("/*/", "Unterminated comment");
70         assertInvalidSql("/*\n* /*a", "Unterminated comment");
71         checkTokens("a/**/", "a");
72         checkTokens("/**/b", "b");
73         checkTokens("a/**/b", "a b");
74         checkTokens("a/* -- \n* /* **/b", "a b");
75     }
76 
testStrings()77     public void testStrings() {
78         assertInvalidSql("'", "Unterminated quote");
79         assertInvalidSql("a'", "Unterminated quote");
80         assertInvalidSql("a'''", "Unterminated quote");
81         assertInvalidSql("a''' ", "Unterminated quote");
82         checkTokens("''", null);
83         checkTokens("''''", null);
84         checkTokens("a''''b", "a b");
85         checkTokens("a' '' 'b", "a b");
86         checkTokens("'abc'", null);
87         checkTokens("'abc\ndef'", null);
88         checkTokens("a'abc\ndef'", "a");
89         checkTokens("'abc\ndef'b", "b");
90         checkTokens("a'abc\ndef'b", "a b");
91         checkTokens("a'''abc\nd''ef'''b", "a b");
92     }
93 
testDoubleQuotes()94     public void testDoubleQuotes() {
95         assertInvalidSql("\"", "Unterminated quote");
96         assertInvalidSql("a\"", "Unterminated quote");
97         assertInvalidSql("a\"\"\"", "Unterminated quote");
98         assertInvalidSql("a\"\"\" ", "Unterminated quote");
99         checkTokens("\"\"", "");
100         checkTokens("\"\"\"\"", "\"");
101         checkTokens("a\"\"\"\"b", "a \" b");
102         checkTokens("a\"\t\"\"\t\"b", "a  \t\"\t  b");
103         checkTokens("\"abc\"", "abc");
104         checkTokens("\"abc\ndef\"", "abc\ndef");
105         checkTokens("a\"abc\ndef\"", "a abc\ndef");
106         checkTokens("\"abc\ndef\"b", "abc\ndef b");
107         checkTokens("a\"abc\ndef\"b", "a abc\ndef b");
108         checkTokens("a\"\"\"abc\nd\"\"ef\"\"\"b", "a \"abc\nd\"ef\" b");
109     }
110 
testBackQuotes()111     public void testBackQuotes() {
112         assertInvalidSql("`", "Unterminated quote");
113         assertInvalidSql("a`", "Unterminated quote");
114         assertInvalidSql("a```", "Unterminated quote");
115         assertInvalidSql("a``` ", "Unterminated quote");
116         checkTokens("``", "");
117         checkTokens("````", "`");
118         checkTokens("a````b", "a ` b");
119         checkTokens("a`\t``\t`b", "a  \t`\t  b");
120         checkTokens("`abc`", "abc");
121         checkTokens("`abc\ndef`", "abc\ndef");
122         checkTokens("a`abc\ndef`", "a abc\ndef");
123         checkTokens("`abc\ndef`b", "abc\ndef b");
124         checkTokens("a`abc\ndef`b", "a abc\ndef b");
125         checkTokens("a```abc\nd``ef```b", "a `abc\nd`ef` b");
126     }
127 
testBrackets()128     public void testBrackets() {
129         assertInvalidSql("[", "Unterminated quote");
130         assertInvalidSql("a[", "Unterminated quote");
131         assertInvalidSql("a[ ", "Unterminated quote");
132         assertInvalidSql("a[[ ", "Unterminated quote");
133         checkTokens("[]", "");
134         checkTokens("[[]", "[");
135         checkTokens("a[[]b", "a [ b");
136         checkTokens("a[\t[\t]b", "a  \t[\t  b");
137         checkTokens("[abc]", "abc");
138         checkTokens("[abc\ndef]", "abc\ndef");
139         checkTokens("a[abc\ndef]", "a abc\ndef");
140         checkTokens("[abc\ndef]b", "abc\ndef b");
141         checkTokens("a[abc\ndef]b", "a abc\ndef b");
142         checkTokens("a[[abc\nd[ef[]b", "a [abc\nd[ef[ b");
143     }
144 
testSemicolons()145     public void testSemicolons() {
146         assertInvalidSql(";", "Semicolon is not allowed");
147         assertInvalidSql("  ;", "Semicolon is not allowed");
148         assertInvalidSql(";  ", "Semicolon is not allowed");
149         assertInvalidSql("-;-", "Semicolon is not allowed");
150         checkTokens("--;\n", null);
151         checkTokens("/*;*/", null);
152         checkTokens("';'", null);
153         checkTokens("[;]", ";");
154         checkTokens("`;`", ";");
155     }
156 
testTokens()157     public void testTokens() {
158         checkTokens("a,abc,a00b,_1,_123,abcdef", "a abc a00b _1 _123 abcdef");
159         checkTokens("a--\nabc/**/a00b''_1'''ABC'''`_123`abc[d]\"e\"f",
160                 "a abc a00b _1 _123 abc d e f");
161     }
162 
getChecker(String... tokens)163     private SqlChecker getChecker(String... tokens) {
164         return new SqlChecker(Arrays.asList(tokens));
165     }
166 
checkEnsureNoInvalidTokens(boolean ok, String sql, String... tokens)167     private void checkEnsureNoInvalidTokens(boolean ok, String sql, String... tokens) {
168         if (ok) {
169             getChecker(tokens).ensureNoInvalidTokens(sql);
170         } else {
171             try {
172                 getChecker(tokens).ensureNoInvalidTokens(sql);
173                 fail("Should have thrown");
174             } catch (InvalidSqlException e) {
175                 // okay
176             }
177         }
178     }
179 
testEnsureNoInvalidTokens()180     public void testEnsureNoInvalidTokens() {
181         checkEnsureNoInvalidTokens(true, "a b c", "Select");
182 
183         checkEnsureNoInvalidTokens(false, "a b ;c", "Select");
184         checkEnsureNoInvalidTokens(false, "a b seLeCt", "Select");
185 
186         checkEnsureNoInvalidTokens(true, "a b select", "x");
187 
188         checkEnsureNoInvalidTokens(false, "A b select", "x", "a");
189         checkEnsureNoInvalidTokens(false, "A b select", "a", "x");
190 
191         checkEnsureNoInvalidTokens(true, "a /*select*/ b c ", "select");
192         checkEnsureNoInvalidTokens(true, "a 'select' b c ", "select");
193 
194         checkEnsureNoInvalidTokens(true, "a b ';' c");
195         checkEnsureNoInvalidTokens(true, "a b /*;*/ c");
196 
197         checkEnsureNoInvalidTokens(false, "a b x_ c");
198         checkEnsureNoInvalidTokens(false, "a b [X_OK] c");
199         checkEnsureNoInvalidTokens(true, "a b 'x_' c");
200         checkEnsureNoInvalidTokens(true, "a b /*x_*/ c");
201     }
202 
checkEnsureSingleTokenOnly(boolean ok, String sql, String... tokens)203     private void checkEnsureSingleTokenOnly(boolean ok, String sql, String... tokens) {
204         if (ok) {
205             getChecker(tokens).ensureSingleTokenOnly(sql);
206         } else {
207             try {
208                 getChecker(tokens).ensureSingleTokenOnly(sql);
209                 fail("Should have thrown");
210             } catch (InvalidSqlException e) {
211                 // okay
212             }
213         }
214     }
215 
testEnsureSingleTokenOnly()216     public void testEnsureSingleTokenOnly() {
217         checkEnsureSingleTokenOnly(true, "a", "select");
218         checkEnsureSingleTokenOnly(true, "ab", "select");
219         checkEnsureSingleTokenOnly(true, "selec", "select");
220         checkEnsureSingleTokenOnly(true, "selectx", "select");
221 
222         checkEnsureSingleTokenOnly(false, "select", "select");
223         checkEnsureSingleTokenOnly(false, "select", "a", "select");
224         checkEnsureSingleTokenOnly(false, "select", "select", "b");
225         checkEnsureSingleTokenOnly(false, "select", "a", "select", "b");
226 
227 
228         checkEnsureSingleTokenOnly(true, "`a`", "select");
229         checkEnsureSingleTokenOnly(true, "[a]", "select");
230         checkEnsureSingleTokenOnly(true, "\"a\"", "select");
231 
232         checkEnsureSingleTokenOnly(false, "'a'", "select");
233 
234         checkEnsureSingleTokenOnly(false, "b`a`", "select");
235         checkEnsureSingleTokenOnly(false, "b[a]", "select");
236         checkEnsureSingleTokenOnly(false, "b\"a\"", "select");
237         checkEnsureSingleTokenOnly(false, "b'a'", "select");
238 
239         checkEnsureSingleTokenOnly(false, "`a`c", "select");
240         checkEnsureSingleTokenOnly(false, "[a]c", "select");
241         checkEnsureSingleTokenOnly(false, "\"a\"c", "select");
242         checkEnsureSingleTokenOnly(false, "'a'c", "select");
243 
244         checkEnsureSingleTokenOnly(false, "", "select");
245         checkEnsureSingleTokenOnly(false, "--", "select");
246         checkEnsureSingleTokenOnly(false, "/**/", "select");
247         checkEnsureSingleTokenOnly(false, "  \n", "select");
248         checkEnsureSingleTokenOnly(false, "a--", "select");
249         checkEnsureSingleTokenOnly(false, "a/**/", "select");
250         checkEnsureSingleTokenOnly(false, "a  \n", "select");
251     }
252 }
253