1/*
2 * Copyright (C) 2008 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
17package libcore.sqlite;
18
19import SQLite.Database;
20import SQLite.Exception;
21import SQLite.Function;
22import SQLite.FunctionContext;
23import SQLite.Stmt;
24import SQLite.TableResult;
25import java.io.UnsupportedEncodingException;
26import java.sql.SQLException;
27import java.sql.Statement;
28import tests.support.DatabaseCreator;
29
30public final class OldFunctionContextTest extends OldSQLiteTest {
31
32    private Database db = null;
33
34    @Override public void setUp() throws java.lang.Exception {
35        super.setUp();
36        db = new Database();
37        db.open(dbFile.getPath(), 0);
38        Statement st = conn.createStatement();
39        st.execute(DatabaseCreator.CREATE_TABLE2);
40        st.execute(DatabaseCreator.CREATE_TABLE_SIMPLE1);
41        st.close();
42    }
43
44    public void testSet_resultString() throws Exception {
45        TestFCString testString = new TestFCString();
46        db.exec("insert into " + DatabaseCreator.TEST_TABLE2
47                + " (ftext) values ('TestInput')", null);
48        db.create_function("test", 1, testString);
49        TableResult res = db.get_table("select test(ftext) from "
50                + DatabaseCreator.TEST_TABLE2);
51        String row[] = (String[]) res.rows.elementAt(0);
52        String val = row[0];
53
54        assertEquals("TestInput", val);
55    }
56
57    public void testSet_resultInt() throws Exception {
58        TestFCInt testInt = new TestFCInt();
59        db.exec("insert into " + DatabaseCreator.SIMPLE_TABLE1
60                + "  values (1,'" + testInt.intVal + "',3)", null);
61        db.create_function("testInt", 1, testInt);
62        TableResult res = db.get_table("select testInt(speed) from "
63                + DatabaseCreator.SIMPLE_TABLE1);
64        String row[] = (String[]) res.rows.elementAt(0);
65        String val = row[0];
66
67        assertEquals(testInt.intVal, Integer.parseInt(val));
68    }
69
70    public void testSet_resultDouble() throws Exception {
71        SinFunc testD = new SinFunc();
72        db.exec("insert into " + DatabaseCreator.TEST_TABLE2
73                + " (fdouble)  values (" + testD.testDouble + ")", null);
74        db.create_function("testDouble", 1, testD);
75        TableResult res = db.get_table("select testDouble(fdouble) from "
76                + DatabaseCreator.TEST_TABLE2);
77        String row[] = (String[]) res.rows.elementAt(0);
78        String val = row[0];
79
80        assertEquals(testD.testDouble, Double.parseDouble(val));
81
82        assertTrue(testD.functionCalled);
83    }
84
85    public void testSet_error() throws Exception {
86        TestFCError testError = new TestFCError();
87        SinFunc testD = new SinFunc();
88        db.exec("insert into " + DatabaseCreator.TEST_TABLE2
89                + " (fdouble)  values (" + testD.testDouble + ")", null);
90        db.create_function("testError", 1, testError);
91
92        try {
93        TableResult res = db.get_table("select testError(fdouble) from "
94                + DatabaseCreator.TEST_TABLE2);
95        fail("Should get Exception");
96        } catch (Exception e) {
97            assertEquals("error in step", e.getMessage());
98        }
99
100        assertFalse(testD.functionCalled);
101    }
102
103    public void testSet_resultByteArray() throws Exception, UnsupportedEncodingException {
104        Stmt st = null;
105        TestFCByteArray testBinArrayFnc = new TestFCByteArray();
106        String expected = "";
107        expected = "X'" + getHexString(testBinArrayFnc.byteVal) + "'";
108
109        // setup
110        db.exec("create table testBinaryData (binVal BINARY) ;", null);
111
112        try {
113        st = db.prepare("insert into testBinaryData values (?)");
114        st.bind(1, testBinArrayFnc.byteVal);
115        st.step();
116
117
118        db.create_function("testBinArray", 1, testBinArrayFnc);
119        TableResult res = db
120                .get_table("select testBinArray(binVal) from testBinaryData");
121
122        String row[] = (String[]) res.rows.elementAt(0);
123        String val = row[0];
124
125        assertTrue(expected.equalsIgnoreCase(val));
126
127        assertTrue(testBinArrayFnc.functionCalled);
128
129        } finally {
130            //teardown
131            db.exec("drop table testBinaryData;", null);
132        }
133    }
134
135    /**
136     * ZeroBlob not supported
137     */
138    public void testSet_result_zeroblob() throws Exception,
139            UnsupportedEncodingException {
140        Stmt st = null;
141        TestFCZeroBlob testZeroBlobFnc = new TestFCZeroBlob();
142        byte[] byteVal = {(byte) 1, (byte) 2, (byte) 3};
143
144
145        // setup
146        db.exec("create table testBinaryData (binVal BINARY) ;", null);
147
148        try {
149        st = db.prepare("insert into testBinaryData values (?)");
150        st.bind(1, byteVal);
151        st.step();
152
153
154        db.create_function("testZeroBlob", 0, testZeroBlobFnc);
155        TableResult res = db
156                .get_table("select testZeroBlob() from testBinaryData");
157        TableResult res2 = db.get_table("select zeroblob("
158                + testZeroBlobFnc.numBytes + ") from testBinaryData");
159
160        String row[] = (String[]) res.rows.elementAt(0);
161        String val = row[0];
162
163        assertNotNull(val);
164
165        assertEquals(((String[]) res2.rows.elementAt(0))[0], val);
166        assertTrue(testZeroBlobFnc.functionCalled);
167
168        } finally  {
169         // teardown
170            db.exec("drop table if exists testBinaryData;", null);
171        }
172    }
173
174    /**
175     * Test Method results in a segmentation fault
176     */
177    public void testCount() throws SQLException, Exception {
178        TestFCCount countTest = new TestFCCount();
179        int inputCount = 10;
180
181        assertFalse(countTest.functionCalled);
182
183        DatabaseCreator.fillTestTable2(conn, inputCount);
184        db.create_function("testCount", 0, countTest);
185        // the invokation of testCount leads to a Segmentation fault
186        /*
187        TableResult res = db
188                .get_table("select testCount() from "+DatabaseCreator.TEST_TABLE2);
189
190        String row[] = (String[]) res.rows.elementAt(0);
191        String val = row[0];
192
193        assertTrue(countTest.functionCalled);
194        assertEquals(inputCount,Integer.parseInt(val));
195        */
196
197    }
198
199    class TestFCError implements Function {
200        public boolean functionCalled = false;
201        public String errorMsg = "FunctionError";
202
203        public void function(FunctionContext fc, String args[]) {
204            functionCalled = true;
205            fc.set_error(errorMsg);
206        }
207
208        public void last_step(FunctionContext fc) {}
209        public void step(FunctionContext fc, String[] args) {}
210    }
211
212    class TestFCCount implements Function {
213        public boolean functionCalled = false;
214        public int noOfRows = 0;
215
216        public void function(FunctionContext fc, String args[]) {
217            functionCalled = true;
218            noOfRows = fc.count();
219            fc.set_result(noOfRows);
220        }
221
222        public void last_step(FunctionContext fc) {}
223        public void step(FunctionContext fc, String[] args) {}
224    }
225
226    class TestFCZeroBlob implements Function {
227        public int numBytes = 16;
228        public boolean functionCalled = false;
229
230        public void function(FunctionContext fc, String args[]) {
231            functionCalled = true;
232            fc.set_result_zeroblob(numBytes);
233        }
234
235        public void last_step(FunctionContext fc) {}
236        public void step(FunctionContext fc, String[] args) {}
237    }
238
239    class TestFCString implements Function {
240        public String testString = "TestString";
241        public boolean functionCalled;
242
243        public void function(FunctionContext fc, String args[]) {
244            assertNotNull(args);
245            functionCalled = true;
246            fc.set_result(args[0]);
247        }
248
249        public void last_step(FunctionContext fc) {}
250        public void step(FunctionContext fc, String[] args) {}
251    }
252
253    class TestFCInt implements Function {
254        public int intVal = Integer.MAX_VALUE;
255        public boolean functionCalled;
256
257        public void function(FunctionContext fc, String args[]) {
258            assertNotNull(args);
259            functionCalled = true;
260            fc.set_result(Integer.parseInt(args[0]));
261        }
262
263        public void last_step(FunctionContext fc) {}
264        public void step(FunctionContext fc, String[] args) {}
265    }
266
267    class TestFCByteArray implements Function {
268        public byte[] byteVal = {(byte)  1, (byte) 2, (byte) 3};
269        public boolean functionCalled;
270
271        public void function(FunctionContext fc, String args[]) {
272            assertNotNull(args);
273            functionCalled = true;
274            fc.set_result(args[0].getBytes());
275        }
276
277        public void last_step(FunctionContext fc) {}
278        public void step(FunctionContext fc, String[] args) {}
279    }
280
281    class SinFunc implements Function {
282        public Double testDouble = 3.0;
283        public boolean functionCalled = false;
284
285        public void function(FunctionContext fc, String args[]) {
286            Double d = new Double(args[0]);
287            functionCalled = true;
288            fc.set_result(d.doubleValue());
289        }
290
291        public void last_step(FunctionContext fc) {}
292        public void step(FunctionContext fc, String[] args) {}
293    }
294
295    static final byte[] HEX_CHAR_TABLE = {
296            (byte)'0', (byte)'1', (byte)'2', (byte)'3',
297            (byte)'4', (byte)'5', (byte)'6', (byte)'7',
298            (byte)'8', (byte)'9', (byte)'a', (byte)'b',
299            (byte)'c', (byte)'d', (byte)'e', (byte)'f'
300          };
301
302    public static String getHexString(byte[] raw)
303            throws UnsupportedEncodingException {
304        byte[] hex = new byte[2 * raw.length];
305        int index = 0;
306
307        for (byte b : raw) {
308            int v = b & 0xFF;
309            hex[index++] = HEX_CHAR_TABLE[v >>> 4];
310            hex[index++] = HEX_CHAR_TABLE[v & 0xF];
311        }
312        return new String(hex, "ASCII");
313    }
314}
315