1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.dialer.filterednumber;
18
19import android.content.ContentUris;
20import android.content.ContentValues;
21import android.provider.BlockedNumberContract;
22import android.provider.BlockedNumberContract.BlockedNumbers;
23import android.test.AndroidTestCase;
24import android.test.mock.MockContentResolver;
25
26import com.android.contacts.common.compat.CompatUtils;
27import com.android.contacts.common.test.mocks.MockContentProvider;
28import com.android.dialer.compat.FilteredNumberCompat;
29import com.android.dialer.database.FilteredNumberContract;
30import com.android.dialer.database.FilteredNumberContract.FilteredNumber;
31import com.android.dialer.database.FilteredNumberContract.FilteredNumberColumns;
32
33import org.mockito.Mock;
34import org.mockito.MockitoAnnotations;
35
36import java.util.concurrent.CountDownLatch;
37import java.util.concurrent.TimeUnit;
38
39public class BlockedNumbersMigratorTest extends AndroidTestCase {
40
41    private static final String NUMBER = "6502530000";
42    private static final String NUMBER1 = "6502530001";
43    private static final String NUMBER2 = "6502530002";
44
45    @Mock private BlockedNumbersMigrator.Listener mListener;
46    private final MockContentResolver mContentResolver = new MockContentResolver();
47    private final MockContentProvider mContentProvider = new MockContentProvider();
48    private BlockedNumbersMigrator mMigrator;
49
50    @Override
51    public void setUp() throws Exception {
52        super.setUp();
53        MockitoAnnotations.initMocks(this);
54        FilteredNumberCompat.setIsEnabledForTest(true);
55        mContentResolver.addProvider(FilteredNumberContract.AUTHORITY, mContentProvider);
56        mContentResolver.addProvider(BlockedNumberContract.AUTHORITY, mContentProvider);
57        mMigrator = new BlockedNumbersMigrator(mContentResolver);
58    }
59
60    public void testConstructor_NullContentResolver() {
61        try {
62            new BlockedNumbersMigrator(null);
63            fail();
64        } catch (NullPointerException e) {}
65    }
66
67    public void testMigrate_M() {
68        if (CompatUtils.isNCompatible()) {
69            return;
70        }
71        assertFalse(mMigrator.migrate(mListener));
72    }
73
74    public void testMigrate_N_Disabled() {
75        if (!CompatUtils.isNCompatible()) {
76            return;
77        }
78        FilteredNumberCompat.setIsEnabledForTest(false);
79        assertFalse(mMigrator.migrate(mListener));
80    }
81
82    public void testMigrate_N_NullListener() {
83        if (!CompatUtils.isNCompatible()) {
84            return;
85        }
86        try {
87            mMigrator.migrate(null);
88            fail();
89        } catch (NullPointerException e) {}
90    }
91
92    public void testMigrate_N() throws InterruptedException {
93        if (!CompatUtils.isNCompatible()) {
94            return;
95        }
96        mContentProvider.expectQuery(FilteredNumber.CONTENT_URI)
97                .withProjection(FilteredNumberColumns.NUMBER).returnRow(NUMBER).returnRow(NUMBER1)
98                .returnRow(NUMBER2);
99
100        setUpNewBlockedNumberExpectations(mContentProvider, NUMBER, 0);
101        setUpNewBlockedNumberExpectations(mContentProvider, NUMBER1, 1);
102        setUpNewBlockedNumberExpectations(mContentProvider, NUMBER2, 2);
103
104        MigrationListener listener = new MigrationListener();
105        assertTrue(mMigrator.migrate(listener));
106        listener.waitForCallback();
107        assertTrue(FilteredNumberCompat.hasMigratedToNewBlocking());
108        mContentProvider.verify();
109    }
110
111    public void testMigrate_N_AlreadyBlocked() throws InterruptedException {
112        if (!CompatUtils.isNCompatible()) {
113            return;
114        }
115        mContentProvider.expectQuery(FilteredNumber.CONTENT_URI)
116                .withProjection(FilteredNumberColumns.NUMBER).returnRow(NUMBER);
117        mContentProvider.expectQuery(BlockedNumbers.CONTENT_URI)
118                .withProjection(BlockedNumbers.COLUMN_ID)
119                .withSelection(BlockedNumbers.COLUMN_ORIGINAL_NUMBER + " = ?", NUMBER).returnRow(0);
120        // No expectation for insert into BlockedNumbers.CONTENT_URI because it's already there
121
122        MigrationListener listener = new MigrationListener();
123        assertTrue(mMigrator.migrate(listener));
124        listener.waitForCallback();
125        assertTrue(FilteredNumberCompat.hasMigratedToNewBlocking());
126        mContentProvider.verify();
127    }
128
129    private void setUpNewBlockedNumberExpectations(MockContentProvider contentProvider,
130            String number, int returnId) {
131        contentProvider.expectQuery(BlockedNumbers.CONTENT_URI)
132                .withProjection(BlockedNumbers.COLUMN_ID)
133                .withSelection(BlockedNumbers.COLUMN_ORIGINAL_NUMBER + " = ?", number).returnEmptyCursor();
134        contentProvider.expectInsert(BlockedNumbers.CONTENT_URI,
135                createBlockedNumberInsertValues(number),
136                ContentUris.withAppendedId(BlockedNumbers.CONTENT_URI, returnId));
137    }
138
139    private ContentValues createBlockedNumberInsertValues(String number) {
140        ContentValues values = new ContentValues();
141        values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, number);
142        return values;
143    }
144
145    private static class MigrationListener implements BlockedNumbersMigrator.Listener {
146
147        private final CountDownLatch mOnCompleteCalled = new CountDownLatch(1);
148
149        @Override
150        public void onComplete() {
151            mOnCompleteCalled.countDown();
152        }
153
154        public void waitForCallback() throws InterruptedException {
155            if (!mOnCompleteCalled.await(5000, TimeUnit.MILLISECONDS)) {
156                throw new IllegalStateException("Waiting on callback timed out.");
157            }
158        }
159    }
160}
161