508aab3522b0775478fc9c489e17a48333b8db0d
[Sunshine.git] / app / src / androidTest / java / uk / me / njae / sunshine / TestProvider.java
1 package uk.me.njae.sunshine;
2
3 import android.annotation.TargetApi;
4 import android.content.ContentUris;
5 import android.content.ContentValues;
6 import android.database.Cursor;
7 import android.net.Uri;
8 import android.os.Build;
9 import android.test.AndroidTestCase;
10 import android.util.Log;
11
12 import uk.me.njae.sunshine.data.WeatherContract.LocationEntry;
13 import uk.me.njae.sunshine.data.WeatherContract.WeatherEntry;
14 import uk.me.njae.sunshine.data.WeatherDbHelper;
15
16 public class TestProvider extends AndroidTestCase {
17
18 public static final String LOG_TAG = TestProvider.class.getSimpleName();
19
20 // brings our database to an empty state
21 public void deleteAllRecords() {
22 mContext.getContentResolver().delete(
23 WeatherEntry.CONTENT_URI,
24 null,
25 null
26 );
27 mContext.getContentResolver().delete(
28 LocationEntry.CONTENT_URI,
29 null,
30 null
31 );
32
33 Cursor cursor = mContext.getContentResolver().query(
34 WeatherEntry.CONTENT_URI,
35 null,
36 null,
37 null,
38 null
39 );
40 assertEquals(0, cursor.getCount());
41 cursor.close();
42
43 cursor = mContext.getContentResolver().query(
44 LocationEntry.CONTENT_URI,
45 null,
46 null,
47 null,
48 null
49 );
50 assertEquals(0, cursor.getCount());
51 cursor.close();
52 }
53
54 // Since we want each test to start with a clean slate, run deleteAllRecords
55 // in setUp (called by the test runner before each test).
56 public void setUp() {
57 deleteAllRecords();
58 }
59
60 public void testInsertReadProvider() {
61
62 // If there's an error in those massive SQL table creation Strings,
63 // errors will be thrown here when you try to get a writable database.
64 WeatherDbHelper dbHelper = new WeatherDbHelper(mContext);
65 // SQLiteDatabase db = dbHelper.getWritableDatabase();
66
67 // Create a new map of values, where column names are the keys
68 ContentValues locationTestValues = TestDb.createNorthPoleLocationValues();
69
70 Uri locationInsertUri = mContext.getContentResolver().insert(LocationEntry.CONTENT_URI, locationTestValues);
71 assertTrue(locationInsertUri != null);
72 long locationRowId = ContentUris.parseId(locationInsertUri);
73
74 Log.d(LOG_TAG, "New row id: " + locationRowId);
75
76 // Data's inserted. IN THEORY. Now pull some out to stare at it and verify it made
77 // the round trip.
78
79 // A cursor is your primary interface to the query results.
80 Cursor cursor = mContext.getContentResolver().query(
81 LocationEntry.CONTENT_URI, // Table to Query
82 null, // All columns
83 null, // Columns for the "where" clause
84 null, // Values for the "where" clause
85 null // columns to group by
86 );
87
88 TestDb.validateCursor(cursor, locationTestValues);
89
90 // Now see if we can successfully query if we include the row id
91 cursor = mContext.getContentResolver().query(
92 LocationEntry.buildLocationUri(locationRowId),
93 null, // leaving "columns" null just returns all the columns.
94 null, // cols for "where" clause
95 null, // values for "where" clause
96 null // sort order
97 );
98
99 TestDb.validateCursor(cursor, locationTestValues);
100
101
102 // Fantastic. Now that we have a location, add some weather!
103
104 ContentValues weatherTestValues = TestDb.createWeatherValues(locationRowId);
105
106 Uri weatherInsertUri = mContext.getContentResolver().insert(WeatherEntry.CONTENT_URI, weatherTestValues);
107 assertTrue(weatherInsertUri != null);
108
109 // A cursor is your primary interface to the query results.
110 Cursor weatherCursor = mContext.getContentResolver().query(
111 WeatherEntry.CONTENT_URI, // Table to Query
112 null, // leaving "columns" null just returns all the columns.
113 null, // cols for "where" clause
114 null, // values for "where" clause
115 null // columns to group by
116 );
117
118 TestDb.validateCursor(weatherCursor, weatherTestValues);
119
120
121 // Add the location values in with the weather data so that we can make
122 // sure that the join worked and we actually get all the values back
123 addAllContentValues(weatherTestValues, locationTestValues);
124
125 // Get the joined Weather and Location data
126 weatherCursor = mContext.getContentResolver().query(
127 WeatherEntry.buildWeatherLocation(TestDb.TEST_LOCATION),
128 null, // leaving "columns" null just returns all the columns.
129 null, // cols for "where" clause
130 null, // values for "where" clause
131 null // sort order
132 );
133 TestDb.validateCursor(weatherCursor, weatherTestValues);
134
135 // Get the joined Weather and Location data with a start date
136 weatherCursor = mContext.getContentResolver().query(
137 WeatherEntry.buildWeatherLocationWithStartDate(
138 TestDb.TEST_LOCATION, TestDb.TEST_DATE),
139 null, // leaving "columns" null just returns all the columns.
140 null, // cols for "where" clause
141 null, // values for "where" clause
142 null // sort order
143 );
144 TestDb.validateCursor(weatherCursor, weatherTestValues);
145
146 // Get the joined Weather data for a specific date
147 weatherCursor = mContext.getContentResolver().query(
148 WeatherEntry.buildWeatherLocationWithDate(TestDb.TEST_LOCATION, TestDb.TEST_DATE),
149 null,
150 null,
151 null,
152 null
153 );
154 TestDb.validateCursor(weatherCursor, weatherTestValues);
155
156 dbHelper.close();
157 }
158
159 public void testGetType() {
160 // content://uk.me.njae.sunshine/weather/
161 String type = mContext.getContentResolver().getType(WeatherEntry.CONTENT_URI);
162 // vnd.android.cursor.dir/uk.me.njae.sunshine/weather
163 assertEquals(WeatherEntry.CONTENT_TYPE, type);
164
165 String testLocation = "94074";
166 // content://uk.me.njae.sunshine/weather/94074
167 type = mContext.getContentResolver().getType(
168 WeatherEntry.buildWeatherLocation(testLocation));
169 // vnd.android.cursor.dir/uk.me.njae.sunshine/weather
170 assertEquals(WeatherEntry.CONTENT_TYPE, type);
171
172 String testDate = "20140612";
173 // content://uk.me.njae.sunshine/weather/94074/20140612
174 type = mContext.getContentResolver().getType(
175 WeatherEntry.buildWeatherLocationWithDate(testLocation, testDate));
176 // vnd.android.cursor.item/uk.me.njae.sunshine/weather
177 assertEquals(WeatherEntry.CONTENT_ITEM_TYPE, type);
178
179 // content://uk.me.njae.sunshine/location/
180 type = mContext.getContentResolver().getType(LocationEntry.CONTENT_URI);
181 // vnd.android.cursor.dir/uk.me.njae.sunshine/location
182 assertEquals(LocationEntry.CONTENT_TYPE, type);
183
184 // content://uk.me.njae.sunshine/location/1
185 type = mContext.getContentResolver().getType(LocationEntry.buildLocationUri(1L));
186 // vnd.android.cursor.item/uk.me.njae.sunshine/location
187 assertEquals(LocationEntry.CONTENT_ITEM_TYPE, type);
188 }
189
190 public void testUpdateLocation() {
191 // Create a new map of values, where column names are the keys
192 ContentValues values = TestDb.createNorthPoleLocationValues();
193
194 Uri locationUri = mContext.getContentResolver().
195 insert(LocationEntry.CONTENT_URI, values);
196 long locationRowId = ContentUris.parseId(locationUri);
197
198 // Verify we got a row back.
199 assertTrue(locationRowId != -1);
200 Log.d(LOG_TAG, "New row id: " + locationRowId);
201
202 ContentValues updatedValues = new ContentValues(values);
203 updatedValues.put(LocationEntry._ID, locationRowId);
204 updatedValues.put(LocationEntry.COLUMN_CITY_NAME, "Santa's Village");
205
206 int count = mContext.getContentResolver().update(
207 LocationEntry.CONTENT_URI, updatedValues, LocationEntry._ID + "= ?",
208 new String[] { Long.toString(locationRowId)});
209
210 assertEquals(count, 1);
211
212 // A cursor is your primary interface to the query results.
213 Cursor cursor = mContext.getContentResolver().query(
214 LocationEntry.buildLocationUri(locationRowId),
215 null,
216 null, // Columns for the "where" clause
217 null, // Values for the "where" clause
218 null // sort order
219 );
220
221 TestDb.validateCursor(cursor, updatedValues);
222 }
223
224 // Make sure we can still delete after adding/updating stuff
225 public void testDeleteRecordsAtEnd() {
226 deleteAllRecords();
227 }
228
229
230
231 // The target api annotation is needed for the call to keySet -- we wouldn't want
232 // to use this in our app, but in a test it's fine to assume a higher target.
233 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
234 void addAllContentValues(ContentValues destination, ContentValues source) {
235 for (String key : source.keySet()) {
236 destination.put(key, source.getAsString(key));
237 }
238 }
239 }