Skip to content

Commit

Permalink
Attempt to fix the connected tests
Browse files Browse the repository at this point in the history
  • Loading branch information
hb0 committed Mar 19, 2024
1 parent ab9b347 commit 094ad2b
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 43 deletions.
13 changes: 13 additions & 0 deletions datacapturing/src/androidTest/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,18 @@
android:process=":persistence_process"
android:syncable="true"
tools:replace="android:authorities"/>

<!-- Some connected Android tests needs this to create a test account, or else we get -->
<!-- SecurityException: ... cannot explicitly add accounts of type: ... -->
<service android:name="de.cyface.synchronization.CyfaceAuthenticatorService"
android:exported="false"
android:process=":sync"> <!-- should be fine to use the sync process -->
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data
android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
</service>
</application>
</manifest>
115 changes: 115 additions & 0 deletions persistence/src/androidTest/java/de/cyface/persistence/TestUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright 2017 Cyface GmbH
*
* This file is part of the Cyface SDK for Android.
*
* The Cyface SDK for Android is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Cyface SDK for Android is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the Cyface SDK for Android. If not, see <http://www.gnu.org/licenses/>.
*/
package de.cyface.persistence;

import static junit.framework.TestCase.fail;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.provider.BaseColumns;

import de.cyface.utils.Validate;

/**
* A utility class with static methods for supporting tests on the persistence code.
*
* @author Klemens Muthmann
* @version 2.0.3
* @since 1.0.0
*/
class TestUtils {

static final String AUTHORITY = "de.cyface.persistence.test.provider";

static long create(final ContentResolver mockResolver, final Uri contentUri, final ContentValues entry) {
final Uri result = mockResolver.insert(contentUri, entry);
Validate.notNull(result);
assertThat("Unable to create new entry.", result.getLastPathSegment(), is(not("-1")));
Validate.notNull(result.getLastPathSegment());
long identifier = Long.parseLong(result.getLastPathSegment());
assertThat("Entry inserted under wrong id.", identifier > 0L, is(true));
return identifier;
}

static void read(final ContentResolver mockResolver, final Uri contentUri, final ContentValues entry) {
try (Cursor cursor = mockResolver.query(contentUri, null, null, null, null);) {
List<ContentValues> fixture = new ArrayList<>();
fixture.add(entry);
Validate.notNull(cursor);
TestUtils.compareCursorWithValues(cursor, fixture);
}
}

static void update(final ContentResolver mockResolver, final Uri contentUri, final long identifier,
final String columnName, final double changedValue) {
ContentValues changedValues = new ContentValues();
changedValues.put(columnName, changedValue);

final int rowsUpdated = mockResolver.update(contentUri, changedValues, BaseColumns._ID + "=?",
new String[] {Long.valueOf(identifier).toString()});
assertEquals("Update of rotation point was unsuccessful.", 1, rowsUpdated);
}

static void delete(final ContentResolver mockResolver, final Uri contentUri, final long identifier) {
final int rowsDeleted = mockResolver.delete(contentUri, BaseColumns._ID + "=?",
new String[] {String.valueOf(identifier)});
assertEquals("Delete was unsuccessful for uri " + contentUri, 1, rowsDeleted);
}

static int count(final ContentResolver mockResolver, final Uri contentUri) {
final Cursor cursor = mockResolver.query(contentUri, null, null, null, null);
Validate.notNull(cursor);
return cursor.getCount();
}

private static void compareCursorWithValues(final Cursor cursor, final List<ContentValues> contentValues) {
assertThat(contentValues.size() <= cursor.getCount(), is(equalTo(true)));
for (ContentValues values : contentValues) {
cursor.moveToNext();
for (String key : values.keySet()) {
int cursorColumnIndex = cursor.getColumnIndex(key);
assertNotEquals(cursorColumnIndex, -1);
int dataType = cursor.getType(cursorColumnIndex);
switch (dataType) {
case Cursor.FIELD_TYPE_FLOAT:
assertEquals(values.getAsDouble(key), cursor.getDouble(cursorColumnIndex), 0.01);
break;
case Cursor.FIELD_TYPE_INTEGER:
assertEquals((long)values.getAsLong(key), cursor.getLong(cursorColumnIndex));
break;
case Cursor.FIELD_TYPE_STRING:
assertEquals(values.getAsString(key), cursor.getString(cursorColumnIndex));
default:
fail();
}
}
}
}
}
42 changes: 0 additions & 42 deletions persistence/src/test/java/de/cyface/persistence/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,47 +70,5 @@ private static void compareCursorWithValues(final Cursor cursor, final List<Cont
}
}
}

}

static long create(final ContentResolver mockResolver, final Uri contentUri, final ContentValues entry) {
final Uri result = mockResolver.insert(contentUri, entry);
Validate.notNull(result);
assertThat("Unable to create new entry.", result.getLastPathSegment(), is(not("-1")));
Validate.notNull(result.getLastPathSegment());
long identifier = Long.parseLong(result.getLastPathSegment());
assertThat("Entry inserted under wrong id.", identifier > 0L, is(true));
return identifier;
}

static void read(final ContentResolver mockResolver, final Uri contentUri, final ContentValues entry) {
try (Cursor cursor = mockResolver.query(contentUri, null, null, null, null);) {
List<ContentValues> fixture = new ArrayList<>();
fixture.add(entry);
Validate.notNull(cursor);
TestUtils.compareCursorWithValues(cursor, fixture);
}
}

static void update(final ContentResolver mockResolver, final Uri contentUri, final long identifier,
final String columnName, final double changedValue) {
ContentValues changedValues = new ContentValues();
changedValues.put(columnName, changedValue);

final int rowsUpdated = mockResolver.update(contentUri, changedValues, BaseColumns._ID + "=?",
new String[] {Long.valueOf(identifier).toString()});
assertEquals("Update of rotation point was unsuccessful.", 1, rowsUpdated);
}

static void delete(final ContentResolver mockResolver, final Uri contentUri, final long identifier) {
final int rowsDeleted = mockResolver.delete(contentUri, BaseColumns._ID + "=?",
new String[] {String.valueOf(identifier)});
assertEquals("Delete was unsuccessful for uri " + contentUri, 1, rowsDeleted);
}

static int count(final ContentResolver mockResolver, final Uri contentUri) {
final Cursor cursor = mockResolver.query(contentUri, null, null, null, null);
Validate.notNull(cursor);
return cursor.getCount();
}
}
25 changes: 25 additions & 0 deletions synchronization/src/androidTest/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,30 @@
android:process=":persistence_process"
android:syncable="true"
tools:replace="android:authorities"/>

<!-- Some connected synchronization Android tests need this for the test sync to start -->
<service
android:name="de.cyface.synchronization.CyfaceSyncService"
android:exported="false"
android:process=":sync">
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/sync_adapter" />
</service>
<!-- Some connected Android tests need this to create a test account, or else we get -->
<!-- SecurityException: ... cannot explicitly add accounts of type: ... -->
<service android:name="de.cyface.synchronization.CyfaceAuthenticatorService"
android:exported="false"
android:process=":sync"> <!-- should be fine to use the sync process -->
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data
android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
</service>
</application>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package de.cyface.synchronization;

import static de.cyface.synchronization.CyfaceSyncService.AUTH_TOKEN_TYPE;
import static de.cyface.synchronization.TestUtils.ACCOUNT_TYPE;
import static de.cyface.synchronization.TestUtils.AUTHORITY;
import static de.cyface.synchronization.TestUtils.TEST_API_URL;
Expand Down Expand Up @@ -101,7 +102,7 @@ public void testGetAuthToken() throws NetworkErrorException {

// Act
// Explicitly calling CyfaceAuthenticator.getAuthToken(), see its documentation
Bundle bundle = new CyfaceAuthenticator(context).getAuthToken(null, requestAccount, Constants.AUTH_TOKEN_TYPE,
Bundle bundle = new CyfaceAuthenticator(context).getAuthToken(null, requestAccount, AUTH_TOKEN_TYPE,
null);

// Assert
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright 2019 Cyface GmbH
*
* This file is part of the Cyface SDK for Android.
*
* The Cyface SDK for Android is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Cyface SDK for Android is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the Cyface SDK for Android. If not, see <http://www.gnu.org/licenses/>.
*/
package de.cyface.synchronization;

/**
* Contains utility methods and constants required by the tests within the synchronization project.
*
* @author Klemens Muthmann
* @author Armin Schnabel
* @version 2.4.0
* @since 2.1.0
*/
public final class TestUtils {
/**
* The tag used to identify Logcat messages from this module.
*/
final static String TAG = Constants.TAG + ".test";
/**
* The content provider authority used during tests. This must be the same as in the manifest and the authenticator
* configuration.
*/
final static String AUTHORITY = "de.cyface.synchronization.test.provider";
/**
* The account type used during testing. This must be the same as in the authenticator configuration.
*/
final static String ACCOUNT_TYPE = "de.cyface.synchronization.test";
/**
* For manual testing this can be replaced with an username available at {@link #TEST_API_URL}.
* <p>
* Never use actual APIs credentials in automated tests.
*/
final static String DEFAULT_USERNAME = "REPLACE_WITH_USERNAME";
/**
* For manual testing this can be replaced with a password available at {@link #TEST_API_URL}.
* <p>
* Never use actual APIs credentials in automated tests.
*/
final static String DEFAULT_PASSWORD = "REPLACE_WITH_PASSWORD";
/**
* For manual testing this can be replaced with a path to an API available for testing.
* <p>
* Never use actual APIs in automated tests.
*/
@SuppressWarnings("unused") // because this is used in the cyface flavour
final static String TEST_API_URL = "https://replace.with/url"; // never use a non-numeric port here!
}

0 comments on commit 094ad2b

Please sign in to comment.