/* * Copyright (C) 2014 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.providers.tv; import com.google.android.collect.Sets; import android.content.ContentUris; import android.content.ContentValues; import android.content.Intent; import android.content.pm.ProviderInfo; import android.database.Cursor; import android.media.tv.TvContract; import android.media.tv.TvContract.Channels; import android.media.tv.TvContract.Programs; import android.media.tv.TvContract.WatchedPrograms; import android.net.Uri; import android.os.Bundle; import android.os.SystemClock; import android.provider.Settings; import android.test.suitebuilder.annotation.Suppress; import android.test.mock.MockContentProvider; import android.test.mock.MockContentResolver; import android.test.ServiceTestCase; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Objects; import java.util.Set; public class EpgDataCleanupServiceTests extends ServiceTestCase { private static final String FAKE_INPUT_ID = "EpgDataCleanupServiceTests"; private MockContentResolver mResolver; private TvProviderForTesting mProvider; public EpgDataCleanupServiceTests() { super(EpgDataCleanupService.class); } @Override protected void setUp() throws Exception { super.setUp(); mResolver = new MockContentResolver(); // DateUtils tries to access Settings provider to get date format string. mResolver.addProvider(Settings.AUTHORITY, new MockContentProvider() { @Override public Bundle call(String method, String request, Bundle args) { return new Bundle(); } }); mProvider = new TvProviderForTesting(); mResolver.addProvider(TvContract.AUTHORITY, mProvider); setContext(new MockTvProviderContext(mResolver, getSystemContext())); final ProviderInfo info = new ProviderInfo(); info.authority = TvContract.AUTHORITY; mProvider.attachInfoForTesting(getContext(), info); Utils.clearTvProvider(mResolver); startService(new Intent(getContext(), EpgDataCleanupService.class)); } @Override protected void tearDown() throws Exception { Utils.clearTvProvider(mResolver); mProvider.shutdown(); super.tearDown(); } private static class Program { long id; final long startTime; final long endTime; Program(long startTime, long endTime) { this(-1, startTime, endTime); } Program(long id, long startTime, long endTime) { this.id = id; this.startTime = startTime; this.endTime = endTime; } @Override public boolean equals(Object obj) { if (!(obj instanceof Program)) { return false; } Program that = (Program) obj; return Objects.equals(id, that.id) && Objects.equals(startTime, that.startTime) && Objects.equals(endTime, that.endTime); } @Override public int hashCode() { return Objects.hash(id, startTime, endTime); } @Override public String toString() { return "Program(id=" + id + ",start=" + startTime + ",end=" + endTime + ")"; } } private long insertChannel() { ContentValues values = new ContentValues(); values.put(Channels.COLUMN_INPUT_ID, FAKE_INPUT_ID); Uri uri = mResolver.insert(Channels.CONTENT_URI, values); assertNotNull(uri); return ContentUris.parseId(uri); } private void insertPrograms(Program... programs) { insertPrograms(Arrays.asList(programs)); } private void insertPrograms(Collection programs) { long channelId = insertChannel(); ContentValues values = new ContentValues(); values.put(Programs.COLUMN_CHANNEL_ID, channelId); for (Program program : programs) { values.put(Programs.COLUMN_START_TIME_UTC_MILLIS, program.startTime); values.put(Programs.COLUMN_END_TIME_UTC_MILLIS, program.endTime); Uri uri = mResolver.insert(Programs.CONTENT_URI, values); assertNotNull(uri); program.id = ContentUris.parseId(uri); } } private Set queryPrograms() { String[] projection = new String[] { Programs._ID, Programs.COLUMN_START_TIME_UTC_MILLIS, Programs.COLUMN_END_TIME_UTC_MILLIS, }; Cursor cursor = mResolver.query(Programs.CONTENT_URI, projection, null, null, null); assertNotNull(cursor); try { Set programs = Sets.newHashSet(); while (cursor.moveToNext()) { programs.add(new Program(cursor.getLong(0), cursor.getLong(1), cursor.getLong(2))); } return programs; } finally { cursor.close(); } } private void insertWatchedPrograms(Program... programs) { insertWatchedPrograms(Arrays.asList(programs)); } private void insertWatchedPrograms(Collection programs) { long channelId = insertChannel(); ContentValues values = new ContentValues(); values.put(WatchedPrograms.COLUMN_PACKAGE_NAME, getContext().getPackageName()); values.put(WatchedPrograms.COLUMN_CHANNEL_ID, channelId); for (Program program : programs) { values.put(WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, program.startTime); values.put(WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, program.endTime); Uri uri = mProvider.insertWatchedProgramSync(values); assertNotNull(uri); program.id = ContentUris.parseId(uri); } } private Set queryWatchedPrograms() { String[] projection = new String[] { WatchedPrograms._ID, WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, }; Cursor cursor = mResolver.query(WatchedPrograms.CONTENT_URI, projection, null, null, null); assertNotNull(cursor); try { Set programs = Sets.newHashSet(); while (cursor.moveToNext()) { programs.add(new Program(cursor.getLong(0), cursor.getLong(1), cursor.getLong(2))); } return programs; } finally { cursor.close(); } } @Override public void testServiceTestCaseSetUpProperly() throws Exception { assertNotNull(getService()); } public void testClearOldPrograms() { Program program = new Program(1, 2); insertPrograms(program); getService().clearOldPrograms(2); assertEquals("Program should NOT be deleted if it ended at given time.", Sets.newHashSet(program), queryPrograms()); getService().clearOldPrograms(3); assertTrue("Program should be deleted if it ended before given time.", queryPrograms().isEmpty()); ArrayList programs = new ArrayList(); for (int i = 0; i < 10; i++) { programs.add(new Program(999 + i, 1000 + i)); } insertPrograms(programs); getService().clearOldPrograms(1005); assertEquals("Program should be deleted if and only if it ended before given time.", new HashSet(programs.subList(5, 10)), queryPrograms()); } // Disable temporarily since it's not trivial to fix due to asynchronous implementation of // watch history management. public void testClearOldWatchedPrograms() { Program program = new Program(1, 2); insertWatchedPrograms(program); getService().clearOldWatchHistory(1); assertEquals("Watch history should NOT be deleted if watch started at given time.", Sets.newHashSet(program), queryWatchedPrograms()); getService().clearOldWatchHistory(2); assertTrue("Watch history shuold be deleted if watch started before given time.", queryWatchedPrograms().isEmpty()); ArrayList programs = new ArrayList(); for (int i = 0; i < 10; i++) { programs.add(new Program(1000 + i, 1001 + i)); } insertWatchedPrograms(programs); getService().clearOldWatchHistory(1005); assertEquals("Watch history should be deleted if and only if it started before given time.", new HashSet(programs.subList(5, 10)), queryWatchedPrograms()); } // Disable temporarily since it's not trivial to fix due to asynchronous implementation of // watch history management. public void testClearOverflowWatchHistory() { ArrayList programs = new ArrayList(); for (int i = 0; i < 10; i++) { programs.add(new Program(1000 + i, 1001 + i)); } insertWatchedPrograms(programs); getService().clearOverflowWatchHistory(5); assertEquals("Watch history should be deleted in watch start time order.", new HashSet(programs.subList(5, 10)), queryWatchedPrograms()); getService().clearOverflowWatchHistory(0); assertTrue("All history should be deleted.", queryWatchedPrograms().isEmpty()); } }