1816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko/* 2816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Copyright (C) 2015 The Android Open Source Project 3816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 4816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License"); 5816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * you may not use this file except in compliance with the License. 6816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * You may obtain a copy of the License at 7816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 8816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * http://www.apache.org/licenses/LICENSE-2.0 9816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 10816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Unless required by applicable law or agreed to in writing, software 11816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS, 12816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * See the License for the specific language governing permissions and 14816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * limitations under the License. 15816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 16816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 17816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkopackage com.android.tv.recommendation; 18816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 196ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport static org.junit.Assert.assertTrue; 206ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 2165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.test.filters.SmallTest; 2207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko 236ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport org.junit.Test; 246ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 25816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.HashMap; 26816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.List; 27816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.Map; 28816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.concurrent.TimeUnit; 29816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 30816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko/** 31816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Unit tests for {@link RecentChannelEvaluator}. 32816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 3307b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko@SmallTest 34816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkopublic class RecentChannelEvaluatorTest extends EvaluatorTestCase<RecentChannelEvaluator> { 35816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int DEFAULT_NUMBER_OF_CHANNELS = 4; 36816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final long DEFAULT_WATCH_START_TIME_MS = 37816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko System.currentTimeMillis() - TimeUnit.DAYS.toMillis(2); 38816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final long DEFAULT_WATCH_END_TIME_MS = 39816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1); 40816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final long DEFAULT_MAX_WATCH_DURATION_MS = TimeUnit.HOURS.toMillis(1); 41816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 4207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko @Override 43816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public RecentChannelEvaluator createEvaluator() { 44816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return new RecentChannelEvaluator(); 45816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 46816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 476ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Test 48816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void testOneChannelWithNoWatchLog() { 49816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko long channelId = addChannel().getId(); 50816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko notifyChannelAndWatchLogLoaded(); 51816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 526ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko assertEqualScores(Recommender.Evaluator.NOT_RECOMMENDED, 53816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mEvaluator.evaluateChannel(channelId)); 54816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 55816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 566ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Test 57816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void testOneChannelWithRandomWatchLogs() { 58816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko addChannel(); 59816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko addRandomWatchLogs(DEFAULT_WATCH_START_TIME_MS, DEFAULT_WATCH_END_TIME_MS, 60816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko DEFAULT_MAX_WATCH_DURATION_MS); 61816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko notifyChannelAndWatchLogLoaded(); 62816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 63816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko assertChannelScoresValid(); 64816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 65816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 666ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Test 67816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void testMultiChannelsWithNoWatchLog() { 68816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko addChannels(DEFAULT_NUMBER_OF_CHANNELS); 69816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko notifyChannelAndWatchLogLoaded(); 70816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 71816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko List<Long> channelIdList = getChannelIdListSorted(); 72816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko for (long channelId : channelIdList) { 736ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko assertEqualScores(Recommender.Evaluator.NOT_RECOMMENDED, 74816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mEvaluator.evaluateChannel(channelId)); 75816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 76816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 77816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 786ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Test 79816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void testMultiChannelsWithRandomWatchLogs() { 80816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko addChannels(DEFAULT_NUMBER_OF_CHANNELS); 81816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko addRandomWatchLogs(DEFAULT_WATCH_START_TIME_MS, DEFAULT_WATCH_END_TIME_MS, 82816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko DEFAULT_MAX_WATCH_DURATION_MS); 83816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko notifyChannelAndWatchLogLoaded(); 84816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 85816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko assertChannelScoresValid(); 86816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 87816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 886ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Test 89816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void testMultiChannelsWithSimpleWatchLogs() { 90816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko addChannels(DEFAULT_NUMBER_OF_CHANNELS); 91816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // Every channel has one watch log with 1 hour. Also, for two channels 92816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // which has ID x and y (x < y), the channel y is watched later than the channel x. 93816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko long latestWatchEndTimeMs = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(2); 94816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko List<Long> channelIdList = getChannelIdListSorted(); 95816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko for (long channelId : channelIdList) { 96816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko addWatchLog(channelId, latestWatchEndTimeMs, TimeUnit.HOURS.toMillis(1)); 97816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko latestWatchEndTimeMs += TimeUnit.HOURS.toMillis(1); 98816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 99816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko notifyChannelAndWatchLogLoaded(); 100816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 101816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko assertChannelScoresValid(); 102816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // Channel score must be increased as channel ID increased. 103816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko double previousScore = Recommender.Evaluator.NOT_RECOMMENDED; 104816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko for (long channelId : channelIdList) { 105816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko double score = mEvaluator.evaluateChannel(channelId); 106816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko assertTrue(previousScore <= score); 107816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko previousScore = score; 108816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 109816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 110816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1116ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Test 112816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void testScoreIncreasesWithNewWatchLog() { 113816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko addChannels(DEFAULT_NUMBER_OF_CHANNELS); 114816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko addRandomWatchLogs(DEFAULT_WATCH_START_TIME_MS, DEFAULT_WATCH_END_TIME_MS, 115816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko DEFAULT_MAX_WATCH_DURATION_MS); 116816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko notifyChannelAndWatchLogLoaded(); 117816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 118816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko List<Long> channelIdList = getChannelIdListSorted(); 119816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko long latestWatchEndTimeMs = getLatestWatchEndTimeMs(); 120816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko for (long channelId : channelIdList) { 121816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko double previousScore = mEvaluator.evaluateChannel(channelId); 122816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 123816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko long durationMs = TimeUnit.MINUTES.toMillis(10); 124816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko addWatchLog(channelId, latestWatchEndTimeMs, durationMs); 125816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko latestWatchEndTimeMs += durationMs; 126816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 127816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // Score must be increased because recentness of the log increases. 128816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko assertTrue(previousScore <= mEvaluator.evaluateChannel(channelId)); 129816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 130816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 131816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1326ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Test 133816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void testScoreDecreasesWithIncrementOfWatchedLogUpdatedTime() { 134816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko addChannels(DEFAULT_NUMBER_OF_CHANNELS); 135816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko addRandomWatchLogs(DEFAULT_WATCH_START_TIME_MS, DEFAULT_WATCH_END_TIME_MS, 136816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko DEFAULT_MAX_WATCH_DURATION_MS); 137816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko notifyChannelAndWatchLogLoaded(); 138816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 139816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Map<Long, Double> scores = new HashMap<>(); 140816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko List<Long> channelIdList = getChannelIdListSorted(); 141816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko long latestWatchedEndTimeMs = getLatestWatchEndTimeMs(); 142816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 143816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko for (long channelId : channelIdList) { 144816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko scores.put(channelId, mEvaluator.evaluateChannel(channelId)); 145816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 146816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 147816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko long newChannelId = addChannel().getId(); 148816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko addWatchLog(newChannelId, latestWatchedEndTimeMs, TimeUnit.MINUTES.toMillis(10)); 149816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 150816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko for (long channelId : channelIdList) { 151816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // Score must be decreased because LastWatchLogUpdateTime increases by new log. 152816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko assertTrue(mEvaluator.evaluateChannel(channelId) <= scores.get(channelId)); 153816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 154816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 155816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko} 156