Messaging: Remove tests

Nobody runs them anyway

Change-Id: I2b07847509269af31430abc6cb0fb190f08d45f9
This commit is contained in:
Michael W
2024-12-07 21:03:02 +01:00
parent 5ce3a1b2db
commit f3863c9a39
68 changed files with 5 additions and 8356 deletions

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 The Android Open Source Project
Copyright (C) 2024 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -297,15 +298,6 @@
android:value="com.android.messaging.ui.conversation.ConversationActivity" />
</activity>
<!-- Test activity that we use to host fragments/views. Unfortunately, apparently necessary
because Android framework test cases want activity to be in the instrumented package.
See http://developer.android.com/reference/android/test/ActivityInstrumentationTestCase2.html
-->
<activity
android:name=".ui.TestActivity"
android:configChanges="orientation|screenSize|keyboardHidden">
</activity>
<activity
android:name=".ui.debug.DebugMmsConfigActivity"
android:configChanges="orientation|screenSize|keyboardHidden"

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/test_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:id="@+id/test_content"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>

View File

@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,7 +45,6 @@ import com.android.messaging.util.LogUtil;
import com.android.messaging.util.OsUtil;
import com.android.messaging.util.PhoneUtils;
import com.android.messaging.util.Trace;
import com.google.common.annotations.VisibleForTesting;
import java.io.File;
import java.lang.Thread.UncaughtExceptionHandler;
@@ -56,32 +56,13 @@ public class BugleApplication extends Application implements UncaughtExceptionHa
private static final String TAG = LogUtil.BUGLE_TAG;
private UncaughtExceptionHandler sSystemUncaughtExceptionHandler;
private static boolean sRunningTests = false;
@VisibleForTesting
protected static void setTestsRunning() {
sRunningTests = true;
}
/**
* @return true if we're running unit tests.
*/
public static boolean isRunningTests() {
return sRunningTests;
}
@Override
public void onCreate() {
Trace.beginSection("app.onCreate");
super.onCreate();
// Note onCreate is called in both test and real application environments
if (!sRunningTests) {
// Only create the factory if not running tests
FactoryImpl.register(getApplicationContext(), this);
} else {
LogUtil.e(TAG, "BugleApplication.onCreate: FactoryImpl.register skipped for test run");
}
FactoryImpl.register(getApplicationContext(), this);
sSystemUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);

View File

@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +24,6 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
import com.android.messaging.BugleApplication;
import com.android.messaging.R;
import com.android.messaging.datamodel.data.ConversationListItemData;
import com.android.messaging.datamodel.data.MessageData;
@@ -31,7 +31,6 @@ import com.android.messaging.datamodel.data.ParticipantData;
import com.android.messaging.util.Assert;
import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
import com.android.messaging.util.LogUtil;
import com.google.common.annotations.VisibleForTesting;
/**
* TODO: Open Issues:
@@ -586,18 +585,6 @@ public class DatabaseHelper extends SQLiteOpenHelper {
mApplicationContext = context;
}
/**
* Test method that always instantiates a new DatabaseHelper instance. This should
* be used ONLY by the tests and never by the real application.
* @param context Test context.
* @return Brand new DatabaseHelper instance.
*/
@VisibleForTesting
static DatabaseHelper getNewInstanceForTest(final Context context) {
Assert.isTrue(BugleApplication.isRunningTests());
return new DatabaseHelper(context);
}
/**
* Get the (singleton) instance of @{link DatabaseWrapper}.
* <p>The database is always opened as a writeable database.

View File

@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +27,6 @@ import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.text.TextUtils;
import com.android.messaging.BugleApplication;
import com.android.messaging.Factory;
import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns;
import com.android.messaging.datamodel.DatabaseHelper.ConversationParticipantsColumns;
@@ -35,7 +35,6 @@ import com.android.messaging.datamodel.data.ConversationListItemData;
import com.android.messaging.datamodel.data.ConversationMessageData;
import com.android.messaging.datamodel.data.MessageData;
import com.android.messaging.datamodel.data.ParticipantData;
import com.android.messaging.util.Assert;
import com.android.messaging.util.LogUtil;
import com.android.messaging.util.OsUtil;
import com.android.messaging.util.PhoneUtils;
@@ -244,12 +243,6 @@ public class MessagingContentProvider extends ContentProvider {
super();
}
@VisibleForTesting
public void setDatabaseForTest(final DatabaseWrapper db) {
Assert.isTrue(BugleApplication.isRunningTests());
mDatabaseWrapper = db;
}
private DatabaseWrapper getDatabaseWrapper() {
if (mDatabaseWrapper == null) {
mDatabaseWrapper = mDatabaseHelper.getDatabase();

View File

@@ -1,88 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui;
import android.app.Fragment;
import android.os.Bundle;
import androidx.fragment.app.FragmentActivity;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import com.android.messaging.R;
import com.android.messaging.util.LogUtil;
import com.google.common.annotations.VisibleForTesting;
/**
* An empty activity that can be used to host a fragment or view for unit testing purposes. Lives in
* app code vs test code due to requirement of ActivityInstrumentationTestCase2.
*/
public class TestActivity extends FragmentActivity {
private FragmentEventListener mFragmentEventListener;
public interface FragmentEventListener {
public void onAttachFragment(Fragment fragment);
}
@Override
protected void onCreate(final Bundle bundle) {
super.onCreate(bundle);
if (bundle != null) {
// The test case may have configured the fragment, and recreating the activity will
// lose that configuration. The real activity is the only activity that would know
// how to reapply that configuration.
throw new IllegalStateException("TestActivity cannot get recreated");
}
// There is a race condition, but this often makes it possible for tests to run with the
// key guard up
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
setContentView(R.layout.test_activity);
}
@VisibleForTesting
public void setFragment(final Fragment fragment) {
LogUtil.i(LogUtil.BUGLE_TAG, "TestActivity.setFragment");
getFragmentManager()
.beginTransaction()
.replace(R.id.test_content, fragment)
.commit();
getFragmentManager().executePendingTransactions();
}
@VisibleForTesting
public void setView(final View view) {
LogUtil.i(LogUtil.BUGLE_TAG, "TestActivity.setView");
((FrameLayout) findViewById(R.id.test_content)).addView(view);
}
@Override
public void onAttachFragment(final Fragment fragment) {
if (mFragmentEventListener != null) {
mFragmentEventListener.onAttachFragment(fragment);
}
}
public void setFragmentEventListener(final FragmentEventListener fragmentEventListener) {
mFragmentEventListener = fragmentEventListener;
}
}

View File

@@ -1,45 +0,0 @@
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package {
default_team: "trendy_team_messages",
// See: http://go/android-license-faq
default_applicable_licenses: [
"Android-Apache-2.0",
],
}
android_test {
name: "messagingtests",
srcs: ["src/**/*.java"],
instrumentation_for: "messaging",
optimize: {
enabled: false,
},
sdk_version: "current",
test_suites: ["general-tests"],
certificate: "platform",
static_libs: [
"mockito-target",
"androidx.test.rules",
],
libs: [
"android.test.mock.stubs",
"android.test.runner.stubs",
"android.test.base.stubs",
],
data: [
":messaging",
],
}

View File

@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.messaging.test" >
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="29"/>
<application android:label="Messaging Tests" >
<uses-library android:name="android.test.runner" />
</application>
<instrumentation
android:label="Messaging Tests"
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.android.messaging"
android:windowSoftInputMode="stateHidden|adjustResize" />
</manifest>

View File

@@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2019 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<configuration description="Runs Messaging Tests.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-instrumentation" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="messagingtests.apk" />
<option name="test-file-name" value="messaging.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.messaging.test" />
<option name="runner" value="android.test.InstrumentationTestRunner" />
</test>
</configuration>

View File

@@ -1,59 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging;
import android.content.Context;
import android.test.AndroidTestCase;
/*
* Base class for service tests that takes care of housekeeping that is common amongst basic test
* cases.
*/
public abstract class BugleTestCase extends AndroidTestCase {
static {
// Set flag during loading of test cases to prevent application initialization starting
setTestsRunning();
}
public static void setTestsRunning() {
BugleApplication.setTestsRunning();
}
@Override
protected void setUp() throws Exception {
super.setUp();
TestUtil.testSetup(super.getContext(), this);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
TestUtil.testTeardown(this);
}
@Override
public Context getContext() {
// This doesn't really get the "application context" - just the fake context
// that the factory has been initialized with for each test case.
return Factory.get().getApplicationContext();
}
public Context getTestContext() {
return super.getContext();
}
}

View File

@@ -1,177 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging;
import android.content.ContentProvider;
import android.content.ContentProviderClient;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import androidx.collection.SimpleArrayMap;
import android.text.TextUtils;
import com.android.messaging.datamodel.FakeCursor;
import com.android.messaging.util.LogUtil;
import java.util.ArrayList;
public class FakeContentProvider extends ContentProvider {
private static class ContentOverride {
private final String uri;
private final String where;
private final String args;
private final String[] columns;
private final Object[][] data;
ContentOverride(final String uri, final String where, final String args,
final String[] columns, final Object[][] data) {
this.uri = uri;
this.where = where;
this.args = args;
this.columns = columns;
this.data = data;
}
boolean match(final String uri, final String where, final String[] args) {
if (!this.uri.equals(uri) || !TextUtils.equals(this.where, where)) {
return false;
}
if (this.args == null || args == null) {
return this.args == null && args == null;
}
return this.args.equals(TextUtils.join(";", args));
}
}
private final Context mGlobalContext;
private final ArrayList<ContentOverride> mOverrides = new ArrayList<ContentOverride>();
private final SimpleArrayMap<String, String> mTypes = new SimpleArrayMap<String, String>();
private final ContentProviderClient mProvider;
private final Uri mUri;
public FakeContentProvider(final Context context, final Uri uri, final boolean canDelegate) {
mGlobalContext = context;
mUri = uri;
if (canDelegate) {
mProvider = mGlobalContext.getContentResolver().acquireContentProviderClient(mUri);
} else {
mProvider = null;
}
ProviderInfo providerInfo = new ProviderInfo();
providerInfo.authority = uri.getAuthority();
this.attachInfo(mGlobalContext, providerInfo);
}
public void addOverrideData(final Uri uri, final String where, final String args,
final String[] columns, final Object[][] data) {
mOverrides.add(new ContentOverride(uri.toString(), where, args, columns, data));
}
public void addOverrideType(final Uri uri, final String type) {
mTypes.put(uri.toString(), type);
}
@Override
public boolean onCreate() {
return false;
}
@Override
public void shutdown() {
if (mProvider != null) {
mProvider.release();
}
}
@Override
public Cursor query(final Uri uri, final String[] projection, final String selection,
final String[] selectionArgs, final String sortOrder) {
LogUtil.w(LogUtil.BUGLE_TAG, "FakeContentProvider: query " + uri.toString()
+ " for " + (projection == null ? null : TextUtils.join(",", projection))
+ " where " + selection
+ " with " + (selectionArgs == null ? null : TextUtils.join(";", selectionArgs)));
for(final ContentOverride content : mOverrides) {
if (content.match(uri.toString(), selection, selectionArgs)) {
return new FakeCursor(projection, content.columns, content.data);
}
}
if (mProvider != null) {
try {
LogUtil.w(LogUtil.BUGLE_TAG, "FakeContentProvider: delgating");
final Cursor cursor = mProvider.query(uri, projection, selection, selectionArgs,
sortOrder);
LogUtil.w(LogUtil.BUGLE_TAG, "FakeContentProvider: response size "
+ cursor.getCount() + " contains " + TextUtils.join(",",
cursor.getColumnNames()) + " type(0) " + cursor.getType(0));
return cursor;
} catch (final RemoteException e) {
e.printStackTrace();
}
}
return null;
}
@Override
public String getType(final Uri uri) {
String type = mTypes.get(uri.toString());
if (type == null) {
try {
type = mProvider.getType(uri);
} catch (final RemoteException e) {
e.printStackTrace();
}
}
return type;
}
@Override
public Uri insert(final Uri uri, final ContentValues values) {
// TODO: Add code to track insert operations and return correct status
throw new UnsupportedOperationException();
}
@Override
public int delete(final Uri uri, final String selection, final String[] selectionArgs) {
// TODO: Add code to track delete operations and return correct status
throw new UnsupportedOperationException();
}
@Override
public int update(final Uri uri, final ContentValues values, final String selection,
final String[] selectionArgs) {
// TODO: Add code to track update operations and return correct status
throw new UnsupportedOperationException();
}
public Bundle call(final String callingPkg, final String method, final String arg,
final Bundle extras) {
return null;
}
}

View File

@@ -1,101 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.test.RenamingDelegatingContext;
import android.test.mock.MockContentResolver;
import android.util.Log;
import java.util.ArrayList;
public class FakeContext extends RenamingDelegatingContext {
private static final String TAG = "FakeContext";
public interface FakeContextHost {
public String getServiceClassName();
public void startServiceForStub(Intent intent);
public void onStartCommandForStub(Intent intent, int flags, int startid);
}
ArrayList<Intent> mStartedIntents;
boolean mServiceStarted = false;
private final FakeContextHost mService;
private final MockContentResolver mContentResolver;
public FakeContext(final Context context, final FakeContextHost service) {
super(context, "test_");
mService = service;
mStartedIntents = new ArrayList<Intent>();
mContentResolver = new MockContentResolver();
}
public FakeContext(final Context context) {
this(context, null);
}
public ArrayList<Intent> extractIntents() {
final ArrayList<Intent> intents = mStartedIntents;
mStartedIntents = new ArrayList<Intent>();
return intents;
}
@Override
public ComponentName startService(final Intent intent) {
// Record that a startService occurred with the intent that was passed.
Log.d(TAG, "MockContext receiving startService. intent=" + intent.toString());
mStartedIntents.add(intent);
if (mService == null) {
return super.startService(intent);
} else if (intent.getComponent() != null &&
intent.getComponent().getClassName().equals(mService.getServiceClassName())) {
if (!mServiceStarted) {
Log.d(TAG, "MockContext first start service.");
mService.startServiceForStub(intent);
} else {
Log.d(TAG, "MockContext not first start service. Calling onStartCommand.");
mService.onStartCommandForStub(intent, 0, 0);
}
mServiceStarted = true;
return new ComponentName(this, intent.getComponent().getClassName());
}
return null;
}
@Override
public ContentResolver getContentResolver() {
// If you want to use a content provider in your test, then you need to add it
// explicitly.
return mContentResolver;
}
public void addContentProvider(final String name, final ContentProvider provider) {
mContentResolver.addProvider(name, provider);
}
public void addDefaultProvider(final Context context, final Uri uri) {
final FakeContentProvider provider = new FakeContentProvider(context, uri, true);
mContentResolver.addProvider(uri.getAuthority(), provider);
}
}

View File

@@ -1,290 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging;
import android.content.ContentProvider;
import android.content.Context;
import android.net.Uri;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import com.android.messaging.datamodel.DataModel;
import com.android.messaging.datamodel.MemoryCacheManager;
import com.android.messaging.datamodel.ParticipantRefresh.ContactContentObserver;
import com.android.messaging.datamodel.media.MediaCacheManager;
import com.android.messaging.datamodel.media.MediaResourceManager;
import com.android.messaging.sms.ApnDatabase;
import com.android.messaging.sms.BugleCarrierConfigValuesLoader;
import com.android.messaging.ui.UIIntents;
import com.android.messaging.util.Assert;
import com.android.messaging.util.BugleGservices;
import com.android.messaging.util.BuglePrefs;
import com.android.messaging.util.FakeBugleGservices;
import com.android.messaging.util.FakeBuglePrefs;
import com.android.messaging.util.MediaUtil;
import com.android.messaging.util.OsUtil;
import com.android.messaging.util.PhoneUtils;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.util.ArrayList;
import java.util.List;
public class FakeFactory extends Factory {
private Context mContext;
private FakeContext mFakeContext;
private BugleGservices mBugleGservices;
private BuglePrefs mBuglePrefs;
private DataModel mDataModel;
private UIIntents mUIIntents;
private MemoryCacheManager mMemoryCacheManager;
private MediaResourceManager mMediaResourceManager;
private MediaCacheManager mMediaCacheManager;
@Mock protected PhoneUtils mPhoneUtils;
private MediaUtil mMediaUtil;
private BugleCarrierConfigValuesLoader mCarrierConfigValuesLoader;
private FakeFactory() {
}
public static FakeFactory registerWithFakeContext(final Context context,
final FakeContext fake) {
// In tests we currently NEVER run the application/factory initialization
Assert.isTrue(!sRegistered);
Assert.isTrue(!sInitialized);
final FakeFactory factory = new FakeFactory();
Factory.setInstance(factory);
// At this point Factory is published. Services can now get initialized and depend on
// Factory.get().
factory.mContext = context;
factory.mFakeContext = fake;
factory.mMediaResourceManager = Mockito.mock(MediaResourceManager.class);
factory.mBugleGservices = new FakeBugleGservices();
factory.mBuglePrefs = new FakeBuglePrefs();
factory.mPhoneUtils = Mockito.mock(PhoneUtils.class);
ApnDatabase.initializeAppContext(context);
Mockito.when(factory.mPhoneUtils.getCanonicalBySystemLocale(Matchers.anyString()))
.thenAnswer(new Answer<String>() {
@Override
public String answer(final InvocationOnMock invocation) throws Throwable {
final Object[] args = invocation.getArguments();
return (String) args[0];
}
}
);
Mockito.when(factory.mPhoneUtils.getCanonicalBySimLocale(Matchers.anyString())).thenAnswer(
new Answer<String>() {
@Override
public String answer(final InvocationOnMock invocation) throws Throwable {
final Object[] args = invocation.getArguments();
return (String) args[0];
}
}
);
Mockito.when(factory.mPhoneUtils.formatForDisplay(Matchers.anyString())).thenAnswer(
new Answer<String>() {
@Override
public String answer(final InvocationOnMock invocation) throws Throwable {
return (String) invocation.getArguments()[0];
}
}
);
if (OsUtil.isAtLeastL_MR1()) {
Mockito.when(factory.mPhoneUtils.toLMr1()).thenReturn(
new PhoneUtils.LMr1() {
@Override
public SubscriptionInfo getActiveSubscriptionInfo() {
return null;
}
@Override
public List<SubscriptionInfo> getActiveSubscriptionInfoList() {
// Return empty list
return new ArrayList<>();
}
@Override
public void registerOnSubscriptionsChangedListener(
final SubscriptionManager.OnSubscriptionsChangedListener listener) {
}
}
);
}
// By default only allow reading of system settings (that we provide) - can delegate
// to real provider if required.
final FakeContentProvider settings = new FakeContentProvider(context,
Settings.System.CONTENT_URI, false);
settings.addOverrideData(Settings.System.CONTENT_URI, "name=?", "time_12_24",
new String[] { "value" }, new Object[][] { { "12" } });
settings.addOverrideData(Settings.System.CONTENT_URI, "name=?", "sound_effects_enabled",
new String[] { "value" }, new Object[][] { { 1 } });
factory.withProvider(Settings.System.CONTENT_URI, settings);
return factory;
}
public static FakeFactory register(final Context applicationContext) {
final FakeContext context = new FakeContext(applicationContext);
return registerWithFakeContext(applicationContext, context);
}
public static FakeFactory registerWithoutFakeContext(final Context applicationContext) {
return registerWithFakeContext(applicationContext, null);
}
@Override
public void onRequiredPermissionsAcquired() {
}
@Override
public Context getApplicationContext() {
return ((mFakeContext != null) ? mFakeContext : mContext );
}
@Override
public DataModel getDataModel() {
return mDataModel;
}
@Override
public BugleGservices getBugleGservices() {
return mBugleGservices;
}
@Override
public BuglePrefs getApplicationPrefs() {
return mBuglePrefs;
}
@Override
public BuglePrefs getWidgetPrefs() {
return mBuglePrefs;
}
@Override
public BuglePrefs getSubscriptionPrefs(final int subId) {
return mBuglePrefs;
}
@Override
public UIIntents getUIIntents() {
return mUIIntents;
}
@Override
public MemoryCacheManager getMemoryCacheManager() {
return mMemoryCacheManager;
}
@Override
public MediaResourceManager getMediaResourceManager() {
return mMediaResourceManager;
}
@Override
public MediaCacheManager getMediaCacheManager() {
return mMediaCacheManager;
}
@Override
public PhoneUtils getPhoneUtils(final int subId) {
return mPhoneUtils;
}
@Override
public MediaUtil getMediaUtil() {
return mMediaUtil;
}
@Override
public BugleCarrierConfigValuesLoader getCarrierConfigValuesLoader() {
return mCarrierConfigValuesLoader;
}
@Override
public ContactContentObserver getContactContentObserver() {
return null;
}
@Override
public void reclaimMemory() {
}
@Override
public void onActivityResume() {
}
public FakeFactory withDataModel(final DataModel dataModel) {
this.mDataModel = dataModel;
return this;
}
public FakeFactory withUIIntents(final UIIntents uiIntents) {
this.mUIIntents = uiIntents;
return this;
}
public FakeFactory withMemoryCacheManager(final MemoryCacheManager memoryCacheManager) {
this.mMemoryCacheManager = memoryCacheManager;
return this;
}
public FakeFactory withBugleGservices(final BugleGservices bugleGservices) {
this.mBugleGservices = bugleGservices;
return this;
}
public FakeFactory withMediaCacheManager(final MediaCacheManager mediaCacheManager) {
this.mMediaCacheManager = mediaCacheManager;
return this;
}
public FakeFactory withProvider(final Uri uri, final ContentProvider provider) {
if (mFakeContext != null) {
mFakeContext.addContentProvider(uri.getAuthority(), provider);
}
return this;
}
public FakeFactory withDefaultProvider(final Uri uri) {
if (mFakeContext != null) {
mFakeContext.addDefaultProvider(this.mContext, uri);
}
return this;
}
public FakeFactory withMediaUtil(final MediaUtil mediaUtil) {
this.mMediaUtil = mediaUtil;
return this;
}
public FakeFactory withCarrierConfigValuesLoader(
final BugleCarrierConfigValuesLoader carrierConfigValuesLoader) {
this.mCarrierConfigValuesLoader = carrierConfigValuesLoader;
return this;
}
}

View File

@@ -1,84 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
import android.os.PowerManager;
import android.test.InstrumentationTestCase;
import com.android.messaging.util.LogUtil;
import com.android.messaging.widget.BugleWidgetProvider;
import com.android.messaging.widget.WidgetConversationProvider;
import junit.framework.TestCase;
import org.mockito.MockitoAnnotations;
/**
* Helpers that can be called from all test base classes to 'reset' state and prevent as much as
* possible having side effects leak from one test to another.
*/
public class TestUtil {
public static void testSetup(final Context context, final TestCase testCase) {
haltIfTestsAreNotAbleToRun(context);
// Workaround to get mockito to work.
// See https://code.google.com/p/dexmaker/issues/detail?id=2. TODO: Apparently
// solvable by using a different runner.
System.setProperty("dexmaker.dexcache",
context.getCacheDir().getPath());
// Initialize @Mock objects.
MockitoAnnotations.initMocks(testCase);
// Tests have to explicitly override this
Factory.setInstance(null);
}
public static void testTeardown(final TestCase testCase) {
if (testCase instanceof InstrumentationTestCase) {
// Make sure the test case is finished running or we'll get NPEs when accessing
// Fragment.get()
((InstrumentationTestCase) testCase).getInstrumentation().waitForIdleSync();
}
Factory.setInstance(null);
}
private static void haltIfTestsAreNotAbleToRun(final Context context) {
final PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (!pm.isScreenOn()) {
// Ideally we could turn it on for you using the WindowManager, but we currently run
// the tests independently of the activity life cycle.
LogUtil.wtf(LogUtil.BUGLE_TAG, "You need to turn on your screen to run tests!");
}
final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int [] conversationWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context,
WidgetConversationProvider.class));
int [] conversationListWidgetIds = appWidgetManager.getAppWidgetIds(new
ComponentName(context, BugleWidgetProvider.class));
if ((conversationWidgetIds.length > 0) || (conversationListWidgetIds.length > 0)) {
// Currently widgets asynchronously access our content providers and singletons which
// interacts badly with our test setup and tear down.
LogUtil.wtf(LogUtil.BUGLE_TAG, "You currently can't reliably run unit tests" +
" with a Messaging widget on your desktop!");
}
}
}

View File

@@ -1,148 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.datamodel.binding.BindableData;
import com.android.messaging.datamodel.binding.Binding;
import com.android.messaging.datamodel.binding.BindingBase;
import com.android.messaging.datamodel.binding.ImmutableBindingRef;
/**
* Test binding
*/
@SmallTest
public class BindingTest extends BugleTestCase {
private static final Object TEST_DATA_ID = "myDataId";
private static final Object YOUR_DATA_ID = "yourDataId";
public void testBindingStartsUnbound() {
final Binding<TestBindableData> binding = BindingBase.createBinding(this);
assertNull(binding.getBindingId());
}
public void testDataStartsUnbound() {
final TestBindableData data = new TestBindableData(TEST_DATA_ID);
assertFalse(data.isBound());
}
public void testBindingUpdatesDataAndBindee() {
final Binding<TestBindableData> binding = BindingBase.createBinding(this);
final TestBindableData data = new TestBindableData(TEST_DATA_ID);
binding.bind(data);
assertTrue(binding.isBound());
assertEquals(binding.getData(), data);
assertTrue(data.isBound(binding.getBindingId()));
assertFalse(data.isBound("SomeRandomString"));
assertNotNull(binding.getBindingId());
assertFalse(data.mListenersUnregistered);
}
public void testRebindingFails() {
final Binding<TestBindableData> binding = BindingBase.createBinding(this);
final TestBindableData yours = new TestBindableData(YOUR_DATA_ID);
binding.bind(yours);
assertEquals(binding.getData(), yours);
assertTrue(yours.isBound(binding.getBindingId()));
final TestBindableData data = new TestBindableData(TEST_DATA_ID);
try {
binding.bind(data);
fail();
} catch (final IllegalStateException e) {
}
assertTrue(binding.isBound());
assertEquals(binding.getData(), yours);
assertTrue(yours.isBound(binding.getBindingId()));
}
public void testUnbindingClearsDataAndBindee() {
final Binding<TestBindableData> binding = BindingBase.createBinding(this);
final TestBindableData data = new TestBindableData(TEST_DATA_ID);
binding.bind(data);
assertTrue(data.isBound(binding.getBindingId()));
assertTrue(binding.isBound());
binding.unbind();
try {
final TestBindableData other = binding.getData();
fail();
} catch (final IllegalStateException e) {
}
assertFalse(data.isBound());
assertNull(binding.getBindingId());
assertTrue(data.mListenersUnregistered);
}
public void testUnbindingAndRebinding() {
final Binding<TestBindableData> binding = BindingBase.createBinding(this);
final TestBindableData yours = new TestBindableData(YOUR_DATA_ID);
binding.bind(yours);
assertEquals(binding.getData(), yours);
assertTrue(yours.isBound(binding.getBindingId()));
binding.unbind();
assertFalse(yours.isBound());
assertNull(binding.getBindingId());
final TestBindableData data = new TestBindableData(TEST_DATA_ID);
binding.bind(data);
assertEquals(binding.getData(), data);
assertTrue(data.isBound(binding.getBindingId()));
assertFalse(data.isBound("SomeRandomString"));
assertTrue(binding.isBound());
assertNotNull(binding.getBindingId());
}
public void testBindingReference() {
final Binding<TestBindableData> binding = BindingBase.createBinding(this);
final TestBindableData data = new TestBindableData(TEST_DATA_ID);
binding.bind(data);
assertEquals(binding.getData(), data);
assertTrue(data.isBound(binding.getBindingId()));
final ImmutableBindingRef<TestBindableData> bindingRef =
BindingBase.createBindingReference(binding);
assertEquals(bindingRef.getData(), data);
assertTrue(data.isBound(bindingRef.getBindingId()));
binding.unbind();
assertFalse(binding.isBound());
assertNull(binding.getBindingId());
assertFalse(bindingRef.isBound());
assertNull(bindingRef.getBindingId());
}
static class TestBindableData extends BindableData {
private final Object mDataId;
public boolean mListenersUnregistered;
public TestBindableData(final Object dataId) {
mDataId = dataId;
mListenersUnregistered = false;
}
@Override
public void unregisterListeners() {
mListenersUnregistered = true;
}
@Override
public boolean isBound() {
return super.isBound();
}
}
}

View File

@@ -1,103 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import org.mockito.Mock;
import java.util.HashSet;
import java.util.Set;
@SmallTest
public class BitmapPoolTest extends BugleTestCase {
private static final int POOL_SIZE = 5;
private static final int IMAGE_DIM = 1;
private static final String NAME = "BitmapPoolTest";
@Mock private MemoryCacheManager mockMemoryCacheManager;
@Override
protected void setUp() throws Exception {
super.setUp();
FakeFactory.register(getTestContext())
.withMemoryCacheManager(mockMemoryCacheManager);
}
private Set<Bitmap> fillPoolAndGetPoolContents(final BitmapPool pool, final int width,
final int height) {
final Set<Bitmap> returnedBitmaps = new HashSet<Bitmap>();
for (int i = 0; i < POOL_SIZE; i++) {
final Bitmap temp = pool.createOrReuseBitmap(width, height);
assertFalse(returnedBitmaps.contains(temp));
returnedBitmaps.add(temp);
}
for (final Bitmap b : returnedBitmaps) {
pool.reclaimBitmap(b);
}
assertTrue(pool.isFull(width, height));
return returnedBitmaps;
}
public void testCreateAndPutBackInPoolTest() {
final BitmapPool pool = new BitmapPool(POOL_SIZE, NAME);
final Bitmap bitmap = pool.createOrReuseBitmap(IMAGE_DIM, IMAGE_DIM);
assertFalse(bitmap.isRecycled());
assertFalse(pool.isFull(IMAGE_DIM, IMAGE_DIM));
pool.reclaimBitmap(bitmap);
// Don't recycle because the pool isn't full yet.
assertFalse(bitmap.isRecycled());
}
public void testCreateBeyondFullAndCheckReuseTest() {
final BitmapPool pool = new BitmapPool(POOL_SIZE, NAME);
final Set<Bitmap> returnedBitmaps =
fillPoolAndGetPoolContents(pool, IMAGE_DIM, IMAGE_DIM);
final Bitmap overflowBitmap = pool.createOrReuseBitmap(IMAGE_DIM, IMAGE_DIM);
assertFalse(overflowBitmap.isRecycled());
assertTrue(returnedBitmaps.contains(overflowBitmap));
}
/**
* Make sure that we have the correct options to create mutable for bitmap pool reuse.
*/
public void testAssertBitmapOptionsAreMutable() {
final BitmapFactory.Options options =
BitmapPool.getBitmapOptionsForPool(false, IMAGE_DIM, IMAGE_DIM);
assertTrue(options.inMutable);
}
public void testDecodeFromResourceBitmap() {
final BitmapPool pool = new BitmapPool(POOL_SIZE, NAME);
final BitmapFactory.Options options =
BitmapPool.getBitmapOptionsForPool(true, IMAGE_DIM, IMAGE_DIM);
final Resources resources = getContext().getResources();
final Bitmap resourceBitmap = pool.decodeSampledBitmapFromResource(
R.drawable.msg_bubble_incoming, resources, options, IMAGE_DIM, IMAGE_DIM);
assertNotNull(resourceBitmap);
assertTrue(resourceBitmap.getByteCount() > 0);
}
}

View File

@@ -1,52 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel;
import android.app.Service;
import android.test.ServiceTestCase;
import com.android.messaging.BugleTestCase;
import com.android.messaging.TestUtil;
/*
* Base class for service tests that takes care of housekeeping that is commong amongst our service
* test case.
*/
public abstract class BugleServiceTestCase<T extends Service> extends ServiceTestCase<T> {
static {
// Set flag during loading of test cases to prevent application initialization starting
BugleTestCase.setTestsRunning();
}
public BugleServiceTestCase(final Class<T> serviceClass) {
super(serviceClass);
}
@Override
protected void setUp() throws Exception {
super.setUp();
TestUtil.testSetup(getContext(), this);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
TestUtil.testTeardown(this);
}
}

View File

@@ -1,28 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
@SmallTest
public class ConversationListTest extends BugleTestCase {
public void testTesting() {
assertTrue(true);
}
}

View File

@@ -1,71 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.FakeFactory;
import com.android.messaging.datamodel.data.ConversationData;
import com.android.messaging.datamodel.data.ConversationData.ConversationDataListener;
import com.android.messaging.datamodel.data.ConversationListData;
import com.android.messaging.datamodel.data.ConversationListData.ConversationListDataListener;
import org.mockito.Mock;
public class DataModelTest extends BugleTestCase {
DataModel dataModel;
@Mock protected ConversationDataListener mockConversationDataListener;
@Mock protected ConversationListDataListener mockConversationListDataListener;
@Override
protected void setUp() throws Exception {
super.setUp();
FakeFactory factory = FakeFactory.register(mContext);
dataModel = new DataModelImpl(getTestContext());
factory.withDataModel(dataModel);
}
@SmallTest
public void testCreateConversationList() {
final ConversationListData list = dataModel.createConversationListData(getContext(),
mockConversationListDataListener, true);
assertTrue(list instanceof ConversationListData);
final ConversationData conv = dataModel.createConversationData(getContext(),
mockConversationDataListener, "testConversation");
assertTrue(conv instanceof ConversationData);
}
private static final String FOCUSED_CONV_ID = "focused_conv_id";
@SmallTest
public void testFocusedConversationIsObservable() {
dataModel.setFocusedConversation(FOCUSED_CONV_ID);
assertTrue(dataModel.isNewMessageObservable(FOCUSED_CONV_ID));
dataModel.setFocusedConversation(null);
assertFalse(dataModel.isNewMessageObservable(FOCUSED_CONV_ID));
}
@SmallTest
public void testConversationIsObservableInList() {
dataModel.setConversationListScrolledToNewestConversation(true);
assertTrue(dataModel.isNewMessageObservable(FOCUSED_CONV_ID));
dataModel.setConversationListScrolledToNewestConversation(false);
assertFalse(dataModel.isNewMessageObservable(FOCUSED_CONV_ID));
}
}

View File

@@ -1,161 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel;
import android.os.Bundle;
import android.test.mock.MockCursor;
import java.util.ArrayList;
/**
* A simple in memory fake cursor that can be used for UI tests.
*/
public class FakeCursor extends MockCursor {
private final ArrayList<Integer> mProjection;
private final String[] mColumnNamesOfData;
private final Object[][] mData;
private int mIndex;
public FakeCursor(final String[] projection, final String[] columnNames,
final Object[][] data) {
mColumnNamesOfData = columnNames;
mData = data;
mIndex = -1;
mProjection = new ArrayList<Integer>(projection.length);
for (final String column : projection) {
mProjection.add(getColumnIndex(column));
}
}
public Object getAt(final String columnName, final int row) {
final int dataIdx = getColumnIndex(columnName);
return (dataIdx < 0 || row < 0 || row >= mData.length) ? 0 : mData[row][dataIdx];
}
@Override
public int getCount() {
return mData.length;
}
@Override
public boolean isFirst() {
return mIndex == 0;
}
@Override
public boolean isLast() {
return mIndex == mData.length - 1;
}
@Override
public boolean moveToFirst() {
if (mData.length == 0) {
return false;
}
mIndex = 0;
return true;
}
@Override
public boolean moveToPosition(final int position) {
if (position < 0 || position >= mData.length) {
return false;
}
mIndex = position;
return true;
}
@Override
public int getPosition() {
return mIndex;
}
@Override
public boolean moveToPrevious() {
if (mIndex <= 0) {
return false;
}
mIndex--;
return true;
}
@Override
public boolean moveToNext() {
if (mIndex == mData.length - 1) {
return false;
}
mIndex++;
return true;
}
@Override
public int getColumnCount() {
return mColumnNamesOfData.length;
}
@Override
public int getColumnIndex(final String columnName) {
for (int i = 0 ; i < mColumnNamesOfData.length ; i++) {
if (mColumnNamesOfData[i].equals(columnName)) {
return i;
}
}
return -1;
}
@Override
public int getColumnIndexOrThrow(final String columnName) {
final int result = getColumnIndex(columnName);
if (result == -1) {
throw new IllegalArgumentException();
}
return result;
}
@Override
public String getString(final int columnIndex) {
final int dataIdx = mProjection.get(columnIndex);
final Object obj = (dataIdx < 0 ? null : mData[mIndex][dataIdx]);
return (obj == null ? null : obj.toString());
}
@Override
public int getInt(final int columnIndex) {
final int dataIdx = mProjection.get(columnIndex);
return (dataIdx < 0 ? 0 : (Integer) mData[mIndex][dataIdx]);
}
@Override
public long getLong(final int columnIndex) {
final int dataIdx = mProjection.get(columnIndex);
return (dataIdx < 0 ? 0 : (Long) mData[mIndex][dataIdx]);
}
@Override
public void close() {
}
@Override
public boolean isClosed() {
return false;
}
@Override
public Bundle getExtras() { return null; }
}

View File

@@ -1,245 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.test.RenamingDelegatingContext;
import com.android.messaging.datamodel.action.ActionService;
import com.android.messaging.datamodel.action.BackgroundWorker;
import com.android.messaging.datamodel.data.BlockedParticipantsData;
import com.android.messaging.datamodel.data.BlockedParticipantsData.BlockedParticipantsDataListener;
import com.android.messaging.datamodel.data.ContactListItemData;
import com.android.messaging.datamodel.data.ContactPickerData;
import com.android.messaging.datamodel.data.ContactPickerData.ContactPickerDataListener;
import com.android.messaging.datamodel.data.ConversationData;
import com.android.messaging.datamodel.data.ConversationData.ConversationDataListener;
import com.android.messaging.datamodel.data.ConversationListData;
import com.android.messaging.datamodel.data.ConversationListData.ConversationListDataListener;
import com.android.messaging.datamodel.data.DraftMessageData;
import com.android.messaging.datamodel.data.GalleryGridItemData;
import com.android.messaging.datamodel.data.LaunchConversationData;
import com.android.messaging.datamodel.data.LaunchConversationData.LaunchConversationDataListener;
import com.android.messaging.datamodel.data.MediaPickerData;
import com.android.messaging.datamodel.data.MessagePartData;
import com.android.messaging.datamodel.data.ParticipantData;
import com.android.messaging.datamodel.data.ParticipantListItemData;
import com.android.messaging.datamodel.data.PeopleAndOptionsData;
import com.android.messaging.datamodel.data.PeopleAndOptionsData.PeopleAndOptionsDataListener;
import com.android.messaging.datamodel.data.PeopleOptionsItemData;
import com.android.messaging.datamodel.data.SettingsData;
import com.android.messaging.datamodel.data.SettingsData.SettingsDataListener;
import com.android.messaging.datamodel.data.SubscriptionListData;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.datamodel.data.VCardContactItemData;
public class FakeDataModel extends DataModel {
private BackgroundWorker mWorker;
private ActionService mActionService;
private final DatabaseHelper mDatabaseHelper;
private ConversationListData mConversationListData;
private ContactPickerData mContactPickerData;
private MediaPickerData mMediaPickerData;
private PeopleAndOptionsData mPeopleAndOptionsData;
private SyncManager mSyncManager;
private SettingsData mSettingsData;
private DraftMessageData mDraftMessageData;
public FakeDataModel(final Context context) {
super();
if (context instanceof RenamingDelegatingContext) {
mDatabaseHelper = DatabaseHelper.getNewInstanceForTest(context);
} else {
mDatabaseHelper = null;
}
}
@Override
public BackgroundWorker getBackgroundWorkerForActionService() {
return mWorker;
}
public FakeDataModel withBackgroundWorkerForActionService(final BackgroundWorker worker) {
mWorker = worker;
return this;
}
public FakeDataModel withActionService(final ActionService ActionService) {
mActionService = ActionService;
return this;
}
public FakeDataModel withConversationListData(final ConversationListData conversationListData) {
mConversationListData = conversationListData;
return this;
}
public FakeDataModel withContactPickerData(final ContactPickerData contactPickerData) {
mContactPickerData = contactPickerData;
return this;
}
public FakeDataModel withMediaPickerData(final MediaPickerData mediaPickerData) {
mMediaPickerData = mediaPickerData;
return this;
}
public FakeDataModel withSyncManager(final SyncManager syncManager) {
mSyncManager = syncManager;
return this;
}
public FakeDataModel withPeopleAndOptionsData(final PeopleAndOptionsData peopleAndOptionsData) {
mPeopleAndOptionsData = peopleAndOptionsData;
return this;
}
public FakeDataModel withSettingsData(final SettingsData settingsData) {
mSettingsData = settingsData;
return this;
}
public FakeDataModel withDraftMessageData(final DraftMessageData draftMessageData) {
mDraftMessageData = draftMessageData;
return this;
}
@Override
public ConversationListData createConversationListData(final Context context,
final ConversationListDataListener listener, final boolean archivedMode) {
return mConversationListData;
}
@Override
public ConversationData createConversationData(final Context context,
final ConversationDataListener listener, final String conversationId) {
throw new IllegalStateException("Add withXXX or mock this method");
}
@Override
public ContactListItemData createContactListItemData() {
// This is a lightweight data holder object for each individual list item for which
// we don't perform any data request, so we can directly return a new instance.
return new ContactListItemData();
}
@Override
public ContactPickerData createContactPickerData(final Context context,
final ContactPickerDataListener listener) {
return mContactPickerData;
}
@Override
public MediaPickerData createMediaPickerData(final Context context) {
return mMediaPickerData;
}
@Override
public GalleryGridItemData createGalleryGridItemData() {
// This is a lightweight data holder object for each individual grid item for which
// we don't perform any data request, so we can directly return a new instance.
return new GalleryGridItemData();
}
@Override
public LaunchConversationData createLaunchConversationData(
final LaunchConversationDataListener listener) {
return new LaunchConversationData(listener);
}
@Override
public PeopleOptionsItemData createPeopleOptionsItemData(final Context context) {
return new PeopleOptionsItemData(context);
}
@Override
public PeopleAndOptionsData createPeopleAndOptionsData(final String conversationId,
final Context context, final PeopleAndOptionsDataListener listener) {
return mPeopleAndOptionsData;
}
@Override
public VCardContactItemData createVCardContactItemData(final Context context,
final MessagePartData data) {
return new VCardContactItemData(context, data);
}
@Override
public VCardContactItemData createVCardContactItemData(final Context context,
final Uri vCardUri) {
return new VCardContactItemData(context, vCardUri);
}
@Override
public ParticipantListItemData createParticipantListItemData(
final ParticipantData participant) {
return new ParticipantListItemData(participant);
}
@Override
public SubscriptionListData createSubscriptonListData(Context context) {
return new SubscriptionListData(context);
}
@Override
public SettingsData createSettingsData(Context context, SettingsDataListener listener) {
return mSettingsData;
}
@Override
public DraftMessageData createDraftMessageData(String conversationId) {
return mDraftMessageData;
}
@Override
public ActionService getActionService() {
return mActionService;
}
@Override
public SyncManager getSyncManager() {
return mSyncManager;
}
@Override
public DatabaseWrapper getDatabase() {
// Note this will crash unless the application context is redirected...
// This is by design so that tests do not inadvertently use the real database
return mDatabaseHelper.getDatabase();
}
@Override
void onCreateTables(final SQLiteDatabase db) {
TestDataFactory.createTestData(db);
}
@Override
public void onActivityResume() {
}
@Override
public void onApplicationCreated() {
}
@Override
public BlockedParticipantsData createBlockedParticipantsData(Context context,
BlockedParticipantsDataListener listener) {
return new BlockedParticipantsData(context, listener);
}
}

View File

@@ -1,91 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel;
import android.database.Cursor;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.util.ContactUtil;
@SmallTest
public class FrequentContactsCursorBuilderTest extends BugleTestCase {
private void verifyBuiltCursor(final Cursor expected, final Cursor actual) {
final int rowCount = expected.getCount();
final int columnCount = expected.getColumnCount();
assertEquals(rowCount, actual.getCount());
assertEquals(columnCount, actual.getColumnCount());
for (int i = 0; i < rowCount; i++) {
expected.moveToPosition(i);
actual.moveToPosition(i);
assertEquals(expected.getLong(ContactUtil.INDEX_DATA_ID),
actual.getLong(ContactUtil.INDEX_DATA_ID));
assertEquals(expected.getLong(ContactUtil.INDEX_CONTACT_ID),
actual.getLong(ContactUtil.INDEX_CONTACT_ID));
assertEquals(expected.getString(ContactUtil.INDEX_LOOKUP_KEY),
actual.getString(ContactUtil.INDEX_LOOKUP_KEY));
assertEquals(expected.getString(ContactUtil.INDEX_DISPLAY_NAME),
actual.getString(ContactUtil.INDEX_DISPLAY_NAME));
assertEquals(expected.getString(ContactUtil.INDEX_PHOTO_URI),
actual.getString(ContactUtil.INDEX_PHOTO_URI));
assertEquals(expected.getString(ContactUtil.INDEX_PHONE_EMAIL),
actual.getString(ContactUtil.INDEX_PHONE_EMAIL));
assertEquals(expected.getInt(ContactUtil.INDEX_PHONE_EMAIL_TYPE),
actual.getInt(ContactUtil.INDEX_PHONE_EMAIL_TYPE));
assertEquals(expected.getString(ContactUtil.INDEX_PHONE_EMAIL_LABEL),
actual.getString(ContactUtil.INDEX_PHONE_EMAIL_LABEL));
}
}
public void testIncompleteBuild() {
final FrequentContactsCursorBuilder builder = new FrequentContactsCursorBuilder();
assertNull(builder.build());
assertNull(builder.setFrequents(TestDataFactory.getStrequentContactsCursor()).build());
builder.resetBuilder();
assertNull(builder.build());
assertNull(builder.setAllContacts(TestDataFactory.getAllContactListCursor()).build());
}
public void testBuildOnce() {
final Cursor cursor = new FrequentContactsCursorBuilder()
.setAllContacts(TestDataFactory.getAllContactListCursor())
.setFrequents(TestDataFactory.getStrequentContactsCursor())
.build();
assertNotNull(cursor);
verifyBuiltCursor(TestDataFactory.getFrequentContactListCursor(), cursor);
}
public void testBuildTwice() {
final FrequentContactsCursorBuilder builder = new FrequentContactsCursorBuilder();
final Cursor firstCursor = builder
.setAllContacts(TestDataFactory.getAllContactListCursor())
.setFrequents(TestDataFactory.getStrequentContactsCursor())
.build();
assertNotNull(firstCursor);
builder.resetBuilder();
assertNull(builder.build());
final Cursor secondCursor = builder
.setAllContacts(TestDataFactory.getAllContactListCursor())
.setFrequents(TestDataFactory.getStrequentContactsCursor())
.build();
assertNotNull(firstCursor);
verifyBuiltCursor(TestDataFactory.getFrequentContactListCursor(), secondCursor);
}
}

View File

@@ -1,44 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel;
import android.test.AndroidTestCase;
import androidx.test.filters.SmallTest;
import com.android.messaging.datamodel.MemoryCacheManager.MemoryCache;
import org.mockito.Mockito;
@SmallTest
public class MemoryCacheManagerTest extends AndroidTestCase {
public void testRegisterCachesGetReclaimed() {
final MemoryCache mockMemoryCache = Mockito.mock(MemoryCache.class);
final MemoryCache otherMockMemoryCache = Mockito.mock(MemoryCache.class);
final MemoryCacheManager memoryCacheManager = new MemoryCacheManager();
memoryCacheManager.registerMemoryCache(mockMemoryCache);
memoryCacheManager.registerMemoryCache(otherMockMemoryCache);
memoryCacheManager.reclaimMemory();
memoryCacheManager.unregisterMemoryCache(otherMockMemoryCache);
memoryCacheManager.reclaimMemory();
Mockito.verify(mockMemoryCache, Mockito.times(2)).reclaim();
Mockito.verify(otherMockMemoryCache, Mockito.times(1)).reclaim();
}
}

View File

@@ -1,285 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.text.TextUtils;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.FakeContentProvider;
import com.android.messaging.FakeContext;
import com.android.messaging.FakeFactory;
import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
import com.android.messaging.datamodel.data.ParticipantData;
import com.android.messaging.datamodel.data.ParticipantData.ParticipantsQuery;
import com.android.messaging.ui.UIIntents;
import com.android.messaging.util.ContactUtil;
import org.junit.Assert;
import org.mockito.Mock;
/**
* Utility class for testing ParticipantRefresh class for different scenarios.
*/
@SmallTest
public class ParticipantRefreshTest extends BugleTestCase {
private FakeContext mContext;
FakeFactory mFakeFactory;
@Mock protected UIIntents mMockUIIntents;
protected FakeDataModel mFakeDataModel;
@Override
public void setUp() throws Exception {
super.setUp();
mContext = new FakeContext(getTestContext());
final ContentProvider provider = new MessagingContentProvider();
provider.attachInfo(mContext, null);
mContext.addContentProvider(MessagingContentProvider.AUTHORITY, provider);
mFakeDataModel = new FakeDataModel(mContext);
mFakeFactory = FakeFactory.registerWithFakeContext(getTestContext(), mContext)
.withDataModel(mFakeDataModel)
.withUIIntents(mMockUIIntents);
}
/**
* Add some phonelookup result into take PhoneLookup content provider. This will be
* used for doing phone lookup during participant refresh.
*/
private void addPhoneLookup(final String phone, final Object[][] lookupResult) {
final Uri uri = ContactUtil.lookupPhone(mContext, phone).getUri();
final FakeContentProvider phoneLookup = new FakeContentProvider(mContext,
uri, false);
phoneLookup.addOverrideData(uri, null, null, ContactUtil.PhoneLookupQuery.PROJECTION,
lookupResult);
mFakeFactory.withProvider(uri, phoneLookup);
}
/**
* Add some participant to test database.
*/
private void addParticipant(final String normalizedDestination, final long contactId,
final String name, final String photoUrl) {
final DatabaseWrapper db = DataModel.get().getDatabase();
final ContentValues values = new ContentValues();
values.put(ParticipantColumns.NORMALIZED_DESTINATION, normalizedDestination);
values.put(ParticipantColumns.CONTACT_ID, contactId);
values.put(ParticipantColumns.FULL_NAME, name);
values.put(ParticipantColumns.PROFILE_PHOTO_URI, photoUrl);
db.beginTransaction();
try {
db.insert(DatabaseHelper.PARTICIPANTS_TABLE, null, values);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
/**
* Verify that participant in the database has expected contacdtId, name and photoUrl fields.
*/
private void verifyParticipant(final String normalizedDestination, final long contactId,
final String name, final String photoUrl) {
final DatabaseWrapper db = DataModel.get().getDatabase();
db.beginTransaction();
try {
final String selection = ParticipantColumns.NORMALIZED_DESTINATION + "=?";
final String[] selectionArgs = new String[] { normalizedDestination };
final Cursor cursor = db.query(DatabaseHelper.PARTICIPANTS_TABLE,
ParticipantsQuery.PROJECTION, selection, selectionArgs, null, null, null);
if (cursor == null || cursor.getCount() != 1) {
Assert.fail("Should have participants for:" + normalizedDestination);
return;
}
cursor.moveToFirst();
final int currentContactId = cursor.getInt(ParticipantsQuery.INDEX_CONTACT_ID);
final String currentName = cursor.getString(ParticipantsQuery.INDEX_FULL_NAME);
final String currentPhotoUrl =
cursor.getString(ParticipantsQuery.INDEX_PROFILE_PHOTO_URI);
if (currentContactId != contactId) {
Assert.fail("Contact Id doesn't match. normalizedNumber=" + normalizedDestination +
" expected=" + contactId + " actual=" + currentContactId);
return;
}
if (!TextUtils.equals(currentName, name)) {
Assert.fail("Name doesn't match. normalizedNumber=" + normalizedDestination +
" expected=" + name + " actual=" + currentName);
return;
}
if (!TextUtils.equals(currentPhotoUrl, photoUrl)) {
Assert.fail("Contact Id doesn't match. normalizedNumber=" + normalizedDestination +
" expected=" + photoUrl + " actual=" + currentPhotoUrl);
return;
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
/**
* Verify that incremental refresh will resolve previously not resolved participants.
*/
public void testIncrementalRefreshNotResolvedSingleMatch() {
addParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED,
null, null);
addPhoneLookup("650-123-1233", new Object[][] {
{ 1L, "John", "content://photo/john", "650-123-1233", null, null, null }
});
ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_INCREMENTAL);
verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
}
/**
* Verify that incremental refresh will resolve previously not resolved participants.
*/
public void testIncrementalRefreshNotResolvedMultiMatch() {
addParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED,
null, null);
addPhoneLookup("650-123-1233", new Object[][] {
{ 1L, "John", "content://photo/john", "650-123-1233", null, null, null },
{ 2L, "Joe", "content://photo/joe", "650-123-1233", null, null, null }
});
ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_INCREMENTAL);
verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
}
/**
* Verify that incremental refresh will not touch already-resolved participants.
*/
public void testIncrementalRefreshResolvedSingleMatch() {
addParticipant("650-123-1233", 1, "Joh", "content://photo/joh");
addPhoneLookup("650-123-1233", new Object[][] {
{ 1L, "John", "content://photo/john", "650-123-1233", null, null, null }
});
ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_INCREMENTAL);
verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
}
/**
* Verify that full refresh will correct already-resolved participants if needed
*/
public void testFullRefreshResolvedSingleMatch() {
addParticipant("650-123-1233", 1, "Joh", "content://photo/joh");
addPhoneLookup("650-123-1233", new Object[][] {
{ 1L, "John", "content://photo/john", "650-123-1233", null, null, null }
});
ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
}
/**
* Verify that incremental refresh will not touch participant that is marked as not found.
*/
public void testIncrementalRefreshNotFound() {
addParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND,
null, null);
addPhoneLookup("650-123-1233", new Object[][] {
{ 1L, "John", "content://photo/john", "650-123-1233", null, null, null }
});
ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_INCREMENTAL);
verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
}
/**
* Verify that full refresh will resolve participant that is marked as not found.
*/
public void testFullRefreshNotFound() {
addParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND,
null, null);
addPhoneLookup("650-123-1233", new Object[][] {
{ 1L, "John", "content://photo/john", "650-123-1233", null, null, null }
});
ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
}
/**
* Verify that refresh take consideration of current contact_id when having multiple matches.
*/
public void testFullRefreshResolvedMultiMatch1() {
addParticipant("650-123-1233", 1, "Joh", "content://photo/joh");
addPhoneLookup("650-123-1233", new Object[][] {
{ 1L, "John", "content://photo/john", "650-123-1233", null, null, null },
{ 2L, "Joe", "content://photo/joe", "650-123-1233", null, null, null }
});
ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
}
/**
* Verify that refresh take consideration of current contact_id when having multiple matches.
*/
public void testFullRefreshResolvedMultiMatch2() {
addParticipant("650-123-1233", 2, "Joh", "content://photo/joh");
addPhoneLookup("650-123-1233", new Object[][] {
{ 1L, "John", "content://photo/john", "650-123-1233", null, null, null },
{ 2L, "Joe", "content://photo/joe", "650-123-1233", null, null, null }
});
ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
}
/**
* Verify that refresh take first contact in case current contact_id no longer matches.
*/
public void testFullRefreshResolvedMultiMatch3() {
addParticipant("650-123-1233", 3, "Joh", "content://photo/joh");
addPhoneLookup("650-123-1233", new Object[][] {
{ 1L, "John", "content://photo/john", "650-123-1233", null, null, null },
{ 2L, "Joe", "content://photo/joe", "650-123-1233", null, null, null }
});
ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
}
/**
* Verify that refresh take first contact in case current contact_id no longer matches.
*/
public void testFullRefreshResolvedBeforeButNotFoundNow() {
addParticipant("650-123-1233", 1, "Joh", "content://photo/joh");
addPhoneLookup("650-123-1233", new Object[][] {});
ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
verifyParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND,
null, null);
}
}

View File

@@ -1,429 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel.action;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import androidx.test.filters.MediumTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.Factory;
import com.android.messaging.FakeContext;
import com.android.messaging.FakeContext.FakeContextHost;
import com.android.messaging.FakeFactory;
import com.android.messaging.datamodel.BugleServiceTestCase;
import com.android.messaging.datamodel.DataModel;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.action.ActionMonitor.ActionCompletedListener;
import com.android.messaging.datamodel.action.ActionMonitor.ActionExecutedListener;
import com.android.messaging.datamodel.action.ActionTestHelpers.ResultTracker;
import com.android.messaging.datamodel.action.ActionTestHelpers.StubBackgroundWorker;
import com.android.messaging.datamodel.action.ActionTestHelpers.StubLoader;
@MediumTest
public class ActionServiceSystemTest extends BugleServiceTestCase<ActionServiceImpl>
implements ActionCompletedListener, ActionExecutedListener, FakeContextHost {
private static final String TAG = "ActionServiceSystemTest";
static {
// Set flag during loading of test cases to prevent application initialization starting
BugleTestCase.setTestsRunning();
}
@Override
public void onActionSucceeded(final ActionMonitor monitor,
final Action action, final Object data, final Object result) {
final TestChatAction test = (TestChatAction) action;
assertEquals("Expect correct action parameter", parameter, test.parameter);
final ResultTracker tracker = (ResultTracker) data;
tracker.completionResult = result;
synchronized(tracker) {
tracker.notifyAll();
}
}
@Override
public void onActionFailed(final ActionMonitor monitor, final Action action,
final Object data, final Object result) {
final TestChatAction test = (TestChatAction) action;
assertEquals("Expect correct action parameter", parameter, test.parameter);
final ResultTracker tracker = (ResultTracker) data;
tracker.completionResult = result;
synchronized(tracker) {
tracker.notifyAll();
}
}
@Override
public void onActionExecuted(final ActionMonitor monitor, final Action action,
final Object data, final Object result) {
final TestChatAction test = (TestChatAction) action;
assertEquals("Expect correct action parameter", parameter, test.parameter);
final ResultTracker tracker = (ResultTracker) data;
tracker.executionResult = result;
}
public ActionServiceSystemTest() {
super(ActionServiceImpl.class);
}
public void testChatActionSucceeds() {
final ResultTracker tracker = new ResultTracker();
final ActionService service = DataModel.get().getActionService();
final TestChatActionMonitor monitor = new TestChatActionMonitor(null, tracker, this, this);
final TestChatAction initial = new TestChatAction(monitor.getActionKey(), parameter);
assertNull("Expect completion result to start null", tracker.completionResult);
assertNull("Expect execution result to start null", tracker.executionResult);
final Parcel parcel = Parcel.obtain();
parcel.writeParcelable(initial, 0);
parcel.setDataPosition(0);
final TestChatAction action = parcel.readParcelable(mContext.getClassLoader());
synchronized(mWorker) {
try {
action.start(monitor);
// Wait for callback across threads
mWorker.wait(2000);
} catch (final InterruptedException e) {
assertTrue("Interrupted waiting for execution", false);
}
}
assertEquals("Expect to see 1 server request queued", 1,
mWorker.getRequestsMade().size());
final Action request = mWorker.getRequestsMade().get(0);
assertTrue("Expect Test type", request instanceof TestChatAction);
final Bundle response = new Bundle();
response.putString(TestChatAction.RESPONSE_TEST, processResponseResult);
synchronized(tracker) {
try {
request.markBackgroundWorkStarting();
request.markBackgroundWorkQueued();
request.markBackgroundWorkStarting();
request.markBackgroundCompletionQueued();
service.handleResponseFromBackgroundWorker(request, response);
// Wait for callback across threads
tracker.wait(2000);
} catch (final InterruptedException e) {
assertTrue("Interrupted waiting for response processing", false);
}
}
// TODO
//assertEquals("Expect execution result set", executeActionResult, tracker.executionResult);
assertEquals("Expect completion result set", processResponseResult,
tracker.completionResult);
}
public void testChatActionFails() {
final ResultTracker tracker = new ResultTracker();
final ActionService service = DataModel.get().getActionService();
final TestChatActionMonitor monitor = new TestChatActionMonitor(null, tracker, this, this);
final TestChatAction action = new TestChatAction(monitor.getActionKey(), parameter);
assertNull("Expect completion result to start null", tracker.completionResult);
assertNull("Expect execution result to start null", tracker.executionResult);
synchronized(mWorker) {
try {
action.start(monitor);
// Wait for callback across threads
mWorker.wait(2000);
} catch (final InterruptedException e) {
assertTrue("Interrupted waiting for requests", false);
}
}
assertEquals("Expect to see 1 server request queued", 1,
mWorker.getRequestsMade().size());
final Action request = mWorker.getRequestsMade().get(0);
assertTrue("Expect Test type", request instanceof TestChatAction);
synchronized(tracker) {
try {
request.markBackgroundWorkStarting();
request.markBackgroundWorkQueued();
request.markBackgroundWorkStarting();
request.markBackgroundCompletionQueued();
service.handleFailureFromBackgroundWorker(request, new Exception("It went wrong"));
// Wait for callback across threads
tracker.wait(2000);
} catch (final InterruptedException e) {
assertTrue("Interrupted waiting for response processing", false);
}
}
// TODO
//assertEquals("Expect execution result set", executeActionResult, tracker.executionResult);
assertEquals("Expect completion result set", processFailureResult,
tracker.completionResult);
}
public void testChatActionNoMonitor() {
final ActionService service = DataModel.get().getActionService();
final TestChatAction action =
new TestChatAction(Action.generateUniqueActionKey(null), parameter);
synchronized(mWorker) {
try {
action.start();
// Wait for callback across threads
mWorker.wait(2000);
} catch (final InterruptedException e) {
assertTrue("Interrupted waiting for execution", false);
}
}
assertEquals("Expect to see 1 server request queued", 1,
mWorker.getRequestsMade().size());
Action request = mWorker.getRequestsMade().get(0);
assertTrue("Expect Test type", request instanceof TestChatAction);
final Bundle response = new Bundle();
response.putString(TestChatAction.RESPONSE_TEST, processResponseResult);
synchronized(mWorker) {
try {
service.handleResponseFromBackgroundWorker(request, response);
// Wait for callback across threads
mWorker.wait(2000);
} catch (final InterruptedException e) {
assertTrue("Interrupted waiting for response processing", false);
}
}
assertEquals("Expect to see second server request queued",
2, mWorker.getRequestsMade().size());
request = mWorker.getRequestsMade().get(1);
assertTrue("Expect other type",
request instanceof TestChatActionOther);
}
public void testChatActionUnregisterListener() {
final ResultTracker tracker = new ResultTracker();
final ActionService service = DataModel.get().getActionService();
final TestChatActionMonitor monitor = new TestChatActionMonitor(null, tracker, this, this);
final TestChatAction action = new TestChatAction(monitor.getActionKey(), parameter);
assertNull("Expect completion result to start null", tracker.completionResult);
assertNull("Expect execution result to start null", tracker.executionResult);
synchronized(mWorker) {
try {
action.start(monitor);
// Wait for callback across threads
mWorker.wait(2000);
} catch (final InterruptedException e) {
assertTrue("Interrupted waiting for execution", false);
}
}
assertEquals("Expect to see 1 server request queued", 1,
mWorker.getRequestsMade().size());
final Action request = mWorker.getRequestsMade().get(0);
assertTrue("Expect Test type", request instanceof TestChatAction);
monitor.unregister();
final Bundle response = new Bundle();
synchronized(mWorker) {
try {
request.markBackgroundWorkStarting();
request.markBackgroundWorkQueued();
request.markBackgroundWorkStarting();
request.markBackgroundCompletionQueued();
service.handleResponseFromBackgroundWorker(request, response);
// Wait for callback across threads
mWorker.wait(2000);
} catch (final InterruptedException e) {
assertTrue("Interrupted waiting for response processing", false);
}
}
//assertEquals("Expect execution result set", executeActionResult, tracker.executionResult);
assertEquals("Expect completion never called", null, tracker.completionResult);
}
StubBackgroundWorker mWorker;
FakeContext mContext;
StubLoader mLoader;
private static final String parameter = "parameter";
private static final Object executeActionResult = "executeActionResult";
private static final String processResponseResult = "processResponseResult";
private static final Object processFailureResult = "processFailureResult";
@Override
public void setUp() throws Exception {
super.setUp();
Log.d(TAG, "ChatActionTest setUp");
mContext = new FakeContext(getContext(), this);
mWorker = new StubBackgroundWorker();
FakeFactory.registerWithFakeContext(getContext(), mContext)
.withDataModel(new FakeDataModel(mContext)
.withBackgroundWorkerForActionService(mWorker)
.withActionService(new ActionService()));
mLoader = new StubLoader();
setContext(Factory.get().getApplicationContext());
}
@Override
public String getServiceClassName() {
return ActionServiceImpl.class.getName();
}
@Override
public void startServiceForStub(final Intent intent) {
this.startService(intent);
}
@Override
public void onStartCommandForStub(final Intent intent, final int flags, final int startId) {
this.getService().onStartCommand(intent, flags, startId);
}
public static class TestChatAction extends Action implements Parcelable {
public static String RESPONSE_TEST = "response_test";
public static String KEY_PARAMETER = "parameter";
protected TestChatAction(final String key, final String parameter) {
super(key);
this.actionParameters.putString(KEY_PARAMETER, parameter);
// Cache parameter as a member variable
this.parameter = parameter;
}
// An example parameter
public final String parameter;
/**
* Process the action locally - runs on datamodel service thread
*/
@Override
protected Object executeAction() {
requestBackgroundWork();
return executeActionResult;
}
/**
* Process the response from the server - runs on datamodel service thread
*/
@Override
protected Object processBackgroundResponse(final Bundle response) {
requestBackgroundWork(new TestChatActionOther(null, parameter));
return response.get(RESPONSE_TEST);
}
/**
* Called in case of failures when sending requests - runs on datamodel service thread
*/
@Override
protected Object processBackgroundFailure() {
return processFailureResult;
}
private TestChatAction(final Parcel in) {
super(in);
// Cache parameter as a member variable
parameter = actionParameters.getString(KEY_PARAMETER);
}
public static final Parcelable.Creator<TestChatAction> CREATOR
= new Parcelable.Creator<TestChatAction>() {
@Override
public TestChatAction createFromParcel(final Parcel in) {
return new TestChatAction(in);
}
@Override
public TestChatAction[] newArray(final int size) {
return new TestChatAction[size];
}
};
@Override
public void writeToParcel(final Parcel parcel, final int flags) {
writeActionToParcel(parcel, flags);
}
}
public static class TestChatActionOther extends Action implements Parcelable {
protected TestChatActionOther(final String key, final String parameter) {
super(generateUniqueActionKey(key));
this.parameter = parameter;
}
public final String parameter;
private TestChatActionOther(final Parcel in) {
super(in);
parameter = in.readString();
}
public static final Parcelable.Creator<TestChatActionOther> CREATOR
= new Parcelable.Creator<TestChatActionOther>() {
@Override
public TestChatActionOther createFromParcel(final Parcel in) {
return new TestChatActionOther(in);
}
@Override
public TestChatActionOther[] newArray(final int size) {
return new TestChatActionOther[size];
}
};
@Override
public void writeToParcel(final Parcel parcel, final int flags) {
writeActionToParcel(parcel, flags);
parcel.writeString(parameter);
}
}
/**
* An operation that notifies a listener upon completion
*/
public static class TestChatActionMonitor extends ActionMonitor {
/**
* Create action state wrapping an BlockUserAction instance
* @param account - account in which to block the user
* @param baseKey - suggested action key from BlockUserAction
* @param data - optional action specific data that is handed back to listener
* @param listener - action completed listener
*/
public TestChatActionMonitor(final String baseKey, final Object data,
final ActionCompletedListener completed, final ActionExecutedListener executed) {
super(STATE_CREATED, Action.generateUniqueActionKey(baseKey), data);
setCompletedListener(completed);
setExecutedListener(executed);
}
}
}

View File

@@ -1,252 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel.action;
import android.content.Intent;
import android.os.Bundle;
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import androidx.test.filters.MediumTest;
import com.android.messaging.Factory;
import com.android.messaging.FakeContext;
import com.android.messaging.FakeContext.FakeContextHost;
import com.android.messaging.FakeFactory;
import com.android.messaging.datamodel.BugleServiceTestCase;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.action.ActionMonitor.ActionCompletedListener;
import com.android.messaging.datamodel.action.ActionMonitor.ActionStateChangedListener;
import com.android.messaging.datamodel.action.ActionTestHelpers.ResultTracker;
import com.android.messaging.datamodel.action.ActionTestHelpers.StubBackgroundWorker;
import com.android.messaging.datamodel.action.ActionTestHelpers.StubLoader;
import java.util.ArrayList;
@MediumTest
public class ActionServiceTest extends BugleServiceTestCase<ActionServiceImpl>
implements FakeContextHost, ActionStateChangedListener, ActionCompletedListener {
private static final String TAG = "ActionServiceTest";
@Override
public void onActionStateChanged(final Action action, final int state) {
mStates.add(state);
}
@Override
public void onActionSucceeded(final ActionMonitor monitor,
final Action action, final Object data, final Object result) {
final TestChatAction test = (TestChatAction) action;
assertNotSame(test.dontRelyOnMe, dontRelyOnMe);
// This will be true - but only briefly
assertEquals(test.dontRelyOnMe, becauseIChange);
final ResultTracker tracker = (ResultTracker) data;
tracker.completionResult = result;
synchronized(tracker) {
tracker.notifyAll();
}
}
@Override
public void onActionFailed(final ActionMonitor monitor, final Action action,
final Object data, final Object result) {
final TestChatAction test = (TestChatAction) action;
assertNotSame(test.dontRelyOnMe, dontRelyOnMe);
// This will be true - but only briefly
assertEquals(test.dontRelyOnMe, becauseIChange);
final ResultTracker tracker = (ResultTracker) data;
tracker.completionResult = result;
synchronized(tracker) {
tracker.notifyAll();
}
}
/**
* For a chat action verify that the service intent is constructed and queued correctly and
* that when that intent is processed it actually executes the action.
*/
public void testChatServiceCreatesIntentAndExecutesAction() {
final ResultTracker tracker = new ResultTracker();
final TestChatActionMonitor monitor = new TestChatActionMonitor(null, tracker, this, this);
final TestChatAction action = new TestChatAction(monitor.getActionKey(), parameter);
action.dontRelyOnMe = dontRelyOnMe;
assertFalse("Expect service initially stopped", mServiceStarted);
synchronized(mWorker) {
try {
action.start(monitor);
// Wait for callback across threads
mWorker.wait(2000);
mServiceStarted = true;
} catch (final InterruptedException e) {
assertTrue("Interrupted waiting for execution", false);
}
}
assertTrue("Expect service started", mServiceStarted);
assertEquals("Expect three states ", mStates.size(), 3);
assertEquals("State-0 should be STATE_QUEUED", (int)mStates.get(0),
ActionMonitor.STATE_QUEUED);
assertEquals("State-1 should be STATE_EXECUTING", (int)mStates.get(1),
ActionMonitor.STATE_EXECUTING);
assertEquals("State-2 should be STATE_COMPLETE", (int)mStates.get(2),
ActionMonitor.STATE_COMPLETE);
}
StubBackgroundWorker mWorker;
FakeContext mContext;
StubLoader mLoader;
ActionService mService;
ArrayList<Integer> mStates;
private static final String parameter = "parameter";
private static final Object dontRelyOnMe = "dontRelyOnMe";
private static final Object becauseIChange = "becauseIChange";
private static final Object executeActionResult = "executeActionResult";
private static final Object processResponseResult = "processResponseResult";
private static final Object processFailureResult = "processFailureResult";
public ActionServiceTest() {
super(ActionServiceImpl.class);
}
@Override
public void setUp() throws Exception {
super.setUp();
Log.d(TAG, "ChatActionTest setUp");
sLooper = Looper.myLooper();
mWorker = new StubBackgroundWorker();
mContext = new FakeContext(getContext(), this);
FakeFactory.registerWithFakeContext(getContext(),mContext)
.withDataModel(new FakeDataModel(mContext)
.withBackgroundWorkerForActionService(mWorker)
.withActionService(new ActionService()));
mStates = new ArrayList<Integer>();
setContext(Factory.get().getApplicationContext());
}
@Override
public String getServiceClassName() {
return ActionServiceImpl.class.getName();
}
boolean mServiceStarted = false;
@Override
public void startServiceForStub(final Intent intent) {
// Do nothing until later
assertFalse(mServiceStarted);
mServiceStarted = true;
}
@Override
public void onStartCommandForStub(final Intent intent, final int flags, final int startId) {
assertTrue(mServiceStarted);
}
private static Looper sLooper;
public static void assertRunsOnOtherThread() {
assertTrue (Looper.myLooper() != Looper.getMainLooper());
assertTrue (Looper.myLooper() != sLooper);
}
public static class TestChatAction extends Action implements Parcelable {
public static String RESPONSE_TEST = "response_test";
public static String KEY_PARAMETER = "parameter";
protected TestChatAction(final String key, final String parameter) {
super(key);
this.actionParameters.putString(KEY_PARAMETER, parameter);
}
transient Object dontRelyOnMe;
/**
* Process the action locally - runs on service thread
*/
@Override
protected Object executeAction() {
this.dontRelyOnMe = becauseIChange;
assertRunsOnOtherThread();
return executeActionResult;
}
/**
* Process the response from the server - runs on service thread
*/
@Override
protected Object processBackgroundResponse(final Bundle response) {
assertRunsOnOtherThread();
return processResponseResult;
}
/**
* Called in case of failures when sending requests - runs on service thread
*/
@Override
protected Object processBackgroundFailure() {
assertRunsOnOtherThread();
return processFailureResult;
}
private TestChatAction(final Parcel in) {
super(in);
}
public static final Parcelable.Creator<TestChatAction> CREATOR
= new Parcelable.Creator<TestChatAction>() {
@Override
public TestChatAction createFromParcel(final Parcel in) {
return new TestChatAction(in);
}
@Override
public TestChatAction[] newArray(final int size) {
return new TestChatAction[size];
}
};
@Override
public void writeToParcel(final Parcel parcel, final int flags) {
writeActionToParcel(parcel, flags);
}
}
/**
* An operation that notifies a listener upon state changes, execution and completion
*/
public static class TestChatActionMonitor extends ActionMonitor {
public TestChatActionMonitor(final String baseKey, final Object data,
final ActionStateChangedListener listener, final ActionCompletedListener executed) {
super(STATE_CREATED, Action.generateUniqueActionKey(baseKey), data);
setStateChangedListener(listener);
setCompletedListener(executed);
assertEquals("Initial state should be STATE_CREATED", mState, STATE_CREATED);
}
}
}

View File

@@ -1,325 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel.action;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.test.filters.MediumTest;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.FakeFactory;
import com.android.messaging.datamodel.DataModelImpl;
import com.android.messaging.datamodel.action.ActionTestHelpers.StubChatActionMonitor;
import java.util.ArrayList;
@MediumTest
public class ActionTest extends BugleTestCase {
private static final String parameter = "parameter";
private static final Object executeActionResult = "executeActionResult";
private static final Object processResponseResult = "processResponseResult";
private static final Object processFailureResult = "processFailureResult";
private static final String mActionKey = "TheActionKey";
private static final Object mData = "PrivateData";
private StubChatActionMonitor mMonitor;
private TestChatAction mAction;
private ArrayList<StubChatActionMonitor.StateTransition> mTransitions;
@Override
public void setUp() throws Exception {
super.setUp();
FakeFactory.register(getTestContext())
.withDataModel(new DataModelImpl(getContext()));
mMonitor = new StubChatActionMonitor(ActionMonitor.STATE_CREATED, mActionKey,
mData);
mAction = new TestChatAction(mActionKey, parameter);
mTransitions = mMonitor.getTransitions();
}
private void verifyState(final int count, final int from, final int to) {
assertEquals(to, mMonitor.getState());
assertEquals(mTransitions.size(), count);
verifyTransition(count-1, from , to);
}
private void verifyTransition(final int index, final int from, final int to) {
assertTrue(mTransitions.size() > index);
assertEquals(mAction, mTransitions.get(index).action);
assertEquals(from, mTransitions.get(index).from);
assertEquals(to, mTransitions.get(index).to);
}
@SmallTest
public void testActionStartTransitionsCorrectly() {
mMonitor.setState(ActionMonitor.STATE_CREATED);
ActionMonitor.registerActionMonitor(mAction.actionKey, mMonitor);
assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
mAction.markStart();
assertEquals("After start state: STATE_QUEUED", ActionMonitor.STATE_QUEUED,
mMonitor.getState());
verifyState(1, ActionMonitor.STATE_CREATED, ActionMonitor.STATE_QUEUED);
ActionMonitor.unregisterActionMonitor(mAction.actionKey, mMonitor);
assertFalse(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
assertFalse(ActionMonitor.sActionMonitors.containsValue(mMonitor));
}
@SmallTest
public void testActionStartAssertsFromIncorrectState() {
mMonitor.setState(ActionMonitor.STATE_UNDEFINED);
ActionMonitor.registerActionMonitor(mAction.actionKey, mMonitor);
assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
try {
mAction.markStart();
fail("Expect assertion when starting from STATE_UNDEFINED");
} catch (final IllegalStateException ex){
}
ActionMonitor.unregisterActionMonitor(mAction.actionKey, mMonitor);
assertFalse(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
assertFalse(ActionMonitor.sActionMonitors.containsValue(mMonitor));
}
public void testActionTransitionsEndToEndWithRequests() {
assertEquals("Start state: STATE_CREATED", ActionMonitor.STATE_CREATED,
mMonitor.getState());
ActionMonitor.registerActionMonitor(mAction.actionKey, mMonitor);
assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
mAction.markStart();
verifyState(1, ActionMonitor.STATE_CREATED, ActionMonitor.STATE_QUEUED);
mAction.markBeginExecute();
verifyState(2, ActionMonitor.STATE_QUEUED, ActionMonitor.STATE_EXECUTING);
final Object result = mAction.executeAction();
mAction.requestBackgroundWork();
assertEquals("Check executeAction result", result, executeActionResult);
mAction.markEndExecute(result);
verifyState(3, ActionMonitor.STATE_EXECUTING,
ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED);
mAction.markBackgroundWorkStarting();
verifyState(4, ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED,
ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION);
mAction.markBackgroundWorkQueued();
verifyState(5, ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION,
ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED);
mAction.markBackgroundWorkStarting();
verifyState(6, ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED,
ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION);
final Bundle response = null;
mAction.markBackgroundCompletionQueued();
verifyState(7, ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION,
ActionMonitor.STATE_BACKGROUND_COMPLETION_QUEUED);
assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
mAction.processBackgroundWorkResponse(response);
verifyTransition(7, ActionMonitor.STATE_BACKGROUND_COMPLETION_QUEUED,
ActionMonitor.STATE_PROCESSING_BACKGROUND_RESPONSE);
verifyState(9, ActionMonitor.STATE_PROCESSING_BACKGROUND_RESPONSE,
ActionMonitor.STATE_COMPLETE);
assertFalse(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
assertFalse(ActionMonitor.sActionMonitors.containsValue(mMonitor));
}
public void testActionTransitionsEndToEndFailsRequests() {
assertEquals("Start state: STATE_CREATED", ActionMonitor.STATE_CREATED,
mMonitor.getState());
ActionMonitor.registerActionMonitor(mAction.actionKey, mMonitor);
assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
mAction.markStart();
verifyState(1, ActionMonitor.STATE_CREATED, ActionMonitor.STATE_QUEUED);
mAction.markBeginExecute();
verifyState(2, ActionMonitor.STATE_QUEUED, ActionMonitor.STATE_EXECUTING);
final Object result = mAction.executeAction();
mAction.requestBackgroundWork();
assertEquals("Check executeAction result", result, executeActionResult);
mAction.markEndExecute(result);
verifyState(3, ActionMonitor.STATE_EXECUTING,
ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED);
mAction.markBackgroundWorkStarting();
verifyState(4, ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED,
ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION);
mAction.markBackgroundWorkQueued();
verifyState(5, ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION,
ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED);
mAction.markBackgroundWorkStarting();
verifyState(6, ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED,
ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION);
assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
mAction.processBackgroundWorkFailure();
verifyState(7, ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION,
ActionMonitor.STATE_COMPLETE);
assertFalse(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
assertFalse(ActionMonitor.sActionMonitors.containsValue(mMonitor));
}
public void testActionTransitionsEndToEndNoRequests() {
assertEquals("Start state: STATE_CREATED", ActionMonitor.STATE_CREATED,
mMonitor.getState());
ActionMonitor.registerActionMonitor(mAction.actionKey, mMonitor);
assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
mAction.markStart();
verifyState(1, ActionMonitor.STATE_CREATED, ActionMonitor.STATE_QUEUED);
mAction.markBeginExecute();
verifyState(2, ActionMonitor.STATE_QUEUED, ActionMonitor.STATE_EXECUTING);
final Object result = mAction.executeAction();
assertEquals("Check executeAction result", result, executeActionResult);
assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
mAction.markEndExecute(result);
verifyState(3, ActionMonitor.STATE_EXECUTING,
ActionMonitor.STATE_COMPLETE);
assertFalse(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
assertFalse(ActionMonitor.sActionMonitors.containsValue(mMonitor));
}
public static class TestChatAction extends Action implements Parcelable {
protected TestChatAction(final String key, final String parameter) {
super(key);
this.parameter = parameter;
}
public final String parameter;
/**
* Process the action locally - runs on service thread
*/
@Override
protected Object executeAction() {
assertEquals("Check parameter", parameter, ActionTest.parameter);
return executeActionResult;
}
/**
* Process the response from the server - runs on service thread
*/
@Override
protected Object processBackgroundResponse(final Bundle response) {
assertEquals("Check parameter", parameter, ActionTest.parameter);
return processResponseResult;
}
/**
* Called in case of failures when sending requests - runs on service thread
*/
@Override
protected Object processBackgroundFailure() {
assertEquals("Check parameter", parameter, ActionTest.parameter);
return processFailureResult;
}
private TestChatAction(final Parcel in) {
super(in);
parameter = in.readString();
}
public static final Parcelable.Creator<TestChatAction> CREATOR
= new Parcelable.Creator<TestChatAction>() {
@Override
public TestChatAction createFromParcel(final Parcel in) {
return new TestChatAction(in);
}
@Override
public TestChatAction[] newArray(final int size) {
return new TestChatAction[size];
}
};
@Override
public void writeToParcel(final Parcel parcel, final int flags) {
writeActionToParcel(parcel, flags);
parcel.writeString(parameter);
}
}
}

View File

@@ -1,175 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel.action;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.List;
public class ActionTestHelpers {
private static final String TAG = "DataModelTestHelpers";
static class StubLoader extends ContentObserver {
ArrayList<Uri> mUriList = new ArrayList<Uri>();
StubLoader() {
super(null);
}
public void clear() {
mUriList.clear();
}
@Override
public void onChange(final boolean selfChange) {
// Handle change.
mUriList.add(null);
}
// Implement the onChange(boolean, Uri) method to take advantage of the new Uri argument.
// Only supported on platform 16 and above...
@Override
public void onChange(final boolean selfChange, final Uri uri) {
// Handle change.
mUriList.add(uri);
}
}
static class StubBackgroundWorker extends BackgroundWorker {
public StubBackgroundWorker() {
super();
mActions = new ArrayList<Action>();
}
ArrayList<Action> mActions;
public ArrayList<Action> getRequestsMade() {
return mActions;
}
@Override
public void queueBackgroundWork(final List<Action> actions) {
mActions.addAll(actions);
synchronized(this) {
this.notifyAll();
}
}
}
static class ResultTracker {
public Object executionResult;
public Object completionResult;
}
static class StubChatActionMonitor extends ActionMonitor {
static public class StateTransition {
Action action;
int from;
int to;
public StateTransition(final Action action, final int from, final int to) {
this.action = action;
this.from = from;
this.to = to;
}
}
private final ArrayList<StateTransition> mTransitions;
public ArrayList<StateTransition> getTransitions() {
return mTransitions;
}
protected StubChatActionMonitor(final int initialState, final String actionKey,
final Object data) {
super(initialState, actionKey, data);
mTransitions = new ArrayList<StateTransition>();
}
@Override
protected void updateState(final Action action, final int expectedState,
final int state) {
mTransitions.add(new StateTransition(action, mState, state));
super.updateState(action, expectedState, state);
}
public void setState(final int state) {
mState = state;
}
public int getState() {
return mState;
}
}
public static class StubActionService extends ActionService {
public static class StubActionServiceCallLog {
public final Action action;
public final Action request;
public final Bundle response;
public final Exception exception;
public final Action update;
public StubActionServiceCallLog(final Action action,
final Action request,
final Bundle response,
final Exception exception,
final Action update) {
this.action = action;
this.request = request;
this.response = response;
this.exception = exception;
this.update = update;
}
}
private final ArrayList<StubActionServiceCallLog> mServiceCalls =
new ArrayList<StubActionServiceCallLog>();
public ArrayList<StubActionServiceCallLog> getCalls() {
return mServiceCalls;
}
@Override
public void startAction(final Action action) {
mServiceCalls.add(new StubActionServiceCallLog(action, null, null, null, null));
synchronized(this) {
this.notifyAll();
}
}
@Override
public void handleResponseFromBackgroundWorker(final Action request,
final Bundle response) {
mServiceCalls.add(new StubActionServiceCallLog(null, request, response, null, null));
synchronized(this) {
this.notifyAll();
}
}
@Override
protected void handleFailureFromBackgroundWorker(final Action request,
final Exception exception) {
mServiceCalls.add(new StubActionServiceCallLog(null, request, null, exception, null));
synchronized(this) {
this.notifyAll();
}
}
}
}

View File

@@ -1,172 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel.action;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.net.Uri;
import android.test.mock.MockContentProvider;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.FakeContext;
import com.android.messaging.FakeFactory;
import com.android.messaging.datamodel.BugleDatabaseOperations;
import com.android.messaging.datamodel.DataModel;
import com.android.messaging.datamodel.DatabaseWrapper;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.MessagingContentProvider;
import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService;
import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService.StubActionServiceCallLog;
import com.android.messaging.datamodel.action.GetOrCreateConversationAction.GetOrCreateConversationActionListener;
import com.android.messaging.datamodel.action.GetOrCreateConversationAction.GetOrCreateConversationActionMonitor;
import com.android.messaging.datamodel.data.ParticipantData;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.sms.MmsUtils;
import org.mockito.Mock;
import java.util.ArrayList;
@SmallTest
public class GetOrCreateConversationActionTest extends BugleTestCase {
@Mock GetOrCreateConversationActionListener mockListener;
public void testGetOrCreateConversation() {
final DatabaseWrapper db = DataModel.get().getDatabase();
final ArrayList<String> recipients = new ArrayList<String>();
recipients.add("5551234567");
recipients.add("5551234568");
// Generate a list of partially formed participants
final ArrayList<ParticipantData> participants = new
ArrayList<ParticipantData>();
for (final String recipient : recipients) {
participants.add(ParticipantData.getFromRawPhoneBySystemLocale(recipient));
}
// Test that we properly stubbed the SMS provider to return a thread id
final long threadId = MmsUtils.getOrCreateThreadId(mContext, recipients);
assertEquals(TestDataFactory.SMS_MMS_THREAD_ID_CURSOR_VALUE, threadId);
ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
GetOrCreateConversationActionMonitor monitor =
GetOrCreateConversationAction.getOrCreateConversation(participants, null,
mockListener);
assertEquals("Failed to start service once for action", calls.size(), 1);
assertTrue("Action not GetOrCreateConversationAction", calls.get(0).action instanceof
GetOrCreateConversationAction);
GetOrCreateConversationAction action = (GetOrCreateConversationAction)
calls.get(0).action;
Object result = action.executeAction();
assertTrue(result instanceof String);
// Make sure that we created a new conversation
int expectedConversationId = TestDataFactory.NUM_TEST_CONVERSATIONS + 1;
assertEquals(expectedConversationId, Integer.parseInt((String) result));
// Now get the conversation that we just created again
monitor = GetOrCreateConversationAction.getOrCreateConversation(participants, null,
mockListener);
calls = mService.getCalls();
assertEquals("Failed to start service for second action", calls.size(), 2);
assertTrue("Action not GetOrCreateConversationAction", calls.get(1).action instanceof
GetOrCreateConversationAction);
action = (GetOrCreateConversationAction)calls.get(1).action;
result = action.executeAction();
assertTrue(result instanceof String);
final String conversationId = (String) result;
// Make sure that we found the same conversation id
assertEquals(expectedConversationId, Integer.parseInt((String) result));
final ArrayList<ParticipantData> conversationParticipants =
BugleDatabaseOperations.getParticipantsForConversation(db, conversationId);
assertEquals("Participant count mismatch", recipients.size(),
conversationParticipants.size());
for(final ParticipantData participant : conversationParticipants) {
assertTrue(recipients.contains(participant.getSendDestination()));
}
final Uri conversationParticipantsUri =
MessagingContentProvider.buildConversationParticipantsUri(conversationId);
final Cursor cursor = mContext.getContentResolver().query(conversationParticipantsUri,
ParticipantData.ParticipantsQuery.PROJECTION, null, null, null);
int countSelf = 0;
while(cursor.moveToNext()) {
final ParticipantData participant = ParticipantData.getFromCursor(cursor);
if (participant.isSelf()) {
countSelf++;
} else {
assertTrue(recipients.contains(participant.getSendDestination()));
}
}
cursor.close();
assertEquals("Expect one self participant in conversations", 1, countSelf);
assertEquals("Cursor count mismatch", recipients.size(), cursor.getCount() - countSelf);
final String realId = BugleDatabaseOperations.getExistingConversation(db, threadId, false);
assertEquals("Conversation already exists", realId, conversationId);
}
private FakeContext mContext;
private StubActionService mService;
@Override
public void setUp() throws Exception {
super.setUp();
mContext = new FakeContext(getTestContext());
final MockContentProvider mockProvider = new MockContentProvider() {
@Override
public Cursor query(final Uri uri, final String[] projection, final String selection,
final String[] selectionArgs, final String sortOrder) {
return TestDataFactory.getSmsMmsThreadIdCursor();
}
};
mContext.addContentProvider("mms-sms", mockProvider);
final MessagingContentProvider provider = new MessagingContentProvider();
final ProviderInfo providerInfo = new ProviderInfo();
providerInfo.authority = MessagingContentProvider.AUTHORITY;
provider.attachInfo(mContext, providerInfo);
mContext.addContentProvider(MessagingContentProvider.AUTHORITY, provider);
mService = new StubActionService();
final FakeDataModel fakeDataModel = new FakeDataModel(mContext)
.withActionService(mService);
FakeFactory.registerWithFakeContext(getTestContext(), mContext)
.withDataModel(fakeDataModel);
provider.setDatabaseForTest(fakeDataModel.getDatabase());
}
}

View File

@@ -1,481 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel.action;
import android.content.ContentProvider;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.net.Uri;
import android.text.TextUtils;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.FakeContext;
import com.android.messaging.FakeFactory;
import com.android.messaging.datamodel.BugleDatabaseOperations;
import com.android.messaging.datamodel.DataModel;
import com.android.messaging.datamodel.DatabaseHelper;
import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns;
import com.android.messaging.datamodel.DatabaseWrapper;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.MediaScratchFileProvider;
import com.android.messaging.datamodel.MessagingContentProvider;
import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService;
import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService.StubActionServiceCallLog;
import com.android.messaging.datamodel.action.ReadDraftDataAction.ReadDraftDataActionListener;
import com.android.messaging.datamodel.data.MessageData;
import com.android.messaging.datamodel.data.MessagePartData;
import com.android.messaging.datamodel.data.ParticipantData;
import com.android.messaging.util.ContentType;
import org.mockito.Mock;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
@SmallTest
public class ReadWriteDraftMessageActionTest extends BugleTestCase {
@Mock ReadDraftDataActionListener mockListener;
// TODO: Add test cases
// 1. Make sure drafts can include attachments and multiple parts
// 2. Make sure attachments get cleaned up appropriately
// 3. Make sure messageId and partIds not reused (currently each draft is a new message).
public void testWriteDraft() {
final String draftMessage = "draftMessage";
final long threadId = 1234567;
final boolean senderBlocked = false;
final String participantNumber = "5551234567";
final DatabaseWrapper db = DataModel.get().getDatabase();
final String conversationId = getOrCreateConversation(db, participantNumber, threadId,
senderBlocked);
final String selfId = getOrCreateSelfId(db);
// Should clear/stub DB
final ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
final MessageData message = MessageData.createDraftSmsMessage(conversationId, selfId,
draftMessage);
WriteDraftMessageAction.writeDraftMessage(conversationId, message);
assertEquals("Failed to start service once for action", calls.size(), 1);
assertTrue("Action not SaveDraftMessageAction",
calls.get(0).action instanceof WriteDraftMessageAction);
final Action save = calls.get(0).action;
final Object result = save.executeAction();
assertTrue("Expect row number string as result", result instanceof String);
final String messageId = (String) result;
// Should check DB
final MessageData actual = BugleDatabaseOperations.readMessage(db, messageId);
assertNotNull("Database missing draft", actual);
assertEquals("Draft text changed", draftMessage, actual.getMessageText());
}
private static String getOrCreateSelfId(final DatabaseWrapper db) {
db.beginTransaction();
final String selfId = BugleDatabaseOperations.getOrCreateParticipantInTransaction(db,
ParticipantData.getSelfParticipant(ParticipantData.DEFAULT_SELF_SUB_ID));
db.setTransactionSuccessful();
db.endTransaction();
return selfId;
}
private static String getOrCreateConversation(final DatabaseWrapper db,
final String participantNumber, final long threadId, final boolean senderBlocked) {
final ArrayList<ParticipantData> participants =
new ArrayList<ParticipantData>();
participants.add(ParticipantData.getFromRawPhoneBySystemLocale(participantNumber));
final String conversationId = BugleDatabaseOperations.getOrCreateConversation(db, threadId,
senderBlocked, participants);
assertNotNull("No conversation", conversationId);
return conversationId;
}
public void testReadDraft() {
final Object data = "data";
final String draftMessage = "draftMessage";
final long threadId = 1234567;
final boolean senderBlocked = false;
final String participantNumber = "5552345678";
final DatabaseWrapper db = DataModel.get().getDatabase();
final String conversationId = getOrCreateConversation(db, participantNumber, threadId,
senderBlocked);
final String selfId = getOrCreateSelfId(db);
// Should clear/stub DB
final ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
final MessageData message = MessageData.createDraftSmsMessage(conversationId, selfId,
draftMessage);
BugleDatabaseOperations.updateDraftMessageData(db, conversationId, message,
BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
final ActionMonitor monitor =
ReadDraftDataAction.readDraftData(conversationId, null, data, mockListener);
assertEquals("Unexpected number of calls to service", 1, calls.size());
assertTrue("Action not of type ReadDraftMessageAction",
calls.get(0).action instanceof ReadDraftDataAction);
final Action read = calls.get(0).action;
final Object result = read.executeAction();
assertTrue(result instanceof ReadDraftDataAction.DraftData);
final ReadDraftDataAction.DraftData draft = (ReadDraftDataAction.DraftData) result;
assertEquals("Draft message text differs", draftMessage, draft.message.getMessageText());
assertEquals("Draft self differs", selfId, draft.message.getSelfId());
assertEquals("Draft conversation differs", conversationId,
draft.conversation.getConversationId());
}
public void testReadDraftForNewConversation() {
final Object data = "data";
long threadId = 1234567;
final boolean senderBlocked = false;
long phoneNumber = 5557654567L;
final String notConversationId = "ThisIsNotValidConversationId";
final DatabaseWrapper db = DataModel.get().getDatabase();
final String selfId = getOrCreateSelfId(db);
// Unless set a new conversation should have a null draft message
final MessageData blank = BugleDatabaseOperations.readDraftMessageData(db,
notConversationId, selfId);
assertNull(blank);
String conversationId = null;
do {
conversationId = BugleDatabaseOperations.getExistingConversation(db,
threadId, senderBlocked);
threadId++;
phoneNumber++;
}
while(!TextUtils.isEmpty(conversationId));
final ArrayList<ParticipantData> participants =
new ArrayList<ParticipantData>();
participants.add(ParticipantData.getFromRawPhoneBySystemLocale(Long.toString(phoneNumber)));
conversationId = BugleDatabaseOperations.getOrCreateConversation(db, threadId,
senderBlocked, participants);
assertNotNull("No conversation", conversationId);
final MessageData actual = BugleDatabaseOperations.readDraftMessageData(db, conversationId,
selfId);
assertNull(actual);
// Should clear/stub DB
final ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
final ActionMonitor monitor =
ReadDraftDataAction.readDraftData(conversationId, null, data, mockListener);
assertEquals("Unexpected number of calls to service", 1, calls.size());
assertTrue("Action not of type ReadDraftMessageAction",
calls.get(0).action instanceof ReadDraftDataAction);
final Action read = calls.get(0).action;
final Object result = read.executeAction();
assertTrue(result instanceof ReadDraftDataAction.DraftData);
final ReadDraftDataAction.DraftData draft = (ReadDraftDataAction.DraftData) result;
assertEquals("Draft message text differs", "", draft.message.getMessageText());
assertEquals("Draft self differs", selfId, draft.message.getSelfId());
assertEquals("Draft conversation differs", conversationId,
draft.conversation.getConversationId());
}
public void testWriteAndReadDraft() {
final Object data = "data";
final String draftMessage = "draftMessage";
final DatabaseWrapper db = DataModel.get().getDatabase();
final Cursor conversations = db.query(DatabaseHelper.CONVERSATIONS_TABLE,
new String[] { ConversationColumns._ID, ConversationColumns.CURRENT_SELF_ID }, null,
null, null /* groupBy */, null /* having */, null /* orderBy */);
if (conversations.moveToFirst()) {
final String conversationId = conversations.getString(0);
final String selfId = getOrCreateSelfId(db);
// Should clear/stub DB
final ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
final MessageData message = MessageData.createDraftSmsMessage(conversationId, selfId,
draftMessage);
WriteDraftMessageAction.writeDraftMessage(conversationId, message);
assertEquals("Failed to start service once for action", calls.size(), 1);
assertTrue("Action not SaveDraftMessageAction",
calls.get(0).action instanceof WriteDraftMessageAction);
final Action save = calls.get(0).action;
Object result = save.executeAction();
assertTrue("Expect row number string as result", result instanceof String);
// Should check DB
final ActionMonitor monitor =
ReadDraftDataAction.readDraftData(conversationId, null, data,
mockListener);
assertEquals("Expect two calls queued", 2, calls.size());
assertTrue("Expect action", calls.get(1).action instanceof ReadDraftDataAction);
final Action read = calls.get(1).action;
result = read.executeAction();
assertTrue(result instanceof ReadDraftDataAction.DraftData);
final ReadDraftDataAction.DraftData draft = (ReadDraftDataAction.DraftData) result;
assertEquals("Draft message text differs", draftMessage, draft.message.getMessageText());
// The conversation's self id is used as the draft's self id.
assertEquals("Draft self differs", conversations.getString(1),
draft.message.getSelfId());
assertEquals("Draft conversation differs", conversationId,
draft.conversation.getConversationId());
} else {
fail("No conversations in database");
}
}
public void testUpdateDraft() {
final String initialMessage = "initialMessage";
final String draftMessage = "draftMessage";
final long threadId = 1234567;
final boolean senderBlocked = false;
final String participantNumber = "5553456789";
final DatabaseWrapper db = DataModel.get().getDatabase();
final String conversationId = getOrCreateConversation(db, participantNumber, threadId,
senderBlocked);
final String selfId = getOrCreateSelfId(db);
final ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
// Insert initial message
MessageData initial = MessageData.createDraftSmsMessage(conversationId, selfId,
initialMessage);
BugleDatabaseOperations.updateDraftMessageData(db, conversationId, initial,
BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
initial = BugleDatabaseOperations.readDraftMessageData(db,
conversationId, selfId);
assertEquals("Initial text mismatch", initialMessage, initial.getMessageText());
// Now update the draft
final MessageData message = MessageData.createDraftSmsMessage(conversationId, selfId,
draftMessage);
WriteDraftMessageAction.writeDraftMessage(conversationId, message);
assertEquals("Failed to start service once for action", calls.size(), 1);
assertTrue("Action not SaveDraftMessageAction",
calls.get(0).action instanceof WriteDraftMessageAction);
final Action save = calls.get(0).action;
final Object result = save.executeAction();
assertTrue("Expect row number string as result", result instanceof String);
// Check DB
final MessageData actual = BugleDatabaseOperations.readDraftMessageData(db,
conversationId, selfId);
assertNotNull("Database missing draft", actual);
assertEquals("Draft text mismatch", draftMessage, actual.getMessageText());
assertNull("Draft messageId should be null", actual.getMessageId());
}
public void testBugleDatabaseDraftOperations() {
final String initialMessage = "initialMessage";
final String draftMessage = "draftMessage";
final long threadId = 1234599;
final boolean senderBlocked = false;
final String participantNumber = "5553456798";
final String subject = "subject here";
final DatabaseWrapper db = DataModel.get().getDatabase();
final String conversationId = getOrCreateConversation(db, participantNumber, threadId,
senderBlocked);
final String selfId = getOrCreateSelfId(db);
final String text = "This is some text";
final Uri mOutputUri = MediaScratchFileProvider.buildMediaScratchSpaceUri("txt");
OutputStream outputStream = null;
try {
outputStream = mContext.getContentResolver().openOutputStream(mOutputUri);
outputStream.write(text.getBytes());
} catch (final FileNotFoundException e) {
fail("Cannot open output file");
} catch (final IOException e) {
fail("Cannot write output file");
}
final MessageData initial =
MessageData.createDraftMmsMessage(conversationId, selfId, initialMessage, subject);
initial.addPart(MessagePartData.createMediaMessagePart(ContentType.MULTIPART_MIXED,
mOutputUri, 0, 0));
final String initialMessageId = BugleDatabaseOperations.updateDraftMessageData(db,
conversationId, initial, BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
assertNotNull(initialMessageId);
final MessageData initialDraft = BugleDatabaseOperations.readMessage(db, initialMessageId);
assertNotNull(initialDraft);
int cnt = 0;
for(final MessagePartData part : initialDraft.getParts()) {
if (part.isAttachment()) {
assertEquals(part.getContentUri(), mOutputUri);
} else {
assertEquals(part.getText(), initialMessage);
}
cnt++;
}
assertEquals("Wrong number of parts", 2, cnt);
InputStream inputStream = null;
try {
inputStream = mContext.getContentResolver().openInputStream(mOutputUri);
final byte[] buffer = new byte[256];
final int read = inputStream.read(buffer);
assertEquals(read, text.getBytes().length);
} catch (final FileNotFoundException e) {
fail("Cannot open input file");
} catch (final IOException e) {
fail("Cannot read input file");
}
final String moreText = "This is some more text";
final Uri mAnotherUri = MediaScratchFileProvider.buildMediaScratchSpaceUri("txt");
outputStream = null;
try {
outputStream = mContext.getContentResolver().openOutputStream(mAnotherUri);
outputStream.write(moreText.getBytes());
} catch (final FileNotFoundException e) {
fail("Cannot open output file");
} catch (final IOException e) {
fail("Cannot write output file");
}
final MessageData another =
MessageData.createDraftMmsMessage(conversationId, selfId, draftMessage, subject);
another.addPart(MessagePartData.createMediaMessagePart(ContentType.MMS_MULTIPART_MIXED,
mAnotherUri, 0, 0));
final String anotherMessageId = BugleDatabaseOperations.updateDraftMessageData(db,
conversationId, another, BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
assertNotNull(anotherMessageId);
final MessageData anotherDraft = BugleDatabaseOperations.readMessage(db, anotherMessageId);
assertNotNull(anotherDraft);
cnt = 0;
for(final MessagePartData part : anotherDraft.getParts()) {
if (part.isAttachment()) {
assertEquals(part.getContentUri(), mAnotherUri);
} else {
assertEquals(part.getText(), draftMessage);
}
cnt++;
}
assertEquals("Wrong number of parts", 2, cnt);
inputStream = null;
try {
inputStream = mContext.getContentResolver().openInputStream(mOutputUri);
assertNull("Original draft content should have been deleted", inputStream);
} catch (final FileNotFoundException e) {
}
inputStream = null;
try {
inputStream = mContext.getContentResolver().openInputStream(mAnotherUri);
final byte[] buffer = new byte[256];
final int read = inputStream.read(buffer);
assertEquals(read, moreText.getBytes().length);
} catch (final FileNotFoundException e) {
fail("Cannot open input file");
} catch (final IOException e) {
fail("Cannot read input file");
}
final MessageData last = null;
final String lastPartId = BugleDatabaseOperations.updateDraftMessageData(db,
conversationId, last, BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
assertNull(lastPartId);
inputStream = null;
try {
inputStream = mContext.getContentResolver().openInputStream(mAnotherUri);
assertNull("Original draft content should have been deleted", inputStream);
} catch (final FileNotFoundException e) {
}
}
private StubActionService mService;
@Override
public void setUp() throws Exception {
super.setUp();
final FakeContext context = new FakeContext(getTestContext());
final ContentProvider bugleProvider = new MessagingContentProvider();
final ProviderInfo bugleProviderInfo = new ProviderInfo();
bugleProviderInfo.authority = MessagingContentProvider.AUTHORITY;
bugleProvider.attachInfo(mContext, bugleProviderInfo);
context.addContentProvider(MessagingContentProvider.AUTHORITY, bugleProvider);
final ContentProvider mediaProvider = new MediaScratchFileProvider();
final ProviderInfo mediaProviderInfo = new ProviderInfo();
mediaProviderInfo.authority = MediaScratchFileProvider.AUTHORITY;
mediaProvider.attachInfo(mContext, mediaProviderInfo);
context.addContentProvider(MediaScratchFileProvider.AUTHORITY, mediaProvider);
mService = new StubActionService();
final FakeDataModel fakeDataModel = new FakeDataModel(context)
.withActionService(mService);
FakeFactory.registerWithFakeContext(getTestContext(), context)
.withDataModel(fakeDataModel);
}
}

View File

@@ -1,97 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel.data;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.FakeFactory;
import com.android.messaging.datamodel.FakeCursor;
import com.android.messaging.datamodel.data.ConversationMessageData.ConversationMessageViewColumns;
@SmallTest
public class ConversationMessageDataTest extends BugleTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
FakeFactory.register(getTestContext());
}
public void testBindFirstMessage() {
final FakeCursor testCursor = TestDataFactory.getConversationMessageCursor();
final ConversationMessageData data = new ConversationMessageData();
testCursor.moveToFirst();
data.bind(testCursor);
// TODO: Add before checking in all bound fields...
assertEquals(testCursor.getAt(ConversationMessageViewColumns.STATUS, 0).equals(
MessageData.BUGLE_STATUS_INCOMING_COMPLETE), data.getIsIncoming());
assertEquals(testCursor.getAt(ConversationMessageViewColumns.SENDER_PROFILE_PHOTO_URI,
0), data.getSenderProfilePhotoUri());
assertEquals(testCursor.getAt(ConversationMessageViewColumns.SENDER_FULL_NAME, 0),
data.getSenderFullName());
}
public void testBindTwice() {
final FakeCursor testCursor = TestDataFactory.getConversationMessageCursor();
final ConversationMessageData data = new ConversationMessageData();
testCursor.moveToPosition(1);
data.bind(testCursor);
assertEquals(TestDataFactory.getMessageText(testCursor, 1), data.getText());
assertEquals(testCursor.getAt(ConversationMessageViewColumns.RECEIVED_TIMESTAMP, 1),
data.getReceivedTimeStamp());
assertEquals(testCursor.getAt(ConversationMessageViewColumns.STATUS, 1).equals(
MessageData.BUGLE_STATUS_INCOMING_COMPLETE), data.getIsIncoming());
assertEquals(testCursor.getAt(ConversationMessageViewColumns.SENDER_PROFILE_PHOTO_URI,
1), data.getSenderProfilePhotoUri());
assertEquals(testCursor.getAt(ConversationMessageViewColumns.SENDER_FULL_NAME, 1),
data.getSenderFullName());
testCursor.moveToPosition(2);
data.bind(testCursor);
assertEquals(TestDataFactory.getMessageText(testCursor, 2), data.getText());
assertEquals(testCursor.getAt(ConversationMessageViewColumns.RECEIVED_TIMESTAMP, 2),
data.getReceivedTimeStamp());
assertEquals(testCursor.getAt(ConversationMessageViewColumns.STATUS, 2).equals(
MessageData.BUGLE_STATUS_INCOMING_COMPLETE), data.getIsIncoming());
assertEquals(testCursor.getAt(ConversationMessageViewColumns.SENDER_PROFILE_PHOTO_URI,
2), data.getSenderProfilePhotoUri());
assertEquals(testCursor.getAt(ConversationMessageViewColumns.SENDER_FULL_NAME, 2),
data.getSenderFullName());
}
public void testMessageClustering() {
final FakeCursor testCursor = TestDataFactory.getConversationMessageCursor();
final ConversationMessageData data = new ConversationMessageData();
testCursor.moveToPosition(0);
data.bind(testCursor);
assertFalse(data.getCanClusterWithPreviousMessage());
assertFalse(data.getCanClusterWithNextMessage());
testCursor.moveToPosition(1);
data.bind(testCursor);
assertFalse(data.getCanClusterWithPreviousMessage());
assertFalse(data.getCanClusterWithNextMessage());
testCursor.moveToPosition(2);
data.bind(testCursor);
assertFalse(data.getCanClusterWithPreviousMessage());
assertTrue(data.getCanClusterWithNextMessage()); // 2 and 3 can be clustered
testCursor.moveToPosition(3);
data.bind(testCursor);
assertTrue(data.getCanClusterWithPreviousMessage()); // 2 and 3 can be clustered
assertFalse(data.getCanClusterWithNextMessage());
}
}

View File

@@ -1,39 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel.data;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
import com.android.messaging.datamodel.FakeCursor;
@SmallTest
public class ConversationParticipantsDataTest extends BugleTestCase {
public void testBindParticipants() {
final FakeCursor testCursor = TestDataFactory.getConversationParticipantsCursor();
final ConversationParticipantsData data = new ConversationParticipantsData();
data.bind(testCursor);
assertEquals(data.getParticipantListExcludingSelf().size(), testCursor.getCount());
final ParticipantData participant2 = data.getParticipantById("2");
assertNotNull(participant2);
assertEquals(participant2.getFirstName(), testCursor.getAt(
ParticipantColumns.FIRST_NAME, 1) );
assertEquals(participant2.getSendDestination(), testCursor.getAt(
ParticipantColumns.SEND_DESTINATION, 1));
}
}

View File

@@ -1,347 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel.data;
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.provider.BaseColumns;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
import android.provider.MediaStore.Images.Media;
import com.android.messaging.datamodel.BugleDatabaseOperations;
import com.android.messaging.datamodel.DatabaseHelper;
import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns;
import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
import com.android.messaging.datamodel.DatabaseHelper.PartColumns;
import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
import com.android.messaging.datamodel.FakeCursor;
import com.android.messaging.datamodel.data.ConversationListItemData.ConversationListViewColumns;
import com.android.messaging.datamodel.data.ConversationMessageData.ConversationMessageViewColumns;
import com.android.messaging.util.Assert;
import com.android.messaging.util.ContactUtil;
import com.android.messaging.util.ContentType;
import java.util.Arrays;
import java.util.List;
/**
* A factory for fake objects that can be useful for multiple tests.
*/
public class TestDataFactory {
private final static String[] sConversationListCursorColumns = new String[] {
ConversationListViewColumns._ID,
ConversationListViewColumns.NAME,
ConversationListViewColumns.ICON,
ConversationListViewColumns.SNIPPET_TEXT,
ConversationListViewColumns.PREVIEW_URI,
ConversationListViewColumns.SORT_TIMESTAMP,
ConversationListViewColumns.READ,
ConversationListViewColumns.PREVIEW_CONTENT_TYPE,
ConversationListViewColumns.MESSAGE_STATUS,
};
private final static String[] sContactCursorColumns = new String[] {
Phone.CONTACT_ID,
Phone.DISPLAY_NAME_PRIMARY,
Phone.PHOTO_THUMBNAIL_URI,
Phone.NUMBER,
Phone.TYPE,
Phone.LABEL,
Phone.LOOKUP_KEY,
Phone._ID,
Phone.SORT_KEY_PRIMARY,
};
private final static String[] sFrequentContactCursorColumns = new String[] {
Contacts._ID,
Contacts.DISPLAY_NAME,
Contacts.PHOTO_URI,
Phone.LOOKUP_KEY,
};
private final static String[] sConversationMessageCursorColumns = new String[] {
ConversationMessageViewColumns._ID,
ConversationMessageViewColumns.CONVERSATION_ID,
ConversationMessageViewColumns.PARTICIPANT_ID,
ConversationMessageViewColumns.SENT_TIMESTAMP,
ConversationMessageViewColumns.RECEIVED_TIMESTAMP,
ConversationMessageViewColumns.STATUS,
ConversationMessageViewColumns.SENDER_FULL_NAME,
ConversationMessageViewColumns.SENDER_PROFILE_PHOTO_URI,
ConversationMessageViewColumns.PARTS_IDS,
ConversationMessageViewColumns.PARTS_CONTENT_TYPES,
ConversationMessageViewColumns.PARTS_CONTENT_URIS,
ConversationMessageViewColumns.PARTS_WIDTHS,
ConversationMessageViewColumns.PARTS_HEIGHTS,
ConversationMessageViewColumns.PARTS_TEXTS,
ConversationMessageViewColumns.PARTS_COUNT
};
private final static String[] sGalleryCursorColumns = new String[] {
Media._ID,
Media.DATA,
Media.WIDTH,
Media.HEIGHT,
Media.MIME_TYPE
};
public static FakeCursor getConversationListCursor() {
final Object[][] cursorData = new Object[][] {
new Object[] { Long.valueOf(1), "name1", "content://icon1",
"snippetText1", "content://snippetUri1", Long.valueOf(10), 1,
ContentType.IMAGE_JPEG, MessageData.BUGLE_STATUS_INCOMING_COMPLETE},
new Object[] { Long.valueOf(2), "name2", "content://icon2",
"snippetText2", "content://snippetUri2", Long.valueOf(20) + 24*60*60*1000,
0, ContentType.IMAGE_JPEG, MessageData.BUGLE_STATUS_INCOMING_COMPLETE},
new Object[] { Long.valueOf(3), "name3", "content://icon3",
"snippetText3", "content://snippetUri3", Long.valueOf(30) + 2*24*60*60*1000,
0, ContentType.IMAGE_JPEG, MessageData.BUGLE_STATUS_OUTGOING_COMPLETE}
};
return new FakeCursor(ConversationListItemData.PROJECTION, sConversationListCursorColumns,
cursorData);
}
public static final int CONVERSATION_LIST_CURSOR_READ_MESSAGE_INDEX = 0;
public static final int CONVERSATION_LIST_CURSOR_UNREAD_MESSAGE_INDEX = 1;
public static FakeCursor getEmptyConversationListCursor() {
return new FakeCursor(ConversationListItemData.PROJECTION, sConversationListCursorColumns,
new Object[][] {});
}
public static FakeCursor getConversationMessageCursor() {
final Object[][] cursorData = new Object[][] {
new Object[] { Long.valueOf(0), Long.valueOf(1), Long.valueOf(1),
Long.valueOf(10), Long.valueOf(10),
MessageData.BUGLE_STATUS_INCOMING_COMPLETE, "Alice", null,
"0", "text/plain", "''", -1, -1, "msg0", 1},
new Object[] { Long.valueOf(1), Long.valueOf(1), Long.valueOf(2),
Long.valueOf(20), Long.valueOf(20),
MessageData.BUGLE_STATUS_OUTGOING_COMPLETE, "Bob", null,
"1", "text/plain", "''", -1, -1, "msg1", 1},
new Object[] { Long.valueOf(2), Long.valueOf(1), Long.valueOf(1),
Long.valueOf(30), Long.valueOf(30),
MessageData.BUGLE_STATUS_OUTGOING_COMPLETE, "Alice", null,
"2", "contentType3", "'content://fakeUri3'", "0", "0", "msg1", 1},
new Object[] { Long.valueOf(3), Long.valueOf(1), Long.valueOf(1),
Long.valueOf(40), Long.valueOf(40),
MessageData.BUGLE_STATUS_OUTGOING_COMPLETE, "Alice", null,
"3|4", "'contentType4'|'text/plain'", "'content://fakeUri4'|''", "0|-1", "0|-1", "''|'msg3'", 2},
};
return new FakeCursor(
ConversationMessageData.getProjection(),
sConversationMessageCursorColumns,
cursorData);
}
public static String getMessageText(final FakeCursor messageCursor, final int row) {
final String allPartsText = messageCursor.getAt(ConversationMessageViewColumns.PARTS_TEXTS, row)
.toString();
final int partsCount = (Integer) messageCursor.getAt(
ConversationMessageViewColumns.PARTS_COUNT, row);
final String messageId = messageCursor.getAt(
ConversationMessageViewColumns._ID, row).toString();
final List<MessagePartData> parts = ConversationMessageData.makeParts(
messageCursor.getAt(ConversationMessageViewColumns.PARTS_IDS, row).toString(),
messageCursor.getAt(ConversationMessageViewColumns.PARTS_CONTENT_TYPES, row).toString(),
messageCursor.getAt(ConversationMessageViewColumns.PARTS_CONTENT_URIS, row).toString(),
messageCursor.getAt(ConversationMessageViewColumns.PARTS_WIDTHS, row).toString(),
messageCursor.getAt(ConversationMessageViewColumns.PARTS_HEIGHTS, row).toString(),
messageCursor.getAt(ConversationMessageViewColumns.PARTS_TEXTS, row).toString(),
partsCount,
messageId);
for (final MessagePartData part : parts) {
if (part.isText()) {
return part.getText();
}
}
return null;
}
// Indexes where to find consecutive and non consecutive messages from same participant
// (respect to index - 1).
public static final int MESSAGE_WITH_SAME_PARTICIPANT_AS_PREVIOUS = 3;
public static final int MESSAGE_WITH_DIFFERENT_PARTICIPANT_AS_PREVIOUS = 2;
public static FakeCursor getConversationParticipantsCursor() {
final String[] sConversationParticipantsCursorColumns = new String[] {
ParticipantColumns._ID,
ParticipantColumns.SUB_ID,
ParticipantColumns.NORMALIZED_DESTINATION,
ParticipantColumns.SEND_DESTINATION,
ParticipantColumns.FULL_NAME,
ParticipantColumns.FIRST_NAME,
ParticipantColumns.PROFILE_PHOTO_URI,
};
final Object[][] cursorData = new Object[][] {
new Object[] { 1, ParticipantData.OTHER_THAN_SELF_SUB_ID, "+15554567890",
"(555)456-7890", "alice in wonderland", "alice", "alice.png" },
new Object[] { 2, ParticipantData.OTHER_THAN_SELF_SUB_ID, "+15551011121",
"(555)101-1121", "bob the baker", "bob", "bob.png"},
new Object[] { 3, ParticipantData.OTHER_THAN_SELF_SUB_ID, "+15551314152",
"(555)131-4152", "charles in charge", "charles", "charles.png" },
};
return new FakeCursor(ParticipantData.ParticipantsQuery.PROJECTION,
sConversationParticipantsCursorColumns, cursorData);
}
public static final int CONTACT_LIST_CURSOR_FIRST_LEVEL_CONTACT_INDEX = 0;
public static final int CONTACT_LIST_CURSOR_SECOND_LEVEL_CONTACT_INDEX = 2;
/**
* Returns a cursor for the all contacts list consumable by ContactPickerFragment.
*/
public static FakeCursor getAllContactListCursor() {
final Object[][] cursorData = new Object[][] {
new Object[] { Long.valueOf(0), "John Smith", "content://uri1",
"425-555-1234", Phone.TYPE_HOME, "", "0", Long.valueOf(0), 0 },
new Object[] { Long.valueOf(1), "Sun Woo Kong", "content://uri2",
"425-555-1235", Phone.TYPE_MOBILE, "", "1", Long.valueOf(1), 1 },
new Object[] { Long.valueOf(1), "Sun Woo Kong", "content://uri2",
"425-555-1238", Phone.TYPE_HOME, "", "1", Long.valueOf(2), 2 },
new Object[] { Long.valueOf(2), "Anna Kinney", "content://uri3",
"425-555-1236", Phone.TYPE_MAIN, "", "3", Long.valueOf(3), 3 },
new Object[] { Long.valueOf(3), "Mike Jones", "content://uri3",
"425-555-1236", Phone.TYPE_MAIN, "", "5", Long.valueOf(4), 4 },
};
return new FakeCursor(ContactUtil.PhoneQuery.PROJECTION, sContactCursorColumns,
cursorData);
}
/**
* Returns a cursor for the frequent contacts list consumable by ContactPickerFragment.
* Note: make it so that this cursor is the generated result of getStrequentContactsCursor()
* and getAllContactListCursor(), i.e., expand the entries in getStrequentContactsCursor()
* with the details from getAllContactListCursor()
*/
public static FakeCursor getFrequentContactListCursor() {
final Object[][] cursorData = new Object[][] {
new Object[] { Long.valueOf(2), "Anna Kinney", "content://uri3",
"425-555-1236", Phone.TYPE_MAIN, "", "3", Long.valueOf(3), 0 },
new Object[] { Long.valueOf(1), "Sun Woo Kong", "content://uri2",
"425-555-1235", Phone.TYPE_MOBILE, "", "1", Long.valueOf(1), 1},
new Object[] { Long.valueOf(1), "Sun Woo Kong", "content://uri2",
"425-555-1238", Phone.TYPE_HOME, "", "1", Long.valueOf(2), 2 },
new Object[] { Long.valueOf(0), "John Smith", "content://uri1",
"425-555-1234", Phone.TYPE_HOME, "", "0", Long.valueOf(0), 3 },
};
return new FakeCursor(ContactUtil.PhoneQuery.PROJECTION, sContactCursorColumns,
cursorData);
}
/**
* Returns a strequent (starred + frequent) cursor (like the one produced by android contact
* provider's CONTENT_STREQUENT_URI query) that's consumable by FrequentContactsCursorBuilder.
*/
public static FakeCursor getStrequentContactsCursor() {
final Object[][] cursorData = new Object[][] {
new Object[] { Long.valueOf(0), "Anna Kinney", "content://uri1", "3" },
new Object[] { Long.valueOf(1), "Sun Woo Kong", "content://uri2", "1" },
new Object[] { Long.valueOf(2), "John Smith", "content://uri3", "0" },
// Email-only entry that shouldn't be included in the result.
new Object[] { Long.valueOf(3), "Email Contact", "content://uri4", "100" },
};
return new FakeCursor(ContactUtil.FrequentContactQuery.PROJECTION,
sFrequentContactCursorColumns, cursorData);
}
public static final int SMS_MMS_THREAD_ID_CURSOR_VALUE = 123456789;
public static FakeCursor getSmsMmsThreadIdCursor() {
final String[] ID_PROJECTION = { BaseColumns._ID };
final Object[][] cursorData = new Object[][] {
new Object[] { Long.valueOf(SMS_MMS_THREAD_ID_CURSOR_VALUE) },
};
return new FakeCursor(ID_PROJECTION, ID_PROJECTION, cursorData);
}
public static FakeCursor getGalleryGridCursor() {
final Object[][] cursorData = new Object[][] {
new Object[] { Long.valueOf(0), "/sdcard/image1", 100, 100, "image/jpeg" },
new Object[] { Long.valueOf(1), "/sdcard/image2", 200, 200, "image/png" },
new Object[] { Long.valueOf(2), "/sdcard/image3", 300, 300, "image/jpeg" },
};
return new FakeCursor(GalleryGridItemData.MEDIA_PROJECTION, sGalleryCursorColumns,
cursorData);
}
public static final int NUM_TEST_CONVERSATIONS = 10;
/**
* Create test data in our db.
*
* Ideally this will create more realistic data with more variety.
*/
public static void createTestData(final SQLiteDatabase db) {
BugleDatabaseOperations.clearParticipantIdCache();
// Timestamp for 1 day ago
final long yesterday = System.currentTimeMillis() - (24 * 60 * 60 * 1000);
final ContentValues conversationValues = new ContentValues();
for (int i = 1; i <= NUM_TEST_CONVERSATIONS; i++) {
conversationValues.put(ConversationColumns.NAME, "Conversation " + i);
final long conversationId = db.insert(DatabaseHelper.CONVERSATIONS_TABLE, null,
conversationValues);
final ContentValues messageValues = new ContentValues();
for (int m = 1; m <= 25; m++) {
// Move forward ten minutes per conversation, 1 minute per message.
final long messageTime = yesterday + (i * 10 * 60 * 1000) + (m * 60 * 1000);
messageValues.put(MessageColumns.RECEIVED_TIMESTAMP, messageTime);
messageValues.put(MessageColumns.CONVERSATION_ID, conversationId);
messageValues.put(MessageColumns.SENDER_PARTICIPANT_ID,
Math.abs(("" + messageTime).hashCode()) % 2);
final long messageId = db.insert(DatabaseHelper.MESSAGES_TABLE, null, messageValues);
// Create a text part for this message
final ContentValues partValues = new ContentValues();
partValues.put(PartColumns.MESSAGE_ID, messageId);
partValues.put(PartColumns.CONVERSATION_ID, conversationId);
partValues.put(PartColumns.TEXT, "Conversation: " + conversationId +
" Message: " + m);
db.insert(DatabaseHelper.PARTS_TABLE, null, partValues);
// Update the snippet for this conversation to the latest message inserted
conversationValues.clear();
conversationValues.put(ConversationColumns.LATEST_MESSAGE_ID, messageId);
final int updatedCount = db.update(DatabaseHelper.CONVERSATIONS_TABLE,
conversationValues,
"_id=?", new String[]{String.valueOf(conversationId)});
Assert.isTrue(updatedCount == 1);
}
}
}
public static List<MessagePartData> getTestDraftAttachments() {
final MessagePartData[] retParts = new MessagePartData[] {
new MessagePartData(ContentType.IMAGE_JPEG, Uri.parse("content://image"),
100, 100),
new MessagePartData(ContentType.VIDEO_3GPP, Uri.parse("content://video"),
100, 100),
new MessagePartData(ContentType.TEXT_VCARD, Uri.parse("content://vcard"),
0, 0),
new MessagePartData(ContentType.AUDIO_3GPP, Uri.parse("content://audio"),
0, 0)
};
return Arrays.asList(retParts);
}
}

View File

@@ -1,68 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel.media;
import android.text.TextUtils;
import java.util.List;
public class FakeImageRequest implements MediaRequest<FakeImageResource> {
public static final String INVALID_KEY = "invalid";
private final String mKey;
private final int mSize;
public FakeImageRequest(final String key, final int size) {
mKey = key;
mSize = size;
}
@Override
public String getKey() {
return mKey;
}
@Override
public FakeImageResource loadMediaBlocking(List<MediaRequest<FakeImageResource>> chainedTask)
throws Exception {
if (TextUtils.equals(mKey, INVALID_KEY)) {
throw new Exception();
} else {
return new FakeImageResource(mSize, mKey);
}
}
@Override
public int getCacheId() {
return FakeMediaCacheManager.FAKE_IMAGE_CACHE;
}
@SuppressWarnings("unchecked")
@Override
public MediaCache<FakeImageResource> getMediaCache() {
return (MediaCache<FakeImageResource>) MediaCacheManager.get().getOrCreateMediaCacheById(
getCacheId());
}
@Override
public int getRequestType() {
return MediaRequest.REQUEST_LOAD_MEDIA;
}
@Override
public MediaRequestDescriptor<FakeImageResource> getDescriptor() {
return null;
}
}

View File

@@ -1,55 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel.media;
public class FakeImageResource extends RefCountedMediaResource {
private boolean mClosed = false;
private boolean mCached = false;
private final int mSize;
private final String mImageId;
public FakeImageResource(final int size, final String imageId) {
super(null);
mSize = size;
mImageId = imageId;
}
public boolean isClosed() {
return mClosed;
}
public String getImageId() {
return mImageId;
}
public void setCached(final boolean cached) {
mCached = cached;
}
public boolean getCached() {
return mCached;
}
@Override
public int getMediaSize() {
return mSize;
}
@Override
protected void close() {
mClosed = true;
}
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel.media;
public class FakeMediaCacheManager extends MediaCacheManager {
// List of available fake cache ids.
public static final int FAKE_IMAGE_CACHE = 1;
public static final int FAKE_BATCH_IMAGE_CACHE = 2;
@Override
public MediaCache<?> createMediaCacheById(final int id) {
switch (id) {
case FAKE_IMAGE_CACHE:
// Make a cache of only 3 KB of data.
return new MediaCache<FakeImageResource>(3, FAKE_IMAGE_CACHE, "FakeImageCache");
case FAKE_BATCH_IMAGE_CACHE:
return new MediaCache<FakeImageResource>(10, FAKE_BATCH_IMAGE_CACHE,
"FakeBatchImageCache");
}
return null;
}
}

View File

@@ -1,112 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel.media;
import android.content.ContentResolver;
import android.graphics.BitmapFactory;
import android.net.Uri;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.MemoryCacheManager;
import com.android.messaging.util.ImageUtils;
import org.mockito.ArgumentCaptor;
import org.mockito.Matchers;
import org.mockito.Mockito;
import org.mockito.Spy;
import java.io.IOException;
@SmallTest
public class ImageRequestTest extends BugleTestCase {
private static final int DOWNSAMPLE_IMAGE_SIZE = 2;
@Spy protected ImageUtils spyImageUtils;
@Override
protected void setUp() throws Exception {
super.setUp();
FakeFactory.register(getTestContext())
.withMemoryCacheManager(new MemoryCacheManager())
.withMediaCacheManager(new BugleMediaCacheManager());
spyImageUtils = Mockito.spy(new ImageUtils());
ImageUtils.set(spyImageUtils);
}
public void testLoadImageUnspecifiedSize() {
final String uriString = ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
getContext().getPackageName() + "/" + R.drawable.ic_audio_light;
final Uri uri = Uri.parse(uriString);
final UriImageRequest imageRequest = new UriImageRequest(getContext(),
new UriImageRequestDescriptor(uri));
try {
final ImageResource imageResource = imageRequest.loadMediaBlocking(null);
final ArgumentCaptor<BitmapFactory.Options> options =
ArgumentCaptor.forClass(BitmapFactory.Options.class);
Mockito.verify(spyImageUtils).calculateInSampleSize(
options.capture(),
Matchers.eq(ImageRequest.UNSPECIFIED_SIZE),
Matchers.eq(ImageRequest.UNSPECIFIED_SIZE));
assertEquals(1, options.getValue().inSampleSize);
assertNotNull(imageResource);
assertNotNull(imageResource.getBitmap());
// Make sure there's no scaling on the bitmap.
final int bitmapWidth = imageResource.getBitmap().getWidth();
final int bitmapHeight = imageResource.getBitmap().getHeight();
assertEquals(options.getValue().outWidth, bitmapWidth);
assertEquals(options.getValue().outHeight, bitmapHeight);
} catch (final IOException e) {
fail("IO exception while trying to load image resource");
}
}
public void testLoadImageWithDownsampling() {
final String uriString = ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
getContext().getPackageName() + "/" + R.drawable.ic_audio_light;
final Uri uri = Uri.parse(uriString);
final UriImageRequest imageRequest = new UriImageRequest(getContext(),
new UriImageRequestDescriptor(uri, DOWNSAMPLE_IMAGE_SIZE, DOWNSAMPLE_IMAGE_SIZE,
false, true /* isStatic */, false /* cropToCircle */,
ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */,
ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */));
try {
final ImageResource imageResource = imageRequest.loadMediaBlocking(null);
final ArgumentCaptor<BitmapFactory.Options> options =
ArgumentCaptor.forClass(BitmapFactory.Options.class);
Mockito.verify(spyImageUtils).calculateInSampleSize(
options.capture(),
Matchers.eq(DOWNSAMPLE_IMAGE_SIZE), Matchers.eq(DOWNSAMPLE_IMAGE_SIZE));
assertNotSame(1, options.getValue().inSampleSize);
assertNotNull(imageResource);
assertNotNull(imageResource.getBitmap());
// Make sure there's down sampling on the bitmap.
final int bitmapWidth = imageResource.getBitmap().getWidth();
final int bitmapHeight = imageResource.getBitmap().getHeight();
assertTrue(bitmapWidth >= DOWNSAMPLE_IMAGE_SIZE &&
bitmapHeight >= DOWNSAMPLE_IMAGE_SIZE &&
(bitmapWidth <= DOWNSAMPLE_IMAGE_SIZE * 4 ||
bitmapHeight <= DOWNSAMPLE_IMAGE_SIZE * 4));
} catch (final IOException e) {
fail("IO exception while trying to load image resource");
}
}
}

View File

@@ -1,174 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.datamodel.media;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.FakeFactory;
import com.android.messaging.datamodel.MemoryCacheManager;
import com.android.messaging.datamodel.media.MediaResourceManager.MediaResourceLoadListener;
import java.util.concurrent.CountDownLatch;
@SmallTest
public class MediaResourceManagerTest extends BugleTestCase {
private static final int KB = 1024;
// Loaded image resource from the MediaResourceManager callback.
private FakeImageResource mImageResource;
private BindableMediaRequest<FakeImageResource> mImageRequest;
@Override
protected void setUp() throws Exception {
super.setUp();
FakeFactory.register(getTestContext())
.withMemoryCacheManager(new MemoryCacheManager())
.withMediaCacheManager(new FakeMediaCacheManager());
}
public void testLoadFromCache() {
final MediaResourceManager mediaResourceManager =
new MediaResourceManager();
MediaCacheManager.get().reclaim();
assertNotNull(mediaResourceManager);
// Load one image of 1KB
loadImage(mediaResourceManager, "image1", 1 * KB, false /* shouldBeCached */, false);
assertEquals("image1", mImageResource.getImageId());
final FakeImageResource loadedResource = mImageResource;
// Load the same image.
loadImage(mediaResourceManager, "image1", 1 * KB, true /* shouldBeCached */, false);
assertEquals(loadedResource, mImageResource);
}
public void testCacheEviction() {
final MediaResourceManager mediaResourceManager =
new MediaResourceManager();
MediaCacheManager.get().reclaim();
assertNotNull(mediaResourceManager);
// Load one image of 1KB
loadImage(mediaResourceManager, "image1", 1 * KB, false /* shouldBeCached */, false);
assertEquals("image1", mImageResource.getImageId());
// Load another image
loadImage(mediaResourceManager, "image2", 2 * KB, false /* shouldBeCached */, false);
assertEquals("image2", mImageResource.getImageId());
// Load another image. This should fill the cache and cause eviction of image1.
loadImage(mediaResourceManager, "image3", 2 * KB, false /* shouldBeCached */, false);
assertEquals("image3", mImageResource.getImageId());
// Load image1. It shouldn't be cached any more.
loadImage(mediaResourceManager, "image1", 1 * KB, false /* shouldBeCached */, false);
assertEquals("image1", mImageResource.getImageId());
}
public void testReclaimMemoryFromMediaCache() {
final MediaResourceManager mediaResourceManager =
new MediaResourceManager();
MediaCacheManager.get().reclaim();
assertNotNull(mediaResourceManager);
// Load one image of 1KB
loadImage(mediaResourceManager, "image1", 1 * KB, false /* shouldBeCached */, false);
assertEquals("image1", mImageResource.getImageId());
// Purge everything from the cache, now the image should no longer be cached.
MediaCacheManager.get().reclaim();
// The image resource should have no ref left.
assertEquals(0, mImageResource.getRefCount());
assertTrue(mImageResource.isClosed());
loadImage(mediaResourceManager, "image1", 1 * KB, false /* shouldBeCached */, false);
assertEquals("image1", mImageResource.getImageId());
}
public void testLoadInvalidImage() {
final MediaResourceManager mediaResourceManager =
new MediaResourceManager();
MediaCacheManager.get().reclaim();
assertNotNull(mediaResourceManager);
// Test the failure case with invalid resource.
loadImage(mediaResourceManager, FakeImageRequest.INVALID_KEY, 1 * KB, false,
true /* shouldFail */);
}
public void testLoadImageSynchronously() {
final MediaResourceManager mediaResourceManager =
new MediaResourceManager();
MediaCacheManager.get().reclaim();
assertNotNull(mediaResourceManager);
// Test a normal sync load.
final FakeImageRequest request = new FakeImageRequest("image1", 1 * KB);
final FakeImageResource resource = mediaResourceManager.requestMediaResourceSync(request);
assertNotNull(resource);
assertFalse(resource.isClosed());
assertNotSame(0, resource.getRefCount());
resource.release();
// Test a failed sync load.
final FakeImageRequest invalidRequest =
new FakeImageRequest(FakeImageRequest.INVALID_KEY, 1 * KB);
assertNull(mediaResourceManager.requestMediaResourceSync(invalidRequest));
}
private void loadImage(final MediaResourceManager manager, final String key,
final int size, final boolean shouldBeCached, final boolean shouldFail) {
try {
final CountDownLatch signal = new CountDownLatch(1);
mImageRequest = AsyncMediaRequestWrapper.createWith(new FakeImageRequest(key, size),
createAssertListener(shouldBeCached, shouldFail, signal));
mImageRequest.bind("1");
manager.requestMediaResourceAsync(mImageRequest);
// Wait for the asynchronous callback before proceeding.
signal.await();
} catch (final InterruptedException e) {
fail("Something interrupted the signal await.");
}
}
private MediaResourceLoadListener<FakeImageResource> createAssertListener(
final boolean shouldBeCached, final boolean shouldFail, final CountDownLatch signal) {
return new MediaResourceLoadListener<FakeImageResource>() {
@Override
public void onMediaResourceLoaded(final MediaRequest<FakeImageResource> request,
final FakeImageResource resource, final boolean isCached) {
assertEquals(mImageRequest, request);
assertNotNull(resource);
assertFalse(resource.isClosed());
assertNotSame(0, resource.getRefCount());
assertFalse(shouldFail);
assertEquals(shouldBeCached, resource.getCached());
resource.setCached(true);
mImageResource = resource;
signal.countDown();
}
@Override
public void onMediaResourceLoadError(
final MediaRequest<FakeImageResource> request, final Exception exception) {
assertTrue(shouldFail);
mImageResource = null;
signal.countDown();
}};
}
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
/**
* Purpose of this class is providing a workaround for https://b/14561718
*/
public class ActivityInstrumentationTestCaseIntent extends Intent {
public ActivityInstrumentationTestCaseIntent(Context packageContext, Class<?> cls) {
super(packageContext, cls);
}
@Override
public Intent setComponent(ComponentName component) {
// Ignore the ComponentName set, as the one ActivityUnitTest does is wrong (and actually
// unnecessary).
return this;
}
}

View File

@@ -1,52 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui;
import android.app.Activity;
import com.android.messaging.BugleTestCase;
import com.android.messaging.TestUtil;
/**
* Helper class that extends ActivityInstrumentationTestCase2 to provide some extra common
* initialization (eg. Mockito boilerplate).
*/
public class BugleActivityInstrumentationTestCase<T extends Activity>
extends android.test.ActivityInstrumentationTestCase2<T> {
static {
// Set flag during loading of test cases to prevent application initialization starting
BugleTestCase.setTestsRunning();
}
public BugleActivityInstrumentationTestCase(final Class<T> activityClass) {
super(activityClass);
}
@Override
protected void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(false);
TestUtil.testSetup(getInstrumentation().getTargetContext(), this);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
TestUtil.testTeardown(this);
}
}

View File

@@ -1,52 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui;
import com.android.messaging.FakeFactory;
import com.android.messaging.datamodel.DataModel;
import org.mockito.Mock;
import org.mockito.Mockito;
public abstract class BugleActivityTest extends BugleActivityUnitTestCase<BugleActionBarActivity> {
@Mock protected DataModel mDataModel;
public BugleActivityTest() {
super(BugleActionBarActivity.class);
}
@SuppressWarnings("unchecked")
@Override
protected void setUp() throws Exception {
super.setUp();
// Create activity
final ActivityInstrumentationTestCaseIntent intent =
new ActivityInstrumentationTestCaseIntent(getInstrumentation().getTargetContext(),
TestActivity.class);
startActivity(intent, null, null);
FakeFactory.register(getInstrumentation().getTargetContext())
.withDataModel(mDataModel);
}
public void testOnResumeDataModelCallback() {
getInstrumentation().callActivityOnStart(getActivity());
getInstrumentation().callActivityOnResume(getActivity());
Mockito.verify(mDataModel).onActivityResume();
}
}

View File

@@ -1,55 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui;
import android.app.Activity;
import android.view.ContextThemeWrapper;
import com.android.messaging.BugleTestCase;
import com.android.messaging.R;
import com.android.messaging.TestUtil;
/**
* Base class for activity unit test cases, provides boilerplate setup/teardown.
*/
public abstract class BugleActivityUnitTestCase<T extends Activity> extends
android.test.ActivityUnitTestCase<T> {
static {
// Set flag during loading of test cases to prevent application initialization starting
BugleTestCase.setTestsRunning();
}
public BugleActivityUnitTestCase(final Class<T> activityClass) {
super(activityClass);
}
@SuppressWarnings("unchecked")
@Override
protected void setUp() throws Exception {
super.setUp();
TestUtil.testSetup(getInstrumentation().getTargetContext(), this);
setActivityContext(new ContextThemeWrapper(getInstrumentation().getTargetContext(),
R.style.Theme_AppCompat_Light_DarkActionBar));
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
TestUtil.testTeardown(this);
}
}

View File

@@ -1,61 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui;
import androidx.viewpager.widget.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SimpleCursorAdapter;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
public class CustomHeaderViewPagerTest extends ViewTest<CustomHeaderViewPager> {
@Override
protected void setUp() throws Exception {
super.setUp();
FakeFactory.register(getInstrumentation().getTargetContext());
}
public void testBindFirstLevel() {
final CustomHeaderViewPager view = new CustomHeaderViewPager(getActivity(), null);
final SimpleCursorAdapter adapter =
new SimpleCursorAdapter(getActivity(), 0, null, null, null, 0);
final CustomHeaderPagerViewHolder[] viewHolders = {
new FakeListViewHolder(getActivity(), adapter),
new FakeListViewHolder(getActivity(), adapter)
};
view.setViewHolders(viewHolders);
final ViewPager pager = (ViewPager) view.findViewById(R.id.pager);
final ViewGroup tabStrip = (ViewGroup) view.findViewById(R.id.tab_strip);
final ViewPagerTabStrip realTab = (ViewPagerTabStrip) tabStrip.getChildAt(0);
assertEquals(2, realTab.getChildCount());
View headerTitleButton = realTab.getChildAt(1);
// Click on the first page. Now the view pager should switch to that page accordingly.
clickButton(headerTitleButton);
assertEquals(1, pager.getCurrentItem());
}
@Override
protected int getLayoutIdForView() {
// All set up should be done by creating a CustomHeaderViewPager which handles inflating
// the layout
return 0;
}
}

View File

@@ -1,60 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui;
import android.content.Context;
import android.widget.CursorAdapter;
import com.android.messaging.R;
/**
* A fake {@link CustomHeaderPagerListViewHolder} for CustomHeaderViewPager tests only.
*/
public class FakeListViewHolder extends CustomHeaderPagerListViewHolder {
public FakeListViewHolder(final Context context, final CursorAdapter adapter) {
super(context, adapter);
}
@Override
protected int getLayoutResId() {
return 0;
}
@Override
protected int getPageTitleResId() {
return android.R.string.untitled;
}
@Override
protected int getEmptyViewResId() {
return R.id.empty_view;
}
@Override
protected int getListViewResId() {
return android.R.id.list;
}
@Override
protected int getEmptyViewTitleResId() {
return R.string.contact_list_empty_text;
}
@Override
protected int getEmptyViewImageResId() {
return R.drawable.ic_oobe_freq_list;
}
}

View File

@@ -1,120 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.res.Configuration;
import android.view.View;
/**
* Helper class that extends Bugle.ui.ActivityInstrumentationTestCase to provide common behavior
* across fragment tests.
*/
public abstract class FragmentTestCase<T extends Fragment>
extends BugleActivityInstrumentationTestCase<TestActivity> {
protected T mFragment;
protected Class<T> mFragmentClass;
public FragmentTestCase(final Class<T> fragmentClass) {
super(TestActivity.class);
mFragmentClass = fragmentClass;
}
@Override
protected void setUp() throws Exception {
super.setUp();
}
protected T getFragment() {
// Fragment creation deferred (typically until test time) so that factory/appcontext is
// ready.
if (mFragment == null) {
try {
mFragment = mFragmentClass.newInstance();
} catch (final InstantiationException e) {
throw new IllegalStateException("Failed to instantiate fragment");
} catch (final IllegalAccessException e) {
throw new IllegalStateException("Failed to instantiate fragment");
}
}
return mFragment;
}
protected void attachFragment() {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
final FragmentManager fragmentManager = getActivity().getFragmentManager();
fragmentManager.beginTransaction().add(mFragment, null /* tag */).commit();
}
});
getInstrumentation().waitForIdleSync();
}
@Override
protected void tearDown() throws Exception {
// In landscape mode, sleep for a second first.
// The reason is: our UI tests don't wait for the UI thread to finish settling down
// before exiting (because they can't know when the UI thread is done). In portrait mode,
// things generally work fine here -- the UI thread is done by the time the test is done.
// In landscape mode, though, since the launcher is in portrait mode, there is a lot of
// extra work that happens in our UI when the app launches into landscape mode, and the
// UI is often not done by the time the test finishes running. So then our teardown
// nulls out the Factory, and then the UI keeps running and derefs the null factory,
// and things blow up.
// So ... as a cheap hack, sleep for one second before finishing the teardown of UI
// tests, but only do it in landscape mode (so that developers running it in portrait
// mode can still run the tests faster).
if (this.getInstrumentation().getTargetContext().getResources().
getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
super.tearDown();
}
protected void clickButton(final View view) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
view.performClick();
}
});
getInstrumentation().waitForIdleSync();
}
protected void setFocus(final View view, final boolean focused) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if (focused) {
view.requestFocus();
} else {
view.clearFocus();
}
}
});
getInstrumentation().waitForIdleSync();
}
}

View File

@@ -1,123 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui;
import android.content.Context;
import android.net.Uri;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.test.filters.MediumTest;
import com.android.messaging.FakeFactory;
import com.android.messaging.datamodel.data.MessagePartData;
import java.util.Arrays;
import java.util.Collections;
@MediumTest
public class MultiAttachmentLayoutTest extends ViewTest<MultiAttachmentLayout> {
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getInstrumentation().getTargetContext();
FakeFactory.register(context);
}
@Override
protected MultiAttachmentLayout getView() {
if (mView == null) {
// View creation deferred (typically until test time) so that factory/appcontext is
// ready.
mView = new MultiAttachmentLayout(getActivity(), null);
mView.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
}
return mView;
}
protected void verifyContent(
final MultiAttachmentLayout view,
final int imageCount,
final int plusCount) {
final int count = view.getChildCount();
int actualImageCount = 0;
final boolean needPlusText = plusCount > 0;
boolean hasPlusText = false;
for (int i = 0; i < count; i++) {
final View child = view.getChildAt(i);
if (child instanceof AsyncImageView) {
actualImageCount++;
} else if (child instanceof TextView) {
assertTrue(plusCount > 0);
assertTrue(((TextView) child).getText().toString().contains("" + plusCount));
hasPlusText = true;
} else {
// Nothing other than image and overflow text view should appear in this layout.
fail("unexpected view in layout. view = " + child);
}
}
assertEquals(imageCount, actualImageCount);
assertEquals(needPlusText, hasPlusText);
}
public void testBindTwoAttachments() {
final MultiAttachmentLayout view = getView();
final MessagePartData testAttachment1 = MessagePartData.createMediaMessagePart(
"image/jpeg", Uri.parse("content://uri1"), 100, 100);
final MessagePartData testAttachment2 = MessagePartData.createMediaMessagePart(
"image/jpeg", Uri.parse("content://uri2"), 100, 100);
view.bindAttachments(createAttachmentList(testAttachment1, testAttachment2),
null /* transitionRect */, 2);
verifyContent(view, 2, 0);
}
public void testBindFiveAttachments() {
final MultiAttachmentLayout view = getView();
final MessagePartData testAttachment1 = MessagePartData.createMediaMessagePart(
"image/jpeg", Uri.parse("content://uri1"), 100, 100);
final MessagePartData testAttachment2 = MessagePartData.createMediaMessagePart(
"image/jpeg", Uri.parse("content://uri2"), 100, 100);
final MessagePartData testAttachment3 = MessagePartData.createMediaMessagePart(
"image/jpeg", Uri.parse("content://uri3"), 100, 100);
final MessagePartData testAttachment4 = MessagePartData.createMediaMessagePart(
"image/jpeg", Uri.parse("content://uri4"), 100, 100);
final MessagePartData testAttachment5 = MessagePartData.createMediaMessagePart(
"image/jpeg", Uri.parse("content://uri5"), 100, 100);
view.bindAttachments(createAttachmentList(testAttachment1, testAttachment2, testAttachment3,
testAttachment4, testAttachment5), null /* transitionRect */, 5);
verifyContent(view, 4, 1);
}
public void testBindTwice() {
// Put the above two tests together so we can simulate binding twice.
testBindTwoAttachments();
testBindFiveAttachments();
}
private Iterable<MessagePartData> createAttachmentList(final MessagePartData... attachments) {
return Collections.unmodifiableList(Arrays.asList(attachments));
}
@Override
protected int getLayoutIdForView() {
return 0; // We construct the view with getView().
}
}

View File

@@ -1,66 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui;
import android.view.View;
/**
* Base class for view tests. Derived class just has to provide a layout id. Tests can then just
* call getView() to get a created view and test its behavior.
*/
public abstract class ViewTest<T extends View> extends BugleActivityUnitTestCase<TestActivity> {
public ViewTest() {
super(TestActivity.class);
}
protected T mView;
@SuppressWarnings("unchecked")
@Override
protected void setUp() throws Exception {
super.setUp();
// Create activity
final ActivityInstrumentationTestCaseIntent intent =
new ActivityInstrumentationTestCaseIntent(getInstrumentation().getTargetContext(),
TestActivity.class);
startActivity(intent, null, null);
}
@SuppressWarnings("unchecked")
protected T getView() {
if (mView == null) {
// View creation deferred (typically until test time) so that factory/appcontext is
// ready.
mView = (T) getActivity().getLayoutInflater().inflate(getLayoutIdForView(), null);
}
return mView;
}
protected void clickButton(final View view) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
view.performClick();
}
});
getInstrumentation().waitForIdleSync();
}
protected abstract int getLayoutIdForView();
}

View File

@@ -1,166 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui.attachmentchooser;
import android.app.Fragment;
import android.widget.CheckBox;
import androidx.test.filters.LargeTest;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.DataModel;
import com.android.messaging.datamodel.data.DraftMessageData;
import com.android.messaging.datamodel.data.MessageData;
import com.android.messaging.datamodel.data.MessagePartData;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.ui.FragmentTestCase;
import com.android.messaging.ui.TestActivity.FragmentEventListener;
import com.android.messaging.ui.attachmentchooser.AttachmentChooserFragment.AttachmentChooserFragmentHost;
import com.android.messaging.ui.conversationlist.ConversationListFragment;
import org.mockito.ArgumentMatcher;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Unit tests for {@link ConversationListFragment}.
*/
@LargeTest
public class AttachmentChooserFragmentTest extends FragmentTestCase<AttachmentChooserFragment> {
@Mock protected DataModel mockDataModel;
@Mock protected DraftMessageData mockDraftMessageData;
@Mock protected AttachmentChooserFragmentHost mockHost;
private static final String CONVERSATION_ID = "cid";
/** A custom argument matcher that checks whether the set argument passed in is a set
* with identical attachment data as the given set.
*/
private class IsSetOfGivenAttachments implements ArgumentMatcher<Set<MessagePartData>> {
private final Set<MessagePartData> mGivenParts;
public IsSetOfGivenAttachments(final Set<MessagePartData> givenParts) {
mGivenParts = givenParts;
}
@Override
public boolean matches(final Set<MessagePartData> actualSet) {
if (actualSet.size() != mGivenParts.size()) {
return false;
}
return mGivenParts.containsAll(actualSet) && actualSet.containsAll(mGivenParts);
}
}
public AttachmentChooserFragmentTest() {
super(AttachmentChooserFragment.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
FakeFactory.register(this.getInstrumentation().getTargetContext())
.withDataModel(mockDataModel);
}
private void loadWith(final List<MessagePartData> attachments) {
Mockito.when(mockDraftMessageData.isBound(Matchers.anyString()))
.thenReturn(true);
Mockito.doReturn(mockDraftMessageData)
.when(mockDataModel)
.createDraftMessageData(Mockito.anyString());
Mockito.doReturn(attachments)
.when(mockDraftMessageData)
.getReadOnlyAttachments();
Mockito.when(mockDataModel.createDraftMessageData(
Matchers.anyString()))
.thenReturn(mockDraftMessageData);
// Create fragment synchronously to avoid need for volatile, synchronization etc.
final AttachmentChooserFragment fragment = getFragment();
// Binding to model happens when attaching fragment to activity, so hook into test
// activity to do so.
getActivity().setFragmentEventListener(new FragmentEventListener() {
@Override
public void onAttachFragment(final Fragment attachedFragment) {
if (fragment == attachedFragment) {
fragment.setConversationId(CONVERSATION_ID);
}
}
});
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
fragment.setHost(mockHost);
getActivity().setFragment(fragment);
Mockito.verify(mockDataModel).createDraftMessageData(
Mockito.matches(CONVERSATION_ID));
Mockito.verify(mockDraftMessageData).loadFromStorage(
Matchers.eq(fragment.mBinding), Matchers.eq((MessageData) null),
Matchers.eq(false));
}
});
// Now load the cursor
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
fragment.onDraftChanged(mockDraftMessageData, DraftMessageData.ALL_CHANGED);
}
});
getInstrumentation().waitForIdleSync();
}
public void testUnselect() {
final List<MessagePartData> attachments = TestDataFactory.getTestDraftAttachments();
loadWith(attachments);
final AttachmentGridView attachmentGridView = (AttachmentGridView)
getFragment().getView().findViewById(R.id.grid);
assertEquals("bad view count", attachments.size(),
attachmentGridView.getAdapter().getCount());
final AttachmentGridItemView itemView = (AttachmentGridItemView)
attachmentGridView.getChildAt(0);
assertEquals(attachmentGridView, itemView.testGetHostInterface());
final CheckBox checkBox = (CheckBox) itemView.findViewById(R.id.checkbox);
assertEquals(true, checkBox.isChecked());
assertEquals(true, attachmentGridView.isItemSelected(itemView.mAttachmentData));
clickButton(checkBox);
assertEquals(false, checkBox.isChecked());
assertEquals(false, attachmentGridView.isItemSelected(itemView.mAttachmentData));
final AttachmentGridItemView itemView2 = (AttachmentGridItemView)
attachmentGridView.getChildAt(1);
final CheckBox checkBox2 = (CheckBox) itemView2.findViewById(R.id.checkbox);
clickButton(checkBox2);
getFragment().confirmSelection();
final MessagePartData[] attachmentsToRemove = new MessagePartData[] {
itemView.mAttachmentData, itemView2.mAttachmentData };
Mockito.verify(mockDraftMessageData).removeExistingAttachments(Matchers.argThat(
new IsSetOfGivenAttachments(new HashSet<>(Arrays.asList(attachmentsToRemove)))));
Mockito.verify(mockDraftMessageData).saveToStorage(Matchers.eq(getFragment().mBinding));
Mockito.verify(mockHost).onConfirmSelection();
}
}

View File

@@ -1,127 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui.contact;
import android.content.Context;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
import android.view.View;
import android.widget.TextView;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.FakeCursor;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.data.ContactListItemData;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.ui.ContactIconView;
import com.android.messaging.ui.ViewTest;
import org.mockito.Mock;
import org.mockito.Mockito;
public class ContactListItemViewTest extends ViewTest<ContactListItemView> {
@Mock ContactListItemView.HostInterface mockHost;
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getInstrumentation().getTargetContext();
FakeFactory.register(context)
.withDataModel(new FakeDataModel(context));
}
protected void verifyAddedContactForData(final ContactListItemData data,
final ContactListItemView view) {
Mockito.verify(mockHost).onContactListItemClicked(data, view);
}
protected void verifyContent(
final ContactListItemView view,
final String contactName,
final String contactDetail,
final String avatarUrl,
final boolean showAvatar) {
final TextView contactNameView = (TextView) view.findViewById(R.id.contact_name);
final TextView contactDetailView = (TextView) view.findViewById(R.id.contact_details);
final ContactIconView avatarView = (ContactIconView) view.findViewById(R.id.contact_icon);
assertNotNull(contactNameView);
assertEquals(contactName, contactNameView.getText());
assertNotNull(contactDetail);
assertEquals(contactDetail, contactDetailView.getText());
assertNotNull(avatarView);
if (showAvatar) {
assertTrue(avatarView.mImageRequestBinding.isBound());
assertEquals(View.VISIBLE, avatarView.getVisibility());
} else {
assertFalse(avatarView.mImageRequestBinding.isBound());
assertEquals(View.INVISIBLE, avatarView.getVisibility());
}
}
public void testBindFirstLevel() {
final ContactListItemView view = getView();
final FakeCursor cursor = TestDataFactory.getAllContactListCursor();
final int row = TestDataFactory.CONTACT_LIST_CURSOR_FIRST_LEVEL_CONTACT_INDEX;
cursor.moveToPosition(row);
view.bind(cursor, mockHost, false, null);
verifyContent(view, (String) cursor.getAt(Contacts.DISPLAY_NAME, row),
(String) cursor.getAt(Phone.NUMBER, row),
(String) cursor.getAt(Contacts.PHOTO_THUMBNAIL_URI, row), true);
}
public void testBindSecondLevel() {
final ContactListItemView view = getView();
final FakeCursor cursor = TestDataFactory.getAllContactListCursor();
final int row = TestDataFactory.CONTACT_LIST_CURSOR_SECOND_LEVEL_CONTACT_INDEX;
cursor.moveToPosition(row);
view.bind(cursor, mockHost, false, null);
verifyContent(view, (String) cursor.getAt(Contacts.DISPLAY_NAME, row),
(String) cursor.getAt(Phone.NUMBER, row),
(String) cursor.getAt(Contacts.PHOTO_THUMBNAIL_URI, row), false);
}
public void testClickAddedContact() {
final ContactListItemView view = getView();
final FakeCursor cursor = TestDataFactory.getAllContactListCursor();
cursor.moveToFirst();
view.bind(cursor, mockHost, false, null);
view.performClick();
verifyAddedContactForData(view.mData, view);
}
public void testBindTwice() {
final ContactListItemView view = getView();
final FakeCursor cursor = TestDataFactory.getAllContactListCursor();
cursor.moveToFirst();
view.bind(cursor, mockHost, false, null);
cursor.moveToNext();
view.bind(cursor, mockHost, false, null);
verifyContent(view, (String) cursor.getAt(Contacts.DISPLAY_NAME, 1),
(String) cursor.getAt(Phone.NUMBER, 1),
(String) cursor.getAt(Contacts.PHOTO_THUMBNAIL_URI, 1), true);
}
@Override
protected int getLayoutIdForView() {
return R.layout.contact_list_item_view;
}
}

View File

@@ -1,219 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui.contact;
import android.content.Context;
import android.database.Cursor;
import android.view.View;
import android.widget.ListView;
import androidx.test.filters.LargeTest;
import androidx.viewpager.widget.ViewPager;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.action.ActionTestHelpers;
import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService;
import com.android.messaging.datamodel.action.GetOrCreateConversationAction;
import com.android.messaging.datamodel.data.ContactPickerData;
import com.android.messaging.datamodel.data.ParticipantData;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.ui.CustomHeaderViewPagerAdapter;
import com.android.messaging.ui.FragmentTestCase;
import com.android.messaging.ui.UIIntents;
import com.android.messaging.ui.contact.ContactPickerFragment.ContactPickerFragmentHost;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import java.util.List;
/**
* Unit tests for {@link ContactPickerFragment}.
*/
@LargeTest
public class ContactPickerFragmentTest
extends FragmentTestCase<ContactPickerFragment> {
@Mock protected ContactPickerData mMockContactPickerData;
@Mock protected UIIntents mMockUIIntents;
@Mock protected ContactPickerFragmentHost mockHost;
protected FakeDataModel mFakeDataModel;
private ActionTestHelpers.StubActionService mService;
public ContactPickerFragmentTest() {
super(ContactPickerFragment.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getInstrumentation().getTargetContext();
mService = new StubActionService();
mFakeDataModel = new FakeDataModel(context)
.withContactPickerData(mMockContactPickerData)
.withActionService(mService);
FakeFactory.register(context)
.withDataModel(mFakeDataModel)
.withUIIntents(mMockUIIntents);
}
/**
* Helper method to initialize the ContactPickerFragment and its data.
*/
private ContactPickerFragmentTest initFragment(final int initialMode) {
Mockito.when(mMockContactPickerData.isBound(Matchers.anyString()))
.thenReturn(true);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
final ContactPickerFragment fragment = getFragment();
fragment.setHost(mockHost);
fragment.setContactPickingMode(initialMode, false);
getActivity().setFragment(fragment);
Mockito.verify(mMockContactPickerData).init(fragment.getLoaderManager(),
fragment.mBinding);
}
});
getInstrumentation().waitForIdleSync();
return this;
}
/**
* Bind the datamodel with all contacts cursor to populate the all contacts list in the
* fragment.
*/
private ContactPickerFragmentTest loadWithAllContactsCursor(final Cursor cursor) {
Mockito.when(mMockContactPickerData.isBound(Matchers.anyString()))
.thenReturn(true);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
getFragment().onAllContactsCursorUpdated(cursor);
}
});
getInstrumentation().waitForIdleSync();
return this;
}
/**
* Bind the datamodel with frequent contacts cursor to populate the contacts list in the
* fragment.
*/
private ContactPickerFragmentTest loadWithFrequentContactsCursor(final Cursor cursor) {
Mockito.when(mMockContactPickerData.isBound(Matchers.anyString()))
.thenReturn(true);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
getFragment().onFrequentContactsCursorUpdated(cursor);
}
});
getInstrumentation().waitForIdleSync();
return this;
}
/**
* Test the initial state of the fragment before loading data.
*/
public void testInitialState() {
initFragment(ContactPickerFragment.MODE_PICK_INITIAL_CONTACT);
// Make sure that the frequent contacts view is shown by default.
final ViewPager pager = (ViewPager) getFragment().getView().findViewById(R.id.pager);
final View currentPagedView = pager.getChildAt(pager.getCurrentItem());
final View frequentContactsView = ((CustomHeaderViewPagerAdapter) pager.getAdapter())
.getViewHolder(0).getView(null);
assertEquals(frequentContactsView, currentPagedView);
}
/**
* Verifies that list view gets correctly populated given a cursor.
*/
public void testLoadAllContactsList() {
final Cursor cursor = TestDataFactory.getAllContactListCursor();
initFragment(ContactPickerFragment.MODE_PICK_INITIAL_CONTACT)
.loadWithAllContactsCursor(cursor);
final ListView listView = (ListView) getFragment().getView()
.findViewById(R.id.all_contacts_list);
assertEquals(cursor.getCount(), listView.getCount());
}
/**
* Verifies that list view gets correctly populated given a cursor.
*/
public void testLoadFrequentContactsList() {
final Cursor cursor = TestDataFactory.getFrequentContactListCursor();
initFragment(ContactPickerFragment.MODE_PICK_INITIAL_CONTACT)
.loadWithFrequentContactsCursor(cursor);
final ListView listView = (ListView) getFragment().getView()
.findViewById(R.id.frequent_contacts_list);
assertEquals(cursor.getCount(), listView.getCount());
}
public void testPickInitialContact() {
final Cursor cursor = TestDataFactory.getFrequentContactListCursor();
initFragment(ContactPickerFragment.MODE_PICK_INITIAL_CONTACT)
.loadWithFrequentContactsCursor(cursor);
final ListView listView = (ListView) getFragment().getView()
.findViewById(R.id.frequent_contacts_list);
// Click on the first contact to add it.
final ContactListItemView cliv = (ContactListItemView) listView.getChildAt(0);
clickButton(cliv);
final ContactRecipientAutoCompleteView chipsView = (ContactRecipientAutoCompleteView)
getFragment().getView()
.findViewById(R.id.recipient_text_view);
// Verify the contact is added to the chips view.
final List<ParticipantData> participants =
chipsView.getRecipientParticipantDataForConversationCreation();
assertEquals(1, participants.size());
assertEquals(cliv.mData.getDestination(), participants.get(0).getSendDestination());
assertTrue(mService.getCalls().get(0).action instanceof GetOrCreateConversationAction);
}
public void testLeaveChipsMode() {
final Cursor cursor = TestDataFactory.getFrequentContactListCursor();
initFragment(ContactPickerFragment.MODE_CHIPS_ONLY)
.loadWithFrequentContactsCursor(cursor);
// Click on the add more participants button
// TODO: Figure out a way to click on the add more participants button now that
// it's part of the menu.
// final ImageButton AddMoreParticipantsButton = (ImageButton) getFragment().getView()
// .findViewById(R.id.add_more_participants_button);
// clickButton(AddMoreParticipantsButton);
// Mockito.verify(mockHost).onInitiateAddMoreParticipants();
}
public void testPickMoreContacts() {
final Cursor cursor = TestDataFactory.getFrequentContactListCursor();
initFragment(ContactPickerFragment.MODE_PICK_MORE_CONTACTS)
.loadWithFrequentContactsCursor(cursor);
final ListView listView = (ListView) getFragment().getView()
.findViewById(R.id.frequent_contacts_list);
// Click on the first contact to add it.
final ContactListItemView cliv = (ContactListItemView) listView.getChildAt(0);
clickButton(cliv);
// Verify that we don't attempt to create a conversation right away.
assertEquals(0, mService.getCalls().size());
}
}

View File

@@ -1,184 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui.conversation;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.isNull;
import android.content.Context;
import android.media.MediaPlayer;
import android.view.View;
import android.widget.EditText;
import androidx.test.filters.MediumTest;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.DataModel;
import com.android.messaging.datamodel.binding.Binding;
import com.android.messaging.datamodel.binding.BindingBase;
import com.android.messaging.datamodel.data.ConversationData;
import com.android.messaging.datamodel.data.DraftMessageData;
import com.android.messaging.datamodel.data.DraftMessageData.CheckDraftForSendTask;
import com.android.messaging.datamodel.data.DraftMessageData.CheckDraftTaskCallback;
import com.android.messaging.datamodel.data.MessageData;
import com.android.messaging.datamodel.data.MessagePartData;
import com.android.messaging.ui.ViewTest;
import com.android.messaging.ui.conversation.ComposeMessageView.IComposeMessageViewHost;
import com.android.messaging.util.BugleGservices;
import com.android.messaging.util.FakeMediaUtil;
import com.android.messaging.util.ImeUtil;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.util.ArrayList;
import java.util.Collections;
@MediumTest
public class ComposeMessageViewTest extends ViewTest<ComposeMessageView> {
private Context mContext;
@Mock protected DataModel mockDataModel;
@Mock protected DraftMessageData mockDraftMessageData;
@Mock protected BugleGservices mockBugleGservices;
@Mock protected ImeUtil mockImeUtil;
@Mock protected IComposeMessageViewHost mockIComposeMessageViewHost;
@Mock protected MediaPlayer mockMediaPlayer;
@Mock protected ConversationInputManager mockInputManager;
@Mock protected ConversationData mockConversationData;
Binding<ConversationData> mConversationBinding;
@Override
protected void setUp() throws Exception {
super.setUp();
mContext = getInstrumentation().getTargetContext();
FakeFactory.register(mContext)
.withDataModel(mockDataModel)
.withBugleGservices(mockBugleGservices)
.withMediaUtil(new FakeMediaUtil(mockMediaPlayer));
Mockito.doReturn(true).when(mockConversationData).isBound(Mockito.anyString());
mConversationBinding = BindingBase.createBinding(this);
mConversationBinding.bind(mockConversationData);
}
@Override
protected ComposeMessageView getView() {
final ComposeMessageView view = super.getView();
view.setInputManager(mockInputManager);
view.setConversationDataModel(BindingBase.createBindingReference(mConversationBinding));
return view;
}
@Override
protected int getLayoutIdForView() {
return R.layout.compose_message_view;
}
public void testSend() {
Mockito.when(mockDraftMessageData.getReadOnlyAttachments())
.thenReturn(Collections.unmodifiableList(new ArrayList<MessagePartData>()));
Mockito.when(mockDraftMessageData.getIsDefaultSmsApp()).thenReturn(true);
Mockito.when(mockIComposeMessageViewHost.isReadyForAction()).thenReturn(true);
final ComposeMessageView view = getView();
final MessageData message = MessageData.createDraftSmsMessage("fake_id", "just_a_self_id",
"Sample Message");
Mockito.when(mockDraftMessageData.isBound(Matchers.anyString()))
.thenReturn(true);
Mockito.when(mockDraftMessageData.getMessageText()).thenReturn(message.getMessageText());
Mockito.when(mockDraftMessageData.prepareMessageForSending(
Matchers.<BindingBase<DraftMessageData>>any()))
.thenReturn(message);
Mockito.when(mockDraftMessageData.hasPendingAttachments()).thenReturn(false);
Mockito.doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
// Synchronously pass the draft check and callback.
((CheckDraftTaskCallback)invocation.getArguments()[2]).onDraftChecked(
mockDraftMessageData, CheckDraftForSendTask.RESULT_PASSED);
return null;
}
}).when(mockDraftMessageData).checkDraftForAction(Mockito.anyBoolean(), Mockito.anyInt(),
Mockito.<CheckDraftTaskCallback>any(),
Mockito.<Binding<DraftMessageData>>any());
view.bind(mockDraftMessageData, mockIComposeMessageViewHost);
final EditText composeEditText = (EditText) view.findViewById(R.id.compose_message_text);
final View sendButton = view.findViewById(R.id.send_message_button);
view.requestDraftMessage(false);
Mockito.verify(mockDraftMessageData).loadFromStorage(any(BindingBase.class),
isNull(), Mockito.eq(false));
view.onDraftChanged(mockDraftMessageData, DraftMessageData.ALL_CHANGED);
assertEquals(message.getMessageText(), composeEditText.getText().toString());
sendButton.performClick();
Mockito.verify(mockIComposeMessageViewHost).sendMessage(
Mockito.argThat(o -> {
assertEquals(message.getMessageText(), o.getMessageText());
return true;
}));
}
public void testNotDefaultSms() {
Mockito.when(mockDraftMessageData.getReadOnlyAttachments())
.thenReturn(Collections.unmodifiableList(new ArrayList<MessagePartData>()));
Mockito.when(mockDraftMessageData.getIsDefaultSmsApp()).thenReturn(false);
Mockito.when(mockIComposeMessageViewHost.isReadyForAction()).thenReturn(false);
final ComposeMessageView view = getView();
final MessageData message = MessageData.createDraftSmsMessage("fake_id", "just_a_self_id",
"Sample Message");
Mockito.when(mockDraftMessageData.isBound(Matchers.anyString()))
.thenReturn(true);
Mockito.when(mockDraftMessageData.getMessageText()).thenReturn(message.getMessageText());
Mockito.when(mockDraftMessageData.prepareMessageForSending(
Matchers.<BindingBase<DraftMessageData>>any()))
.thenReturn(message);
Mockito.when(mockDraftMessageData.hasPendingAttachments()).thenReturn(false);
view.bind(mockDraftMessageData, mockIComposeMessageViewHost);
final EditText composeEditText = (EditText) view.findViewById(R.id.compose_message_text);
final View sendButton = view.findViewById(R.id.send_message_button);
view.requestDraftMessage(false);
Mockito.verify(mockDraftMessageData).loadFromStorage(any(BindingBase.class),
isNull(), Mockito.eq(false));
view.onDraftChanged(mockDraftMessageData, DraftMessageData.ALL_CHANGED);
assertEquals(message.getMessageText(), composeEditText.getText().toString());
sendButton.performClick();
Mockito.verify(mockIComposeMessageViewHost).warnOfMissingActionConditions(
any(Boolean.class), any(Runnable.class));
}
}

View File

@@ -1,121 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui.conversation;
import android.text.TextUtils;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.ui.contact.ContactPickerFragment;
import com.android.messaging.ui.conversation.ConversationActivityUiState.ConversationActivityUiStateHost;
import org.mockito.Mock;
import org.mockito.Mockito;
@SmallTest
public class ConversationActivityUiStateTest extends BugleTestCase {
@Mock protected ConversationActivityUiStateHost mockListener;
/**
* Test the Ui state where we start off with the contact picker to pick the first contact.
*/
public void testPickInitialContact() {
final ConversationActivityUiState uiState = new ConversationActivityUiState(null);
uiState.setHost(mockListener);
assertTrue(uiState.shouldShowContactPickerFragment());
assertFalse(uiState.shouldShowConversationFragment());
assertEquals(ContactPickerFragment.MODE_PICK_INITIAL_CONTACT,
uiState.getDesiredContactPickingMode());
uiState.onGetOrCreateConversation("conversation1");
Mockito.verify(mockListener, Mockito.times(1)).onConversationContactPickerUiStateChanged(
Mockito.eq(ConversationActivityUiState.STATE_CONTACT_PICKER_ONLY_INITIAL_CONTACT),
Mockito.eq(
ConversationActivityUiState.STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW),
Mockito.anyBoolean());
assertTrue(uiState.shouldShowContactPickerFragment());
assertTrue(uiState.shouldShowConversationFragment());
assertTrue(TextUtils.equals("conversation1", uiState.getConversationId()));
assertEquals(ContactPickerFragment.MODE_CHIPS_ONLY,
uiState.getDesiredContactPickingMode());
}
/**
* Test the Ui state where we have both the chips view and the conversation view and we
* start message compose.
*/
public void testHybridUiStateStartCompose() {
final ConversationActivityUiState uiState = new ConversationActivityUiState("conv1");
uiState.testSetUiState(
ConversationActivityUiState.STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW);
uiState.setHost(mockListener);
// Start message compose.
uiState.onStartMessageCompose();
Mockito.verify(mockListener, Mockito.times(1)).onConversationContactPickerUiStateChanged(
Mockito.eq(
ConversationActivityUiState.STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW),
Mockito.eq(ConversationActivityUiState.STATE_CONVERSATION_ONLY),
Mockito.anyBoolean());
assertFalse(uiState.shouldShowContactPickerFragment());
assertTrue(uiState.shouldShowConversationFragment());
}
/**
* Test the Ui state where we have both the chips view and the conversation view and we
* try to add a participant.
*/
public void testHybridUiStateAddParticipant() {
final ConversationActivityUiState uiState = new ConversationActivityUiState("conv1");
uiState.testSetUiState(
ConversationActivityUiState.STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW);
uiState.setHost(mockListener);
uiState.onAddMoreParticipants();
Mockito.verify(mockListener, Mockito.times(1)).onConversationContactPickerUiStateChanged(
Mockito.eq(
ConversationActivityUiState.STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW),
Mockito.eq(
ConversationActivityUiState.STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS),
Mockito.anyBoolean());
assertTrue(uiState.shouldShowContactPickerFragment());
assertFalse(uiState.shouldShowConversationFragment());
assertEquals(ContactPickerFragment.MODE_PICK_MORE_CONTACTS,
uiState.getDesiredContactPickingMode());
}
/**
* Test the Ui state where we are trying to add more participants and commit.
*/
public void testCommitAddParticipant() {
final ConversationActivityUiState uiState = new ConversationActivityUiState(null);
uiState.testSetUiState(
ConversationActivityUiState.STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS);
uiState.setHost(mockListener);
uiState.onGetOrCreateConversation("conversation1");
// After adding more contacts, the terminal state is always conversation only (i.e. we
// don't go back to hybrid mode).
Mockito.verify(mockListener, Mockito.times(1)).onConversationContactPickerUiStateChanged(
Mockito.eq(ConversationActivityUiState.STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS),
Mockito.eq(ConversationActivityUiState.STATE_CONVERSATION_ONLY),
Mockito.anyBoolean());
assertFalse(uiState.shouldShowContactPickerFragment());
assertTrue(uiState.shouldShowConversationFragment());
}
}

View File

@@ -1,163 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui.conversation;
import android.app.Activity;
import android.app.Fragment;
import android.database.Cursor;
import androidx.recyclerview.widget.RecyclerView;
import androidx.test.filters.LargeTest;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.DataModel;
import com.android.messaging.datamodel.MemoryCacheManager;
import com.android.messaging.datamodel.data.ConversationData;
import com.android.messaging.datamodel.data.ConversationData.ConversationDataListener;
import com.android.messaging.datamodel.data.DraftMessageData;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.datamodel.media.MediaResourceManager;
import com.android.messaging.ui.FragmentTestCase;
import com.android.messaging.ui.PlainTextEditText;
import com.android.messaging.ui.TestActivity.FragmentEventListener;
import com.android.messaging.ui.conversation.ConversationFragment.ConversationFragmentHost;
import com.android.messaging.ui.conversationlist.ConversationListFragment;
import com.android.messaging.util.BugleGservices;
import com.android.messaging.util.ImeUtil;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
/**
* Unit tests for {@link ConversationListFragment}.
*/
@LargeTest
public class ConversationFragmentTest extends FragmentTestCase<ConversationFragment> {
@Mock protected DataModel mockDataModel;
@Mock protected ConversationData mockConversationData;
@Mock protected DraftMessageData mockDraftMessageData;
@Mock protected MediaResourceManager mockMediaResourceManager;
@Mock protected BugleGservices mockBugleGservices;
@Mock protected ConversationFragmentHost mockHost;
@Mock protected MemoryCacheManager mockMemoryCacheManager;
private ImeUtil mSpiedImeUtil;
private static final String CONVERSATION_ID = "cid";
public ConversationFragmentTest() {
super(ConversationFragment.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
ImeUtil.clearInstance();
mSpiedImeUtil = Mockito.spy(new ImeUtil());
FakeFactory.register(this.getInstrumentation().getTargetContext())
.withDataModel(mockDataModel)
.withBugleGservices(mockBugleGservices)
.withMemoryCacheManager(mockMemoryCacheManager);
}
/**
* Helper that will do the 'binding' of ConversationFragmentTest with ConversationData and
* leave fragment in 'ready' state.
* @param cursor
*/
private void loadWith(final Cursor cursor) {
Mockito.when(mockDraftMessageData.isBound(Matchers.anyString()))
.thenReturn(true);
Mockito.when(mockConversationData.isBound(Matchers.anyString()))
.thenReturn(true);
Mockito.doReturn(mockDraftMessageData)
.when(mockDataModel)
.createDraftMessageData(Mockito.anyString());
Mockito.doReturn(mockDraftMessageData)
.when(mockDataModel)
.createDraftMessageData(null);
Mockito.when(mockDataModel.createConversationData(
Matchers.any(Activity.class),
Matchers.any(ConversationDataListener.class),
Matchers.anyString()))
.thenReturn(mockConversationData);
// Create fragment synchronously to avoid need for volatile, synchronization etc.
final ConversationFragment fragment = getFragment();
// Binding to model happens when attaching fragment to activity, so hook into test
// activity to do so.
getActivity().setFragmentEventListener(new FragmentEventListener() {
@Override
public void onAttachFragment(final Fragment attachedFragment) {
if (fragment == attachedFragment) {
fragment.setConversationInfo(getActivity(), CONVERSATION_ID, null);
}
}
});
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
fragment.setHost(mockHost);
getActivity().setFragment(fragment);
Mockito.verify(mockDataModel).createConversationData(
getActivity(), fragment, CONVERSATION_ID);
Mockito.verify(mockConversationData).init(fragment.getLoaderManager(),
fragment.mBinding);
}
});
// Wait for initial layout pass to work around crash in recycler view
getInstrumentation().waitForIdleSync();
// Now load the cursor
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
fragment.onConversationMessagesCursorUpdated(mockConversationData, cursor, null,
false);
}
});
getInstrumentation().waitForIdleSync();
}
/**
* Verifies that list view gets correctly populated given a cursor.
*/
public void testLoadListView() {
final Cursor cursor = TestDataFactory.getConversationMessageCursor();
loadWith(cursor);
final RecyclerView listView =
(RecyclerView) getFragment().getView().findViewById(android.R.id.list);
assertEquals("bad cursor", cursor.getCount(), listView.getAdapter().getItemCount());
assertEquals("bad cursor count", cursor.getCount(), listView.getChildCount());
}
public void testClickComposeMessageView() {
final Cursor cursor = TestDataFactory.getConversationMessageCursor();
loadWith(cursor);
final PlainTextEditText composeEditText = (PlainTextEditText) getFragment().getView()
.findViewById(R.id.compose_message_text);
setFocus(composeEditText, false);
Mockito.verify(mockHost, Mockito.never()).onStartComposeMessage();
setFocus(composeEditText, true);
Mockito.verify(mockHost).onStartComposeMessage();
}
}

View File

@@ -1,191 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui.conversation;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.widget.EditText;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.binding.Binding;
import com.android.messaging.datamodel.binding.BindingBase;
import com.android.messaging.datamodel.data.ConversationData;
import com.android.messaging.datamodel.data.DraftMessageData;
import com.android.messaging.datamodel.data.SubscriptionListData;
import com.android.messaging.ui.conversation.ConversationInputManager.ConversationInputHost;
import com.android.messaging.ui.conversation.ConversationInputManager.ConversationInputSink;
import com.android.messaging.ui.mediapicker.MediaPicker;
import com.android.messaging.util.BugleGservices;
import com.android.messaging.util.ImeUtil;
import com.android.messaging.util.ImeUtil.ImeStateHost;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
@SmallTest
public class ConversationInputManagerTest extends BugleTestCase {
@Spy protected ImeUtil spyImeUtil;
@Mock protected BugleGservices mockBugleGservices;
@Mock protected FragmentManager mockFragmentManager;
@Mock protected ConversationInputHost mockConversationInputHost;
@Mock protected ConversationInputSink mockConversationInputSink;
@Mock protected ImeStateHost mockImeStateHost;
@Mock protected ConversationData mockConversationData;
@Mock protected DraftMessageData mockDraftMessageData;
@Mock protected MediaPicker mockMediaPicker;
@Mock protected SubscriptionListData mockSubscriptionListData;
@Mock protected FragmentTransaction mockFragmentTransaction;
@Override
protected void setUp() throws Exception {
super.setUp();
FakeFactory.register(getTestContext())
.withBugleGservices(mockBugleGservices);
spyImeUtil = Mockito.spy(new ImeUtil());
ImeUtil.set(spyImeUtil);
}
private ConversationInputManager initNewInputManager(final Bundle savedState) {
// Set up the mocks.
Mockito.when(mockConversationInputHost.getSimSelectorView())
.thenReturn(new SimSelectorView(getTestContext(), null));
Mockito.when(mockConversationInputHost.createMediaPicker()).thenReturn(mockMediaPicker);
Mockito.when(mockConversationInputSink.getComposeEditText())
.thenReturn(new EditText(getTestContext()));
Mockito.doReturn(mockFragmentTransaction).when(mockFragmentTransaction).replace(
Mockito.eq(R.id.mediapicker_container), Mockito.any(MediaPicker.class),
Mockito.anyString());
Mockito.when(mockFragmentManager.findFragmentByTag(MediaPicker.FRAGMENT_TAG))
.thenReturn(null);
Mockito.when(mockFragmentManager.beginTransaction()).thenReturn(mockFragmentTransaction);
Mockito.when(mockSubscriptionListData.hasData()).thenReturn(true);
Mockito.when(mockConversationData.getSubscriptionListData())
.thenReturn(mockSubscriptionListData);
Mockito.doReturn(true).when(mockConversationData).isBound(Mockito.anyString());
Mockito.doReturn(true).when(mockDraftMessageData).isBound(Mockito.anyString());
final Binding<ConversationData> dataBinding = BindingBase.createBinding(this);
dataBinding.bind(mockConversationData);
final Binding<DraftMessageData> draftBinding = BindingBase.createBinding(this);
draftBinding.bind(mockDraftMessageData);
final ConversationInputManager inputManager = new ConversationInputManager(getTestContext(),
mockConversationInputHost, mockConversationInputSink, mockImeStateHost,
mockFragmentManager, dataBinding, draftBinding, savedState);
return inputManager;
}
public void testShowHideInputs() {
final ConversationInputManager inputManager = initNewInputManager(new Bundle());
Mockito.when(mockMediaPicker.isOpen()).thenReturn(true);
inputManager.showHideMediaPicker(true /* show */, true /* animate */);
Mockito.verify(mockFragmentTransaction).replace(
Mockito.eq(R.id.mediapicker_container), Mockito.any(MediaPicker.class),
Mockito.anyString());
Mockito.verify(mockMediaPicker).open(Mockito.anyInt(), Mockito.eq(true /* animate */));
assertEquals(true, inputManager.isMediaPickerVisible());
assertEquals(false, inputManager.isSimSelectorVisible());
assertEquals(false, inputManager.isImeKeyboardVisible());
Mockito.when(mockMediaPicker.isOpen()).thenReturn(false);
inputManager.showHideMediaPicker(false /* show */, true /* animate */);
Mockito.verify(mockMediaPicker).dismiss(Mockito.eq(true /* animate */));
assertEquals(false, inputManager.isMediaPickerVisible());
assertEquals(false, inputManager.isSimSelectorVisible());
assertEquals(false, inputManager.isImeKeyboardVisible());
}
public void testShowTwoInputsSequentially() {
// First show the media picker, then show the IME keyboard.
final ConversationInputManager inputManager = initNewInputManager(new Bundle());
Mockito.when(mockMediaPicker.isOpen()).thenReturn(true);
inputManager.showHideMediaPicker(true /* show */, true /* animate */);
assertEquals(true, inputManager.isMediaPickerVisible());
assertEquals(false, inputManager.isSimSelectorVisible());
assertEquals(false, inputManager.isImeKeyboardVisible());
Mockito.when(mockMediaPicker.isOpen()).thenReturn(false);
inputManager.showHideImeKeyboard(true /* show */, true /* animate */);
assertEquals(false, inputManager.isMediaPickerVisible());
assertEquals(false, inputManager.isSimSelectorVisible());
assertEquals(true, inputManager.isImeKeyboardVisible());
}
public void testOnKeyboardShow() {
final ConversationInputManager inputManager = initNewInputManager(new Bundle());
Mockito.when(mockMediaPicker.isOpen()).thenReturn(true);
inputManager.showHideMediaPicker(true /* show */, true /* animate */);
assertEquals(true, inputManager.isMediaPickerVisible());
assertEquals(false, inputManager.isSimSelectorVisible());
assertEquals(false, inputManager.isImeKeyboardVisible());
Mockito.when(mockMediaPicker.isOpen()).thenReturn(false);
inputManager.testNotifyImeStateChanged(true /* imeOpen */);
assertEquals(false, inputManager.isMediaPickerVisible());
assertEquals(false, inputManager.isSimSelectorVisible());
assertEquals(true, inputManager.isImeKeyboardVisible());
}
public void testRestoreState() {
final ConversationInputManager inputManager = initNewInputManager(new Bundle());
Mockito.when(mockMediaPicker.isOpen()).thenReturn(true);
inputManager.showHideMediaPicker(true /* show */, true /* animate */);
assertEquals(true, inputManager.isMediaPickerVisible());
assertEquals(false, inputManager.isSimSelectorVisible());
assertEquals(false, inputManager.isImeKeyboardVisible());
Bundle savedInstanceState = new Bundle();
inputManager.onSaveInputState(savedInstanceState);
// Now try to restore the state
final ConversationInputManager restoredInputManager =
initNewInputManager(savedInstanceState);
// Make sure the state is preserved.
assertEquals(true, restoredInputManager.isMediaPickerVisible());
assertEquals(false, restoredInputManager.isSimSelectorVisible());
assertEquals(false, restoredInputManager.isImeKeyboardVisible());
}
public void testBackPress() {
final ConversationInputManager inputManager = initNewInputManager(new Bundle());
Mockito.when(mockMediaPicker.isOpen()).thenReturn(true);
inputManager.showHideMediaPicker(true /* show */, true /* animate */);
assertEquals(true, inputManager.isMediaPickerVisible());
assertEquals(false, inputManager.isSimSelectorVisible());
assertEquals(false, inputManager.isImeKeyboardVisible());
Mockito.when(mockMediaPicker.isOpen()).thenReturn(false);
assertEquals(true, inputManager.onBackPressed());
assertEquals(false, inputManager.isMediaPickerVisible());
assertEquals(false, inputManager.isSimSelectorVisible());
assertEquals(false, inputManager.isImeKeyboardVisible());
}
}

View File

@@ -1,109 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui.conversation;
import android.view.View;
import android.widget.TextView;
import androidx.test.filters.MediumTest;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.FakeCursor;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.ui.ViewTest;
import com.android.messaging.ui.conversation.ConversationMessageView.ConversationMessageViewHost;
import com.android.messaging.util.Dates;
import org.mockito.Mock;
@MediumTest
public class ConversationMessageViewTest extends ViewTest<ConversationMessageView> {
@Mock ConversationMessageViewHost mockHost;
@Override
protected void setUp() throws Exception {
super.setUp();
FakeFactory.register(getInstrumentation().getTargetContext());
}
@Override
protected ConversationMessageView getView() {
final ConversationMessageView view = super.getView();
view.setHost(mockHost);
return view;
}
protected void verifyContent(final ConversationMessageView view, final String messageText,
final boolean showTimestamp, final String timestampText) {
final TextView messageTextView = (TextView) view.findViewById(R.id.message_text);
final TextView statusTextView = (TextView) view.findViewById(R.id.message_status);
assertNotNull(messageTextView);
assertEquals(messageText, messageTextView.getText());
if (showTimestamp) {
assertEquals(View.VISIBLE, statusTextView.getVisibility());
assertEquals(timestampText, statusTextView.getText());
} else {
assertEquals(View.GONE, statusTextView.getVisibility());
}
}
public void testBind() {
final ConversationMessageView view = getView();
final FakeCursor cursor = TestDataFactory.getConversationMessageCursor();
cursor.moveToFirst();
view.bind(cursor);
verifyContent(view, TestDataFactory.getMessageText(cursor, 0), true, Dates
.getMessageTimeString((Long) cursor.getAt("received_timestamp", 0)).toString());
}
public void testBindTwice() {
final ConversationMessageView view = getView();
final FakeCursor cursor = TestDataFactory.getConversationMessageCursor();
cursor.moveToFirst();
view.bind(cursor);
cursor.moveToNext();
view.bind(cursor);
verifyContent(view, TestDataFactory.getMessageText(cursor, 1), true, Dates
.getMessageTimeString((Long) cursor.getAt("received_timestamp", 1)).toString());
}
public void testBindLast() {
final ConversationMessageView view = getView();
final FakeCursor cursor = TestDataFactory.getConversationMessageCursor();
final int lastPos = cursor.getCount() - 1;
cursor.moveToPosition(lastPos);
view.bind(cursor);
verifyContent(view, TestDataFactory.getMessageText(cursor, lastPos), true, Dates
.getMessageTimeString((Long) cursor.getAt("received_timestamp", lastPos))
.toString());
}
@Override
protected int getLayoutIdForView() {
return R.layout.conversation_message_view;
}
}

View File

@@ -1,128 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui.conversationlist;
import android.content.Context;
import android.database.Cursor;
import android.view.View;
import android.widget.ImageView;
import androidx.recyclerview.widget.RecyclerView;
import androidx.test.filters.LargeTest;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.data.ConversationListData;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.ui.FragmentTestCase;
import com.android.messaging.ui.UIIntents;
import com.android.messaging.ui.conversationlist.ConversationListFragment.ConversationListFragmentHost;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
/**
* Unit tests for {@link ConversationListFragment}.
*/
@LargeTest
public class ConversationListFragmentTest
extends FragmentTestCase<ConversationListFragment> {
@Mock protected ConversationListData mMockConversationListData;
@Mock protected ConversationListFragmentHost mMockConversationHostListHost;
@Mock protected UIIntents mMockUIIntents;
protected FakeDataModel mFakeDataModel;
public ConversationListFragmentTest() {
super(ConversationListFragment.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getInstrumentation().getTargetContext();
mFakeDataModel = new FakeDataModel(context)
.withConversationListData(mMockConversationListData);
FakeFactory.register(context)
.withDataModel(mFakeDataModel)
.withUIIntents(mMockUIIntents);
}
/**
* Helper that will do the 'binding' of ConversationListFragmentTest with ConversationListData
* and leave fragment in 'ready' state.
* @param cursor
*/
private void loadWith(final Cursor cursor) {
Mockito.when(mMockConversationListData.isBound(Matchers.anyString()))
.thenReturn(true);
final ConversationListFragment fragment = getFragment();
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
fragment.setHost(mMockConversationHostListHost);
getActivity().setFragment(fragment);
Mockito.verify(mMockConversationListData).init(fragment.getLoaderManager(),
fragment.mListBinding);
fragment.onConversationListCursorUpdated(mMockConversationListData, cursor);
}
});
getInstrumentation().waitForIdleSync();
}
/**
* Verifies that list view gets correctly populated given a cursor.
*/
public void testLoadListView() {
final Cursor cursor = TestDataFactory.getConversationListCursor();
loadWith(cursor);
final RecyclerView listView =
(RecyclerView) getFragment().getView().findViewById(android.R.id.list);
//assertEquals(cursor.getCount(), listView.getCount());
assertEquals(cursor.getCount(), listView.getChildCount());
}
/**
* Verifies that 'empty list' promo is rendered with an empty cursor.
*/
public void testEmptyView() {
loadWith(TestDataFactory.getEmptyConversationListCursor());
final RecyclerView listView =
(RecyclerView) getFragment().getView().findViewById(android.R.id.list);
final View emptyMessageView =
getFragment().getView().findViewById(R.id.no_conversations_view);
assertEquals(View.VISIBLE, emptyMessageView.getVisibility());
assertEquals(0, listView.getChildCount());
}
/**
* Verifies that the button to start a new conversation works.
*/
public void testStartNewConversation() {
final Cursor cursor = TestDataFactory.getConversationListCursor();
loadWith(cursor);
final ImageView startNewConversationButton = (ImageView)
getFragment().getView().findViewById(R.id.start_new_conversation_button);
clickButton(startNewConversationButton);
Mockito.verify(mMockConversationHostListHost).onCreateConversationClick();
}
}

View File

@@ -1,176 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui.conversationlist;
import android.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;
import androidx.test.filters.MediumTest;
import com.android.messaging.Factory;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.FakeCursor;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.data.ConversationListItemData;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.ui.AsyncImageView;
import com.android.messaging.ui.UIIntentsImpl;
import com.android.messaging.ui.ViewTest;
import com.android.messaging.util.Dates;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.Mockito;
@MediumTest
public class ConversationListItemViewTest extends ViewTest<ConversationListItemView> {
@Mock private ConversationListItemView.HostInterface mockHost;
private FakeCursor mCursor;
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getInstrumentation().getTargetContext();
FakeFactory.register(context)
.withDataModel(new FakeDataModel(context))
.withUIIntents(new UIIntentsImpl());
mCursor = TestDataFactory.getConversationListCursor();
}
protected void verifyLaunchedConversationForId(final String id,
final ConversationListItemView conversationView) {
// Must be a short click.
final ArgumentMatcher<ConversationListItemData> itemDataIdMatcher =
arg -> TextUtils.equals(id, arg.getConversationId());
Mockito.verify(mockHost).onConversationClicked(
Mockito.argThat(itemDataIdMatcher), Mockito.eq(false),
Mockito.eq(conversationView));
}
protected void verifyContent(
final ConversationListItemView view, final FakeCursor cursor, final int index) {
/* ConversationQueryColumns.NAME */
final String conversationQueryColumnsName = "name";
final String name = (String) cursor.getAt(conversationQueryColumnsName, index);
/* ConversationQueryColumns.SNIPPET_TEXT */
final String conversationQueryColumnsSnippetText = "snippet_text";
final String snippet = (String) cursor.getAt(conversationQueryColumnsSnippetText, index);
/* ConversationQueryColumns.SORT_TIMESTAMP */
final String conversationQueryColumnsSortTimestamp = "sort_timestamp";
final String timestamp = Dates.getConversationTimeString(
(Long) cursor.getAt(conversationQueryColumnsSortTimestamp, index)).toString();
final boolean unread = !isRead(cursor, index);
verifyContent(view, name, snippet, timestamp, unread);
}
protected void verifyContent(
final ConversationListItemView view,
final String conversationName,
final String snippet,
final String timestamp,
final boolean unread) {
final TextView conversationNameView =
(TextView) view.findViewById(R.id.conversation_name);
final TextView snippetTextView = (TextView) view.findViewById(R.id.conversation_snippet);
final TextView timestampTextView = (TextView) view.findViewById(
R.id.conversation_timestamp);
final AsyncImageView imagePreviewView =
(AsyncImageView) view.findViewById(R.id.conversation_image_preview);
final Context context = Factory.get().getApplicationContext();
assertNotNull(conversationNameView);
assertEquals(conversationName, conversationNameView.getText());
assertNotNull(snippetTextView);
if (unread) {
assertEquals(ConversationListItemView.UNREAD_SNIPPET_LINE_COUNT,
snippetTextView.getMaxLines());
assertEquals(context.getResources().getColor(R.color.conversation_list_item_unread),
snippetTextView.getCurrentTextColor());
assertEquals(context.getResources().getColor(R.color.conversation_list_item_unread),
conversationNameView.getCurrentTextColor());
} else {
assertEquals(ConversationListItemView.NO_UNREAD_SNIPPET_LINE_COUNT,
snippetTextView.getMaxLines());
assertEquals(context.getResources().getColor(R.color.conversation_list_item_read),
snippetTextView.getCurrentTextColor());
assertEquals(context.getResources().getColor(R.color.conversation_list_item_read),
conversationNameView.getCurrentTextColor());
}
assertEquals(View.VISIBLE, imagePreviewView.getVisibility());
assertTrue(snippetTextView.getText().toString().contains(snippet));
assertEquals(timestamp, timestampTextView.getText());
}
protected boolean isRead(final FakeCursor cursor, final int index) {
return 1 == ((Integer) cursor.getAt("read", index)).intValue();
}
public void testBindUnread() {
final ConversationListItemView view = getView();
final int messageIndex = TestDataFactory.CONVERSATION_LIST_CURSOR_UNREAD_MESSAGE_INDEX;
mCursor.moveToPosition(messageIndex);
assertFalse(isRead(mCursor, messageIndex));
view.bind(mCursor, mockHost);
verifyContent(view, mCursor, messageIndex);
}
public void testBindRead() {
final ConversationListItemView view = getView();
final int messageIndex = TestDataFactory.CONVERSATION_LIST_CURSOR_READ_MESSAGE_INDEX;
mCursor.moveToPosition(messageIndex);
assertTrue(isRead(mCursor, messageIndex));
view.bind(mCursor, mockHost);
verifyContent(view, mCursor, messageIndex);
}
public void testClickLaunchesConversation() {
final ConversationListItemView view = getView();
final View swipeableContainer = view.findViewById(R.id.swipeableContainer);
mCursor.moveToFirst();
view.bind(mCursor, mockHost);
swipeableContainer.performClick();
verifyLaunchedConversationForId(
mCursor.getAt("_id" /* ConversationQueryColumns._ID */, 0).toString(), view);
}
public void testBindTwice() {
final ConversationListItemView view = getView();
mCursor.moveToFirst();
view.bind(mCursor, mockHost);
mCursor.moveToNext();
view.bind(mCursor, mockHost);
verifyContent(view, mCursor, mCursor.getPosition());
}
@Override
protected int getLayoutIdForView() {
return R.layout.conversation_list_item_view;
}
}

View File

@@ -1,89 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui.mediapicker;
import android.media.MediaPlayer;
import android.media.MediaRecorder.OnErrorListener;
import android.media.MediaRecorder.OnInfoListener;
import android.net.Uri;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.data.MessagePartData;
import com.android.messaging.ui.ViewTest;
import com.android.messaging.util.FakeMediaUtil;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
public class AudioRecordViewTest extends ViewTest<AudioRecordView> {
@Mock AudioRecordView.HostInterface mockHost;
@Mock LevelTrackingMediaRecorder mockRecorder;
@Mock MediaPlayer mockMediaPlayer;
@Override
protected void setUp() throws Exception {
super.setUp();
FakeFactory.register(getInstrumentation().getContext())
.withMediaUtil(new FakeMediaUtil(mockMediaPlayer));
}
private void verifyAudioSubmitted() {
Mockito.verify(mockHost).onAudioRecorded(Matchers.any(MessagePartData.class));
}
private AudioRecordView initView() {
final AudioRecordView view = getView();
view.testSetMediaRecorder(mockRecorder);
view.setHostInterface(mockHost);
return view;
}
public void testRecording() {
Mockito.when(mockRecorder.isRecording()).thenReturn(false);
Mockito.when(mockRecorder.startRecording(Matchers.<OnErrorListener>any(),
Matchers.<OnInfoListener>any(), Matchers.anyInt())).thenReturn(true);
Mockito.when(mockRecorder.stopRecording()).thenReturn(Uri.parse("content://someaudio/2"));
final AudioRecordView view = initView();
view.onRecordButtonTouchDown();
Mockito.verify(mockRecorder).startRecording(Matchers.<OnErrorListener>any(),
Matchers.<OnInfoListener>any(), Matchers.anyInt());
Mockito.when(mockRecorder.isRecording()).thenReturn(true);
// Record for 1 second to make it meaningful.
sleepNoThrow(1000);
view.onRecordButtonTouchUp();
// We added some buffer to the end of the audio recording, so sleep for sometime and
// verify audio is recorded.
sleepNoThrow(700);
Mockito.verify(mockRecorder).stopRecording();
verifyAudioSubmitted();
}
private void sleepNoThrow(final long duration) {
try {
Thread.sleep(duration);
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
}
}
@Override
protected int getLayoutIdForView() {
return R.layout.mediapicker_audio_chooser;
}
}

View File

@@ -1,161 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui.mediapicker;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.os.AsyncTask;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.ui.mediapicker.CameraManager.CameraWrapper;
import org.mockito.InOrder;
import org.mockito.Mockito;
@SmallTest
public class CameraManagerTest extends BugleTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
// Force each test to set up a camera wrapper to match their needs
CameraManager.setCameraWrapper(null);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
MockCameraFactory.cleanup();
}
public void testNoCameraDeviceGetInfo() {
CameraManager.setCameraWrapper(MockCameraFactory.createCameraWrapper());
assertEquals(false, CameraManager.get().hasAnyCamera());
assertEquals(false, CameraManager.get().hasFrontAndBackCamera());
boolean threw = false;
try {
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_BACK);
} catch (AssertionError e) {
threw = true;
}
if (!threw) {
fail("selectCamera should have thrown");
}
}
public void testFrontFacingOnlyGetInfo() {
CameraManager.setCameraWrapper(MockCameraFactory.createCameraWrapper(
MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_FRONT)
));
assertEquals(true, CameraManager.get().hasAnyCamera());
assertEquals(false, CameraManager.get().hasFrontAndBackCamera());
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_FRONT);
assertEquals(CameraInfo.CAMERA_FACING_FRONT, CameraManager.get().getCameraInfo().facing);
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_BACK);
assertEquals(CameraInfo.CAMERA_FACING_FRONT, CameraManager.get().getCameraInfo().facing);
}
public void testBackFacingOnlyGetInfo() {
CameraManager.setCameraWrapper(MockCameraFactory.createCameraWrapper(
MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_BACK)
));
assertEquals(true, CameraManager.get().hasAnyCamera());
assertEquals(false, CameraManager.get().hasFrontAndBackCamera());
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_FRONT);
assertEquals(CameraInfo.CAMERA_FACING_BACK, CameraManager.get().getCameraInfo().facing);
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_BACK);
assertEquals(CameraInfo.CAMERA_FACING_BACK, CameraManager.get().getCameraInfo().facing);
}
public void testFrontAndBackGetInfo() {
CameraManager.setCameraWrapper(MockCameraFactory.createCameraWrapper(
MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_FRONT),
MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_BACK)
));
assertEquals(true, CameraManager.get().hasAnyCamera());
assertEquals(true, CameraManager.get().hasFrontAndBackCamera());
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_FRONT);
assertEquals(CameraInfo.CAMERA_FACING_FRONT, CameraManager.get().getCameraInfo().facing);
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_BACK);
assertEquals(CameraInfo.CAMERA_FACING_BACK, CameraManager.get().getCameraInfo().facing);
}
public void testSwapCamera() {
CameraManager.setCameraWrapper(MockCameraFactory.createCameraWrapper(
MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_FRONT),
MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_BACK)
));
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_FRONT);
assertEquals(CameraInfo.CAMERA_FACING_FRONT, CameraManager.get().getCameraInfo().facing);
CameraManager.get().swapCamera();
assertEquals(CameraInfo.CAMERA_FACING_BACK, CameraManager.get().getCameraInfo().facing);
}
public void testOpenCamera() {
Camera backCamera = MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_BACK);
Camera frontCamera = MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_FRONT);
CameraWrapper wrapper = MockCameraFactory.createCameraWrapper(frontCamera, backCamera);
CameraManager.setCameraWrapper(wrapper);
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_BACK);
CameraManager.get().openCamera();
CameraManager.get().openCamera();
CameraManager.get().openCamera();
waitForPendingAsyncTasks();
Mockito.verify(wrapper, Mockito.never()).open(0);
Mockito.verify(wrapper).open(1);
Mockito.verify(wrapper, Mockito.never()).release(frontCamera);
Mockito.verify(wrapper, Mockito.never()).release(backCamera);
CameraManager.get().swapCamera();
waitForPendingAsyncTasks();
Mockito.verify(wrapper).open(0);
Mockito.verify(wrapper).open(1);
Mockito.verify(wrapper, Mockito.never()).release(frontCamera);
Mockito.verify(wrapper).release(backCamera);
InOrder inOrder = Mockito.inOrder(wrapper);
inOrder.verify(wrapper).open(1);
inOrder.verify(wrapper).release(backCamera);
inOrder.verify(wrapper).open(0);
}
private void waitForPendingAsyncTasks() {
try {
final Object lockObject = new Object();
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
synchronized (lockObject) {
lockObject.notifyAll();
}
}
}.execute();
synchronized (lockObject) {
lockObject.wait(500);
}
} catch (InterruptedException e) {
fail();
}
}
}

View File

@@ -1,145 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui.mediapicker;
import android.content.Context;
import android.provider.MediaStore.Images.Media;
import android.view.View;
import android.widget.CheckBox;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.FakeCursor;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.data.GalleryGridItemData;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.ui.AsyncImageView;
import com.android.messaging.ui.ViewTest;
import com.android.messaging.util.UriUtil;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
public class GalleryGridItemViewTest extends ViewTest<GalleryGridItemView> {
@Mock GalleryGridItemView.HostInterface mockHost;
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getInstrumentation().getTargetContext();
FakeFactory.register(context)
.withDataModel(new FakeDataModel(context));
}
protected void verifyClickedItem(final View view, final GalleryGridItemData data) {
Mockito.verify(mockHost).onItemClicked(view, data, false /* longClick */);
}
protected void verifyContent(
final GalleryGridItemView view,
final String imageUrl,
final boolean showCheckbox,
final boolean isSelected) {
final AsyncImageView imageView = (AsyncImageView) view.findViewById(R.id.thumbnail);
final CheckBox checkBox = (CheckBox) view.findViewById(R.id.checkbox);
assertNotNull(imageView);
assertTrue(imageView.mImageRequestBinding.isBound());
assertTrue(imageView.mImageRequestBinding.getData().getKey().startsWith(imageUrl));
assertNotNull(checkBox);
if (showCheckbox) {
assertEquals(View.VISIBLE, checkBox.getVisibility());
assertEquals(isSelected, checkBox.isChecked());
} else {
assertNotSame(View.VISIBLE, checkBox.getVisibility());
}
}
public void testBind() {
Mockito.when(mockHost.isMultiSelectEnabled()).thenReturn(false);
Mockito.when(mockHost.isItemSelected(Matchers.<GalleryGridItemData>any()))
.thenReturn(false);
final GalleryGridItemView view = getView();
final FakeCursor cursor = TestDataFactory.getGalleryGridCursor();
cursor.moveToFirst();
final String path = (String) cursor.getAt(Media.DATA, 0);
view.bind(cursor, mockHost);
verifyContent(view, UriUtil.getUriForResourceFile(path).toString(),
false, false);
}
public void testBindMultiSelectUnSelected() {
Mockito.when(mockHost.isMultiSelectEnabled()).thenReturn(true);
Mockito.when(mockHost.isItemSelected(Matchers.<GalleryGridItemData>any()))
.thenReturn(false);
final GalleryGridItemView view = getView();
final FakeCursor cursor = TestDataFactory.getGalleryGridCursor();
cursor.moveToFirst();
final String path = (String) cursor.getAt(Media.DATA, 0);
view.bind(cursor, mockHost);
verifyContent(view, UriUtil.getUriForResourceFile(path).toString(),
true, false);
}
public void testBindMultiSelectSelected() {
Mockito.when(mockHost.isMultiSelectEnabled()).thenReturn(true);
Mockito.when(mockHost.isItemSelected(Matchers.<GalleryGridItemData>any()))
.thenReturn(true);
final GalleryGridItemView view = getView();
final FakeCursor cursor = TestDataFactory.getGalleryGridCursor();
cursor.moveToFirst();
final String path = (String) cursor.getAt(Media.DATA, 0);
view.bind(cursor, mockHost);
verifyContent(view, UriUtil.getUriForResourceFile(path).toString(),
true, true);
}
public void testClick() {
Mockito.when(mockHost.isMultiSelectEnabled()).thenReturn(false);
Mockito.when(mockHost.isItemSelected(Matchers.<GalleryGridItemData>any()))
.thenReturn(false);
final GalleryGridItemView view = getView();
final FakeCursor cursor = TestDataFactory.getGalleryGridCursor();
cursor.moveToFirst();
view.bind(cursor, mockHost);
view.performClick();
verifyClickedItem(view, view.mData);
}
public void testBindTwice() {
Mockito.when(mockHost.isMultiSelectEnabled()).thenReturn(true);
Mockito.when(mockHost.isItemSelected(Matchers.<GalleryGridItemData>any()))
.thenReturn(false);
final GalleryGridItemView view = getView();
final FakeCursor cursor = TestDataFactory.getGalleryGridCursor();
cursor.moveToFirst();
view.bind(cursor, mockHost);
cursor.moveToNext();
final String path = (String) cursor.getAt(Media.DATA, 1);
view.bind(cursor, mockHost);
verifyContent(view, UriUtil.getUriForResourceFile(path).toString(),
true, false);
}
@Override
protected int getLayoutIdForView() {
return R.layout.gallery_grid_item_view;
}
}

View File

@@ -1,129 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui.mediapicker;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.binding.Binding;
import com.android.messaging.datamodel.binding.BindingBase;
import com.android.messaging.datamodel.data.DraftMessageData;
import com.android.messaging.datamodel.data.MediaPickerData;
import com.android.messaging.ui.FragmentTestCase;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
public class MediaPickerTest extends FragmentTestCase<MediaPicker> {
@Mock protected MediaPickerData mMockMediaPickerData;
@Mock protected DraftMessageData mMockDraftMessageData;
protected FakeDataModel mFakeDataModel;
public MediaPickerTest() {
super(MediaPicker.class);
}
@Override
protected MediaPicker getFragment() {
if (mFragment == null) {
mFragment = new MediaPicker(getInstrumentation().getTargetContext());
}
return mFragment;
}
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getInstrumentation().getTargetContext();
mFakeDataModel = new FakeDataModel(context)
.withMediaPickerData(mMockMediaPickerData);
FakeFactory.register(context)
.withDataModel(mFakeDataModel);
}
/**
* Helper method to initialize the MediaPicker and its data.
*/
private void initFragment(final int supportedMediaTypes, final Integer[] expectedLoaderIds,
final boolean filterTabBeforeAttach) {
Mockito.when(mMockMediaPickerData.isBound(Matchers.anyString()))
.thenReturn(true);
Mockito.when(mMockDraftMessageData.isBound(Matchers.anyString()))
.thenReturn(true);
final Binding<DraftMessageData> draftBinding = BindingBase.createBinding(this);
draftBinding.bind(mMockDraftMessageData);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
final MediaPicker fragment = getFragment();
if (filterTabBeforeAttach) {
fragment.setSupportedMediaTypes(supportedMediaTypes);
getActivity().setFragment(fragment);
} else {
getActivity().setFragment(fragment);
fragment.setSupportedMediaTypes(supportedMediaTypes);
}
fragment.setDraftMessageDataModel(draftBinding);
Mockito.verify(mMockMediaPickerData,
Mockito.atLeastOnce()).init(
Matchers.eq(fragment.getLoaderManager()));
fragment.open(MediaPicker.MEDIA_TYPE_ALL, false);
}
});
getInstrumentation().waitForIdleSync();
}
public void testDefaultTabs() {
Mockito.when(mMockMediaPickerData.getSelectedChooserIndex()).thenReturn(0);
initFragment(MediaPicker.MEDIA_TYPE_ALL, new Integer[] {
MediaPickerData.GALLERY_MEDIA_LOADER },
false);
final MediaPicker mediaPicker = getFragment();
final View view = mediaPicker.getView();
assertNotNull(view);
final ViewGroup tabStrip = (ViewGroup) view.findViewById(R.id.mediapicker_tabstrip);
assertEquals(tabStrip.getChildCount(), 4);
for (int i = 0; i < tabStrip.getChildCount(); i++) {
final ImageButton tabButton = (ImageButton) tabStrip.getChildAt(i);
assertEquals(View.VISIBLE, tabButton.getVisibility());
assertEquals(i == 0, tabButton.isSelected());
}
}
public void testFilterTabsBeforeAttach() {
Mockito.when(mMockMediaPickerData.getSelectedChooserIndex()).thenReturn(0);
initFragment(MediaPicker.MEDIA_TYPE_IMAGE, new Integer[] {
MediaPickerData.GALLERY_MEDIA_LOADER },
true);
final MediaPicker mediaPicker = getFragment();
final View view = mediaPicker.getView();
assertNotNull(view);
final ViewGroup tabStrip = (ViewGroup) view.findViewById(R.id.mediapicker_tabstrip);
assertEquals(tabStrip.getChildCount(), 4);
for (int i = 0; i < tabStrip.getChildCount(); i++) {
final ImageButton tabButton = (ImageButton) tabStrip.getChildAt(i);
assertEquals(i == 0, tabButton.isSelected());
}
}
}

View File

@@ -1,73 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.ui.mediapicker;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import com.android.messaging.ui.mediapicker.CameraManager.CameraWrapper;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.util.HashMap;
import java.util.Map;
class MockCameraFactory {
private static Map<Camera, CameraInfo> sCameraInfos = new HashMap<Camera, CameraInfo>();
public static Camera createCamera(int facing) {
Camera camera = Mockito.mock(Camera.class);
CameraInfo cameraInfo = new CameraInfo();
cameraInfo.facing = facing;
sCameraInfos.put(camera, cameraInfo);
return camera;
}
public static void getCameraInfo(Camera camera, CameraInfo outCameraInfo) {
CameraInfo cameraInfo = sCameraInfos.get(camera);
outCameraInfo.facing = cameraInfo.facing;
outCameraInfo.orientation = cameraInfo.orientation;
outCameraInfo.canDisableShutterSound = cameraInfo.canDisableShutterSound;
}
public static CameraWrapper createCameraWrapper(final Camera... cameras) {
CameraWrapper wrapper = Mockito.mock(CameraWrapper.class);
Mockito.when(wrapper.getNumberOfCameras()).thenReturn(cameras.length);
Mockito.when(wrapper.open(Mockito.anyInt())).then(new Answer<Camera>() {
@Override
public Camera answer(InvocationOnMock invocation) {
return cameras[(Integer) invocation.getArguments()[0]];
}
});
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
getCameraInfo(
cameras[(Integer) invocation.getArguments()[0]],
(CameraInfo) invocation.getArguments()[1]
);
return null;
}
}).when(wrapper).getCameraInfo(Mockito.anyInt(), Mockito.any(CameraInfo.class));
return wrapper;
}
public static void cleanup() {
sCameraInfos.clear();
}
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.util;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
@SmallTest
public class BugleGservicesTest extends BugleTestCase {
public void testGServiceGet() {
final BugleGservices bugleGservices = new FakeBugleGservices();
assertEquals(BugleGservicesKeys.SMS_IGNORE_MESSAGE_REGEX_DEFAULT,
bugleGservices.getString(
BugleGservicesKeys.SMS_IGNORE_MESSAGE_REGEX,
BugleGservicesKeys.SMS_IGNORE_MESSAGE_REGEX_DEFAULT));
}
}

View File

@@ -1,307 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.util;
import android.content.ContentProviderOperation;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.text.TextUtils;
import androidx.test.filters.LargeTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.FakeFactory;
import org.junit.Assert;
import java.util.ArrayList;
/*
* Class for testing ContactUtil.
*/
@LargeTest
public class ContactUtilTest extends BugleTestCase {
private static final String TEST_NAME_PREFIX = "BugleTest:";
@Override
protected void setUp() throws Exception {
super.setUp();
// TODO: This test will actually mess with contacts on your phone.
// Ideally we would use a fake content provider to give us contact data...
FakeFactory.registerWithoutFakeContext(getTestContext());
// add test contacts.
addTestContact("John", "650-123-1233", "john@gmail.com", false);
addTestContact("Joe", "(650)123-1233", "joe@gmail.com", false);
addTestContact("Jim", "650 123 1233", "jim@gmail.com", false);
addTestContact("Samantha", "650-123-1235", "samantha@gmail.com", true);
addTestContact("Adrienne", "650-123-1236", "adrienne@gmail.com", true);
}
@Override
protected void tearDown() throws Exception {
deleteTestContacts();
super.tearDown();
}
/**
* Add a test contact based on contact name, phone and email.
*/
private void addTestContact(
final String name, final String phone, final String email, final boolean starred)
throws Exception {
final ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
.build());
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
TEST_NAME_PREFIX + name).build());
if (phone != null) {
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
.build());
}
if (email != null) {
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Email.DATA, email)
.withValue(ContactsContract.CommonDataKinds.Email.TYPE,
ContactsContract.CommonDataKinds.Email.TYPE_WORK)
.build());
}
mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
// Star the whole contact if needed.
if (starred) {
final ContentValues values = new ContentValues();
values.put(Contacts.STARRED, 1);
getContext().getContentResolver().update(Contacts.CONTENT_URI, values,
Contacts.DISPLAY_NAME + "= ?", new String[] { TEST_NAME_PREFIX + name });
}
}
/**
* Remove test contacts added during test setup.
*/
private void deleteTestContacts() {
final Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
Uri.encode(TEST_NAME_PREFIX));
final Cursor cur =
mContext.getContentResolver().query(contactUri, null, null, null, null);
try {
if (cur.moveToFirst()) {
do {
final String lookupKey = cur.getString(cur.getColumnIndex(Contacts.LOOKUP_KEY));
final Uri uri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey);
mContext.getContentResolver().delete(uri, null, null);
} while (cur.moveToNext());
}
} catch (final Exception e) {
LogUtil.e(LogUtil.BUGLE_TAG, "Failed to delete test contacts", e);
}
}
/**
* Verify ContactUtil.getPhone will return all phones, including the ones added for test.
*/
public void ingoredTestGetPhones() {
final Cursor cur = ContactUtil.getPhones(getContext())
.performSynchronousQuery();
LogUtil.i(LogUtil.BUGLE_TAG, "testGetPhones: Number of phones on the device:" +
cur.getCount());
verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Samantha");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Adrienne");
}
/**
* Verify ContactUtil.filterPhone will work on name based matches.
*/
public void ingoredTestFilterPhonesByName() {
final Cursor cur = ContactUtil.filterPhones(getContext(), TEST_NAME_PREFIX)
.performSynchronousQuery();
if (cur.getCount() != 5) {
Assert.fail("Cursor should have size of 5");
return;
}
verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Samantha");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Adrienne");
}
/**
* Verify ContactUtil.filterPhone will work on partial number matches.
*/
public void ingoredTestFilterPhonesByPartialNumber() {
final String[] filters = new String[] { "650123", "650-123", "(650)123", "650 123" };
for (final String filter : filters) {
final Cursor cur = ContactUtil.filterPhones(getContext(), filter)
.performSynchronousQuery();
LogUtil.i(LogUtil.BUGLE_TAG, "testFilterPhonesByPartialNumber: Number of phones:" +
cur.getCount());
verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Samantha");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Adrienne");
}
}
/**
* Verify ContactUtil.filterPhone will work on full number matches.
*/
public void ingoredTestFilterPhonesByFullNumber() {
final String[] filters = new String[] {
"6501231233", "650-123-1233", "(650)123-1233", "650 123 1233" };
for (final String filter : filters) {
final Cursor cur = ContactUtil.filterPhones(getContext(), filter)
.performSynchronousQuery();
LogUtil.i(LogUtil.BUGLE_TAG, "testFilterPhonesByFullNumber: Number of phones:" +
cur.getCount());
verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
}
}
/**
* Verify ContactUtil.lookPhone will work on number including area code.
*/
public void ingoredTestLookupPhoneWithAreaCode() {
final String[] filters = new String[] {
"6501231233", "650-123-1233", "(650)123-1233", "650 123 1233" };
for (final String filter : filters) {
final Cursor cur = ContactUtil.lookupPhone(getContext(), filter)
.performSynchronousQuery();
LogUtil.i(LogUtil.BUGLE_TAG, "testLookupPhoneWithAreaCode: Number of phones:" +
cur.getCount());
verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
}
}
/**
* Verify ContactUtil.lookPhone will work on number without area code.
*/
public void ingoredTestLookupPhoneWithoutAreaCode() {
final String[] filters = new String[] {
"1231233", "123-1233", "123 1233" };
for (final String filter : filters) {
final Cursor cur = ContactUtil.lookupPhone(getContext(), filter)
.performSynchronousQuery();
LogUtil.i(LogUtil.BUGLE_TAG, "testLookupPhoneWithoutAreaCode: Number of phones:" +
cur.getCount());
verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Joe");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Jim");
}
}
public void ingoredTestGetFrequentPhones() {
final Cursor cur = ContactUtil.getFrequentContacts(getContext())
.performSynchronousQuery();
LogUtil.i(LogUtil.BUGLE_TAG, "testGetFrequentPhones: Number of phones on the device:" +
cur.getCount());
verifyCursorContains(cur, TEST_NAME_PREFIX + "Samantha");
verifyCursorContains(cur, TEST_NAME_PREFIX + "Adrienne");
}
/**
* Verify ContactUtil.filterEmails will work on partial email.
*/
public void ingoredTestFilterEmails() {
final Cursor cur = ContactUtil.filterEmails(getContext(), "john@")
.performSynchronousQuery();
LogUtil.i(LogUtil.BUGLE_TAG, "testFilterEmails: Number of emails:" +
cur.getCount());
verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
}
/**
* Verify ContactUtil.lookupEmail will work on full email.
*/
public void ingoredTestLookupEmail() {
final Cursor cur = ContactUtil.lookupEmail(getContext(), "john@gmail.com")
.performSynchronousQuery();
LogUtil.i(LogUtil.BUGLE_TAG, "testLookupEmail: Number of emails:" +
cur.getCount());
verifyCursorContains(cur, TEST_NAME_PREFIX + "John");
}
/**
* Utility method to check whether cursor contains a particular contact.
*/
private void verifyCursorContains(final Cursor cursor, final String nameToVerify) {
if (cursor.moveToFirst()) {
do {
final String name = cursor.getString(ContactUtil.INDEX_DISPLAY_NAME);
if (TextUtils.equals(name, nameToVerify)) {
return;
}
} while (cursor.moveToNext());
}
Assert.fail("Cursor should have " + nameToVerify);
}
}

View File

@@ -1,55 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.util;
/**
* Fake implementation which just returns the default values.
*/
public class FakeBugleGservices extends BugleGservices {
public FakeBugleGservices() {
}
@Override
public void registerForChanges(final Runnable r) {
}
@Override
public long getLong(final String key, final long defaultValue) {
return defaultValue;
}
@Override
public int getInt(final String key, final int defaultValue) {
return defaultValue;
}
@Override
public boolean getBoolean(final String key, final boolean defaultValue) {
return defaultValue;
}
@Override
public String getString(final String key, final String defaultValue) {
return defaultValue;
}
@Override
public float getFloat(String key, float defaultValue) {
return defaultValue;
}
}

View File

@@ -1,84 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.util;
/**
* Fake implementation which just returns the default values and ignores put operations.
*/
public class FakeBuglePrefs extends BuglePrefs {
public FakeBuglePrefs() {
}
@Override
public int getInt(final String key, final int defaultValue) {
return defaultValue;
}
@Override
public long getLong(final String key, final long defaultValue) {
return defaultValue;
}
@Override
public boolean getBoolean(final String key, final boolean defaultValue) {
return defaultValue;
}
@Override
public String getString(final String key, final String defaultValue) {
return defaultValue;
}
@Override
public byte[] getBytes(String key) {
return null;
}
@Override
public void putInt(final String key, final int value) {
}
@Override
public void putLong(final String key, final long value) {
}
@Override
public void putBoolean(final String key, final boolean value) {
}
@Override
public void putString(final String key, final String value) {
}
@Override
public void putBytes(String key, byte[] value) {
}
@Override
public String getSharedPreferencesName() {
return "FakeBuglePrefs";
}
@Override
public void onUpgrade(int oldVersion, int newVersion) {
}
@Override
public void remove(String key) {
}
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.util;
import android.content.Context;
import android.media.MediaPlayer;
public class FakeMediaUtil extends MediaUtil {
private final MediaPlayer mMediaPlayer;
public FakeMediaUtil(final MediaPlayer mediaPlayer) {
mMediaPlayer = mediaPlayer;
}
@Override
public void playSound(Context context, int resId, OnCompletionListener completionListener) {
if (completionListener != null) {
completionListener.onCompletion();
}
}
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.messaging.util;
import androidx.test.filters.SmallTest;
import com.android.messaging.BugleTestCase;
/*
* Class for testing YouTubeUtil.
*/
@SmallTest
public class YouTubeUtilTest extends BugleTestCase {
public void testGetYoutubePreviewImageLink() {
final String videoId = "dQw4w9WgXcQ";
final String videoThumbnailUrl = YouTubeUtil.YOUTUBE_STATIC_THUMBNAIL_PREFIX + videoId
+ YouTubeUtil.YOUTUBE_STATIC_THUMBNAIL_END;
// Check known valid youtube links to videos
assertEquals(
YouTubeUtil.getYoutubePreviewImageLink("http://www.youtube.com/watch?v=" + videoId),
videoThumbnailUrl);
assertEquals(
YouTubeUtil.getYoutubePreviewImageLink("https://www.youtube.com/watch?v=" + videoId
+ "&feature=youtu.be"), videoThumbnailUrl);
assertEquals(
YouTubeUtil.getYoutubePreviewImageLink("www.youtube.com/watch?v=" + videoId),
videoThumbnailUrl);
assertEquals(
YouTubeUtil.getYoutubePreviewImageLink("http://www.youtube.com/embed/" + videoId),
videoThumbnailUrl);
assertEquals(YouTubeUtil.getYoutubePreviewImageLink("http://www.youtube.com/v/" + videoId),
videoThumbnailUrl);
assertEquals(
YouTubeUtil.getYoutubePreviewImageLink("https://youtube.googleapis.com/v/"
+ videoId), videoThumbnailUrl);
assertEquals(
YouTubeUtil.getYoutubePreviewImageLink("http://www.youtube.com/apiplayer?video_id="
+ videoId), videoThumbnailUrl);
// This is the type of links that are used as shares from YouTube and will be the most
// likely case that we see
assertEquals(YouTubeUtil.getYoutubePreviewImageLink("http://youtu.be/" + videoId),
videoThumbnailUrl);
// Try links that shouldn't work
assertNull(YouTubeUtil.getYoutubePreviewImageLink("http://www.youtube.com"));
}
}