1 package org.robolectric.shadows; 2 3 import static com.google.common.truth.Truth.assertThat; 4 import static java.nio.charset.StandardCharsets.UTF_8; 5 6 import android.database.Cursor; 7 import android.database.sqlite.SQLiteCursor; 8 import android.database.sqlite.SQLiteDatabase; 9 import android.database.sqlite.SQLiteException; 10 import androidx.test.ext.junit.runners.AndroidJUnit4; 11 import org.junit.After; 12 import org.junit.Before; 13 import org.junit.Test; 14 import org.junit.runner.RunWith; 15 16 @RunWith(AndroidJUnit4.class) 17 public class SQLiteCursorTest { 18 19 private SQLiteDatabase database; 20 private Cursor cursor; 21 22 @Before setUp()23 public void setUp() throws Exception { 24 database = SQLiteDatabase.create(null); 25 26 database.execSQL("CREATE TABLE table_name(" + 27 "id INTEGER PRIMARY KEY, " + 28 "name VARCHAR(255), " + 29 "long_value BIGINT," + 30 "float_value REAL," + 31 "double_value DOUBLE, " + 32 "blob_value BINARY, " + 33 "clob_value CLOB );"); 34 35 addPeople(); 36 cursor = createCursor(); 37 } 38 39 @After tearDown()40 public void tearDown() throws Exception { 41 database.close(); 42 } 43 44 @Test testGetColumnNames()45 public void testGetColumnNames() throws Exception { 46 String[] columnNames = cursor.getColumnNames(); 47 48 assertColumnNames(columnNames); 49 } 50 51 @Test testGetColumnNamesEmpty()52 public void testGetColumnNamesEmpty() throws Exception { 53 setupEmptyResult(); 54 String[] columnNames = cursor.getColumnNames(); 55 56 // Column names are present even with an empty result. 57 assertThat(columnNames).isNotNull(); 58 assertColumnNames(columnNames); 59 } 60 61 @Test testGetColumnIndex()62 public void testGetColumnIndex() throws Exception { 63 assertThat(cursor.getColumnIndex("id")).isEqualTo(0); 64 assertThat(cursor.getColumnIndex("name")).isEqualTo(1); 65 } 66 67 @Test testGetColumnIndexNotFound()68 public void testGetColumnIndexNotFound() throws Exception { 69 assertThat(cursor.getColumnIndex("Fred")).isEqualTo(-1); 70 } 71 72 @Test testGetColumnIndexEmpty()73 public void testGetColumnIndexEmpty() throws Exception { 74 setupEmptyResult(); 75 76 assertThat(cursor.getColumnIndex("id")).isEqualTo(0); 77 assertThat(cursor.getColumnIndex("name")).isEqualTo(1); 78 } 79 80 @Test testGetColumnIndexOrThrow()81 public void testGetColumnIndexOrThrow() throws Exception { 82 assertThat(cursor.getColumnIndexOrThrow("id")).isEqualTo(0); 83 assertThat(cursor.getColumnIndexOrThrow("name")).isEqualTo(1); 84 } 85 86 @Test(expected = IllegalArgumentException.class) testGetColumnIndexOrThrowNotFound()87 public void testGetColumnIndexOrThrowNotFound() throws Exception { 88 cursor.getColumnIndexOrThrow("Fred"); 89 } 90 91 @Test testGetColumnIndexOrThrowEmpty()92 public void testGetColumnIndexOrThrowEmpty() throws Exception { 93 setupEmptyResult(); 94 95 assertThat(cursor.getColumnIndexOrThrow("name")).isEqualTo(1); 96 } 97 98 @Test(expected = IllegalArgumentException.class) testGetColumnIndexOrThrowNotFoundEmpty()99 public void testGetColumnIndexOrThrowNotFoundEmpty() throws Exception { 100 setupEmptyResult(); 101 102 cursor.getColumnIndexOrThrow("Fred"); 103 } 104 105 @Test testMoveToFirst()106 public void testMoveToFirst() throws Exception { 107 assertThat(cursor.moveToFirst()).isTrue(); 108 assertThat(cursor.getInt(0)).isEqualTo(1234); 109 assertThat(cursor.getString(1)).isEqualTo("Chuck"); 110 } 111 112 @Test testMoveToFirstEmpty()113 public void testMoveToFirstEmpty() throws Exception { 114 setupEmptyResult(); 115 116 assertThat(cursor.moveToFirst()).isFalse(); 117 } 118 119 @Test testMoveToNext()120 public void testMoveToNext() throws Exception { 121 assertThat(cursor.moveToFirst()).isTrue(); 122 123 assertThat(cursor.moveToNext()).isTrue(); 124 assertThat(cursor.getInt(0)).isEqualTo(1235); 125 assertThat(cursor.getString(1)).isEqualTo("Julie"); 126 } 127 128 @Test testMoveToNextPastEnd()129 public void testMoveToNextPastEnd() throws Exception { 130 assertThat(cursor.moveToFirst()).isTrue(); 131 132 assertThat(cursor.moveToNext()).isTrue(); 133 assertThat(cursor.moveToNext()).isTrue(); 134 assertThat(cursor.moveToNext()).isFalse(); 135 } 136 137 @Test testMoveBackwards()138 public void testMoveBackwards() throws Exception { 139 assertThat(cursor.getPosition()).isEqualTo(-1); 140 141 assertThat(cursor.moveToFirst()).isTrue(); 142 assertThat(cursor.getPosition()).isEqualTo(0); 143 assertThat(cursor.moveToNext()).isTrue(); 144 assertThat(cursor.getPosition()).isEqualTo(1); 145 assertThat(cursor.moveToNext()).isTrue(); 146 assertThat(cursor.getPosition()).isEqualTo(2); 147 148 assertThat(cursor.moveToFirst()).isTrue(); 149 assertThat(cursor.getPosition()).isEqualTo(0); 150 assertThat(cursor.moveToNext()).isTrue(); 151 assertThat(cursor.getPosition()).isEqualTo(1); 152 assertThat(cursor.moveToNext()).isTrue(); 153 assertThat(cursor.getPosition()).isEqualTo(2); 154 155 assertThat(cursor.moveToPosition(1)).isTrue(); 156 assertThat(cursor.getPosition()).isEqualTo(1); 157 } 158 159 @Test testMoveToNextEmpty()160 public void testMoveToNextEmpty() throws Exception { 161 setupEmptyResult(); 162 163 assertThat(cursor.moveToFirst()).isFalse(); 164 assertThat(cursor.moveToNext()).isFalse(); 165 } 166 167 @Test testMoveToPrevious()168 public void testMoveToPrevious() throws Exception { 169 assertThat(cursor.moveToFirst()).isTrue(); 170 assertThat(cursor.moveToNext()).isTrue(); 171 172 assertThat(cursor.moveToPrevious()).isTrue(); 173 assertThat(cursor.getInt(0)).isEqualTo(1234); 174 assertThat(cursor.getString(1)).isEqualTo("Chuck"); 175 } 176 177 @Test testMoveToPreviousPastStart()178 public void testMoveToPreviousPastStart() throws Exception { 179 assertThat(cursor.moveToFirst()).isTrue(); 180 181 // Impossible to move cursor before the first item 182 assertThat(cursor.moveToPrevious()).isFalse(); 183 } 184 185 @Test testMoveToPreviousEmpty()186 public void testMoveToPreviousEmpty() throws Exception { 187 setupEmptyResult(); 188 assertThat(cursor.moveToFirst()).isFalse(); 189 190 assertThat(cursor.moveToPrevious()).isFalse(); 191 } 192 193 @Test testGetPosition()194 public void testGetPosition() throws Exception { 195 assertThat(cursor.moveToFirst()).isTrue(); 196 assertThat(cursor.getPosition()).isEqualTo(0); 197 198 assertThat(cursor.moveToNext()).isTrue(); 199 assertThat(cursor.getPosition()).isEqualTo(1); 200 } 201 202 @Test testGetBlob()203 public void testGetBlob() throws Exception { 204 String sql = "UPDATE table_name set blob_value=? where id=1234"; 205 byte[] byteData = sql.getBytes(UTF_8); 206 207 database.execSQL(sql, new Object[]{byteData}); 208 209 assertThat(cursor.moveToFirst()).isTrue(); 210 211 byte[] retrievedByteData = cursor.getBlob(5); 212 assertThat(byteData.length).isEqualTo(retrievedByteData.length); 213 214 for (int i = 0; i < byteData.length; i++) { 215 assertThat(byteData[i]).isEqualTo(retrievedByteData[i]); 216 } 217 } 218 219 @Test testGetClob()220 public void testGetClob() throws Exception { 221 String sql = "UPDATE table_name set clob_value=? where id=1234"; 222 String s = "Don't CLOBber my data, please. Thank you."; 223 224 database.execSQL(sql, new Object[]{s}); 225 226 assertThat(cursor.moveToFirst()).isTrue(); 227 228 String actual = cursor.getString(6); 229 assertThat(s).isEqualTo(actual); 230 } 231 232 @Test testGetString()233 public void testGetString() throws Exception { 234 assertThat(cursor.moveToFirst()).isTrue(); 235 236 String[] data = {"Chuck", "Julie", "Chris"}; 237 238 for (String aData : data) { 239 assertThat(cursor.getString(1)).isEqualTo(aData); 240 cursor.moveToNext(); 241 } 242 } 243 244 @Test testGetStringWhenInteger()245 public void testGetStringWhenInteger() throws Exception { 246 assertThat(cursor.moveToFirst()).isTrue(); 247 248 assertThat(cursor.getString(0)).isEqualTo("1234"); 249 } 250 251 @Test testGetStringWhenLong()252 public void testGetStringWhenLong() throws Exception { 253 assertThat(cursor.moveToFirst()).isTrue(); 254 255 assertThat(cursor.getString(2)).isEqualTo("3463"); 256 } 257 258 @Test testGetStringWhenFloat()259 public void testGetStringWhenFloat() throws Exception { 260 assertThat(cursor.moveToFirst()).isTrue(); 261 262 assertThat(cursor.getString(3)).isEqualTo("1.5"); 263 } 264 265 @Test testGetStringWhenDouble()266 public void testGetStringWhenDouble() throws Exception { 267 assertThat(cursor.moveToFirst()).isTrue(); 268 269 assertThat(cursor.getString(4)).isEqualTo("3.14159"); 270 } 271 272 @Test(expected = SQLiteException.class) testGetStringWhenBlob()273 public void testGetStringWhenBlob() throws Exception { 274 String sql = "UPDATE table_name set blob_value=? where id=1234"; 275 byte[] byteData = sql.getBytes(UTF_8); 276 277 database.execSQL(sql, new Object[]{byteData}); 278 279 assertThat(cursor.moveToFirst()).isTrue(); 280 281 cursor.getString(5); 282 } 283 284 @Test(expected = SQLiteException.class) testGetIntWhenBlob()285 public void testGetIntWhenBlob() throws Exception { 286 String sql = "UPDATE table_name set blob_value=? where id=1234"; 287 byte[] byteData = sql.getBytes(UTF_8); 288 289 database.execSQL(sql, new Object[]{byteData}); 290 291 assertThat(cursor.moveToFirst()).isTrue(); 292 293 cursor.getInt(5); 294 } 295 296 @Test testGetStringWhenNull()297 public void testGetStringWhenNull() throws Exception { 298 assertThat(cursor.moveToFirst()).isTrue(); 299 300 assertThat(cursor.getString(5)).isNull(); 301 } 302 303 @Test testGetInt()304 public void testGetInt() throws Exception { 305 assertThat(cursor.moveToFirst()).isTrue(); 306 307 int[] data = {1234, 1235, 1236}; 308 309 for (int aData : data) { 310 assertThat(cursor.getInt(0)).isEqualTo(aData); 311 cursor.moveToNext(); 312 } 313 } 314 315 @Test testGetNumbersFromStringField()316 public void testGetNumbersFromStringField() throws Exception { 317 database.execSQL("update table_name set name = '1.2'"); 318 assertThat(cursor.moveToFirst()).isTrue(); 319 320 assertThat(cursor.getInt(1)).isEqualTo(1); 321 assertThat(cursor.getDouble(1)).isEqualTo(1.2d); 322 assertThat(cursor.getFloat(1)).isEqualTo(1.2f); 323 } 324 325 @Test testGetNumbersFromBlobField()326 public void testGetNumbersFromBlobField() throws Exception { 327 database.execSQL("update table_name set name = '1.2'"); 328 assertThat(cursor.moveToFirst()).isTrue(); 329 330 assertThat(cursor.getInt(1)).isEqualTo(1); 331 assertThat(cursor.getDouble(1)).isEqualTo(1.2d); 332 assertThat(cursor.getFloat(1)).isEqualTo(1.2f); 333 } 334 335 @Test testGetLong()336 public void testGetLong() throws Exception { 337 assertThat(cursor.moveToFirst()).isTrue(); 338 339 assertThat(cursor.getLong(2)).isEqualTo(3463L); 340 } 341 342 @Test testGetFloat()343 public void testGetFloat() throws Exception { 344 assertThat(cursor.moveToFirst()).isTrue(); 345 346 assertThat(cursor.getFloat(3)).isEqualTo((float) 1.5); 347 } 348 349 @Test testGetDouble()350 public void testGetDouble() throws Exception { 351 assertThat(cursor.moveToFirst()).isTrue(); 352 353 assertThat(cursor.getDouble(4)).isEqualTo(3.14159); 354 } 355 356 @Test testClose()357 public void testClose() throws Exception { 358 assertThat(cursor.isClosed()).isFalse(); 359 cursor.close(); 360 assertThat(cursor.isClosed()).isTrue(); 361 } 362 363 @Test testIsNullWhenNull()364 public void testIsNullWhenNull() throws Exception { 365 assertThat(cursor.moveToFirst()).isTrue(); 366 assertThat(cursor.moveToNext()).isTrue(); 367 368 assertThat(cursor.isNull(cursor.getColumnIndex("id"))).isFalse(); 369 assertThat(cursor.isNull(cursor.getColumnIndex("name"))).isFalse(); 370 371 assertThat(cursor.isNull(cursor.getColumnIndex("long_value"))).isTrue(); 372 assertThat(cursor.isNull(cursor.getColumnIndex("float_value"))).isTrue(); 373 assertThat(cursor.isNull(cursor.getColumnIndex("double_value"))).isTrue(); 374 } 375 376 @Test testIsNullWhenNotNull()377 public void testIsNullWhenNotNull() throws Exception { 378 assertThat(cursor.moveToFirst()).isTrue(); 379 380 for (int i = 0; i < 5; i++) { 381 assertThat(cursor.isNull(i)).isFalse(); 382 } 383 } 384 385 @Test testIsNullWhenIndexOutOfBounds()386 public void testIsNullWhenIndexOutOfBounds() throws Exception { 387 assertThat(cursor.moveToFirst()).isTrue(); 388 389 // column index 5 is out-of-bounds 390 assertThat(cursor.isNull(5)).isTrue(); 391 } 392 393 @Test testGetTypeWhenInteger()394 public void testGetTypeWhenInteger() throws Exception { 395 assertThat(cursor.moveToFirst()).isTrue(); 396 397 assertThat(cursor.getType(0)).isEqualTo(Cursor.FIELD_TYPE_INTEGER); 398 } 399 400 @Test testGetTypeWhenString()401 public void testGetTypeWhenString() throws Exception { 402 assertThat(cursor.moveToFirst()).isTrue(); 403 404 assertThat(cursor.getType(1)).isEqualTo(Cursor.FIELD_TYPE_STRING); 405 } 406 407 @Test testGetTypeWhenLong()408 public void testGetTypeWhenLong() throws Exception { 409 assertThat(cursor.moveToFirst()).isTrue(); 410 411 assertThat(cursor.getType(2)).isEqualTo(Cursor.FIELD_TYPE_INTEGER); 412 } 413 414 @Test testGetTypeWhenFloat()415 public void testGetTypeWhenFloat() throws Exception { 416 assertThat(cursor.moveToFirst()).isTrue(); 417 418 assertThat(cursor.getType(3)).isEqualTo(Cursor.FIELD_TYPE_FLOAT); 419 } 420 421 @Test testGetTypeWhenDouble()422 public void testGetTypeWhenDouble() throws Exception { 423 assertThat(cursor.moveToFirst()).isTrue(); 424 425 assertThat(cursor.getType(4)).isEqualTo(Cursor.FIELD_TYPE_FLOAT); 426 } 427 428 @Test testGetTypeWhenBlob()429 public void testGetTypeWhenBlob() throws Exception { 430 String sql = "UPDATE table_name set blob_value=? where id=1234"; 431 byte[] byteData = sql.getBytes(UTF_8); 432 433 database.execSQL(sql, new Object[]{byteData}); 434 435 assertThat(cursor.moveToFirst()).isTrue(); 436 assertThat(cursor.getType(5)).isEqualTo(Cursor.FIELD_TYPE_BLOB); 437 } 438 439 @Test testGetTypeWhenNull()440 public void testGetTypeWhenNull() throws Exception { 441 assertThat(cursor.moveToFirst()).isTrue(); 442 443 assertThat(cursor.getType(5)).isEqualTo(Cursor.FIELD_TYPE_NULL); 444 } 445 446 @Test testGetNullNumberValues()447 public void testGetNullNumberValues() throws Exception { 448 String sql = "UPDATE table_name set long_value=NULL, float_value=NULL, double_value=NULL"; 449 database.execSQL(sql); 450 451 assertThat(cursor.moveToFirst()).isTrue(); 452 453 assertThat(cursor.getType(2)).isEqualTo(Cursor.FIELD_TYPE_NULL); 454 assertThat(cursor.getLong(2)).isEqualTo(0); 455 456 assertThat(cursor.getType(3)).isEqualTo(Cursor.FIELD_TYPE_NULL); 457 assertThat(cursor.getFloat(3)).isEqualTo(0f); 458 459 assertThat(cursor.getType(4)).isEqualTo(Cursor.FIELD_TYPE_NULL); 460 assertThat(cursor.getDouble(4)).isEqualTo(0d); 461 } 462 addPeople()463 private void addPeople() throws Exception { 464 String[] inserts = { 465 "INSERT INTO table_name (id, name, long_value, float_value, double_value) VALUES(1234, 'Chuck', 3463, 1.5, 3.14159);", 466 "INSERT INTO table_name (id, name) VALUES(1235, 'Julie');", 467 "INSERT INTO table_name (id, name) VALUES(1236, 'Chris');" 468 }; 469 470 for (String insert : inserts) { 471 database.execSQL(insert); 472 } 473 } 474 createCursor()475 private Cursor createCursor() throws Exception { 476 String sql ="SELECT * FROM table_name;"; 477 Cursor cursor = database.rawQuery(sql, null); 478 assertThat(cursor).isInstanceOf(SQLiteCursor.class); 479 return cursor; 480 } 481 setupEmptyResult()482 private void setupEmptyResult() throws Exception { 483 database.execSQL("DELETE FROM table_name;"); 484 cursor = createCursor(); 485 } 486 assertColumnNames(String[] columnNames)487 private void assertColumnNames(String[] columnNames) { 488 assertThat(columnNames.length).isEqualTo(7); 489 assertThat(columnNames[0]).isEqualTo("id"); 490 assertThat(columnNames[1]).isEqualTo("name"); 491 assertThat(columnNames[2]).isEqualTo("long_value"); 492 assertThat(columnNames[3]).isEqualTo("float_value"); 493 assertThat(columnNames[4]).isEqualTo("double_value"); 494 assertThat(columnNames[5]).isEqualTo("blob_value"); 495 assertThat(columnNames[6]).isEqualTo("clob_value"); 496 } 497 } 498