1/*
2 * Copyright (C) 2015 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.tv.recommendation;
18
19import android.test.suitebuilder.annotation.SmallTest;
20
21import java.util.List;
22import java.util.concurrent.TimeUnit;
23
24/**
25 * Unit tests for {@link FavoriteChannelEvaluator}.
26 */
27@SmallTest
28public class FavoriteChannelEvaluatorTest extends EvaluatorTestCase<FavoriteChannelEvaluator> {
29    private static final int DEFAULT_NUMBER_OF_CHANNELS = 4;
30    private static final long DEFAULT_WATCH_START_TIME_MS =
31            System.currentTimeMillis() - TimeUnit.DAYS.toMillis(2);
32    private static final long DEFAULT_WATCH_END_TIME_MS =
33            System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1);
34    private static final long DEFAULT_MAX_WATCH_DURATION_MS = TimeUnit.HOURS.toMillis(1);
35
36    @Override
37    public FavoriteChannelEvaluator createEvaluator() {
38        return new FavoriteChannelEvaluator();
39    }
40
41    public void testOneChannelWithNoWatchLog() {
42        long channelId = addChannel().getId();
43        notifyChannelAndWatchLogLoaded();
44
45        assertEquals(Recommender.Evaluator.NOT_RECOMMENDED,
46                mEvaluator.evaluateChannel(channelId));
47    }
48
49    public void testOneChannelWithRandomWatchLogs() {
50        addChannel();
51        addRandomWatchLogs(DEFAULT_WATCH_START_TIME_MS, DEFAULT_WATCH_END_TIME_MS,
52                DEFAULT_MAX_WATCH_DURATION_MS);
53        notifyChannelAndWatchLogLoaded();
54
55        assertChannelScoresValid();
56    }
57
58    public void testMultiChannelsWithNoWatchLog() {
59        addChannels(DEFAULT_NUMBER_OF_CHANNELS);
60        notifyChannelAndWatchLogLoaded();
61
62        List<Long> channelIdList = getChannelIdListSorted();
63        for (long channelId : channelIdList) {
64            assertEquals(Recommender.Evaluator.NOT_RECOMMENDED,
65                    mEvaluator.evaluateChannel(channelId));
66        }
67    }
68
69    public void testMultiChannelsWithRandomWatchLogs() {
70        addChannels(DEFAULT_NUMBER_OF_CHANNELS);
71        addRandomWatchLogs(DEFAULT_WATCH_START_TIME_MS, DEFAULT_WATCH_END_TIME_MS,
72                DEFAULT_MAX_WATCH_DURATION_MS);
73        notifyChannelAndWatchLogLoaded();
74
75        assertChannelScoresValid();
76    }
77
78    public void testMultiChannelsWithSimpleWatchLogs() {
79        addChannels(DEFAULT_NUMBER_OF_CHANNELS);
80        // For two channels which has ID x and y (x < y), the channel y is more watched
81        // than the channel x. (Duration is longer than channel x)
82        long latestWatchEndTimeMs = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(2);
83        long durationMs = 0;
84        List<Long> channelIdList = getChannelIdListSorted();
85        for (long channelId : channelIdList) {
86            durationMs += TimeUnit.MINUTES.toMillis(30);
87            addWatchLog(channelId, latestWatchEndTimeMs, durationMs);
88            latestWatchEndTimeMs += durationMs;
89        }
90        notifyChannelAndWatchLogLoaded();
91
92        assertChannelScoresValid();
93        // Channel score must be increased as channel ID increased.
94        double previousScore = Recommender.Evaluator.NOT_RECOMMENDED;
95        for (long channelId : channelIdList) {
96            double score = mEvaluator.evaluateChannel(channelId);
97            assertTrue(previousScore <= score);
98            previousScore = score;
99        }
100    }
101
102    public void testTwoChannelsWithSameWatchDuration() {
103        long channelOne = addChannel().getId();
104        long channelTwo = addChannel().getId();
105        addWatchLog(channelOne, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1),
106                TimeUnit.MINUTES.toMillis(30));
107        addWatchLog(channelTwo, System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(30),
108                TimeUnit.MINUTES.toMillis(30));
109        notifyChannelAndWatchLogLoaded();
110
111        assertTrue(mEvaluator.evaluateChannel(channelOne) ==
112                mEvaluator.evaluateChannel(channelTwo));
113    }
114
115    public void testTwoChannelsWithDifferentWatchDuration() {
116        long channelOne = addChannel().getId();
117        long channelTwo = addChannel().getId();
118        addWatchLog(channelOne, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(3),
119                TimeUnit.MINUTES.toMillis(30));
120        addWatchLog(channelTwo, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(2),
121                TimeUnit.HOURS.toMillis(1));
122        notifyChannelAndWatchLogLoaded();
123
124        // Channel two was watched longer than channel one, so it's score is bigger.
125        assertTrue(mEvaluator.evaluateChannel(channelOne) < mEvaluator.evaluateChannel(channelTwo));
126
127        addWatchLog(channelOne, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1),
128                TimeUnit.HOURS.toMillis(1));
129
130        // Now, channel one was watched longer than channel two, so it's score is bigger.
131        assertTrue(mEvaluator.evaluateChannel(channelOne) > mEvaluator.evaluateChannel(channelTwo));
132    }
133
134    public void testScoreIncreasesWithNewWatchLog() {
135        long channelId = addChannel().getId();
136        addRandomWatchLogs(DEFAULT_WATCH_START_TIME_MS, DEFAULT_WATCH_END_TIME_MS,
137                DEFAULT_MAX_WATCH_DURATION_MS);
138        notifyChannelAndWatchLogLoaded();
139
140        long latestWatchEndTimeMs = getLatestWatchEndTimeMs();
141        double previousScore = mEvaluator.evaluateChannel(channelId);
142
143        addWatchLog(channelId, latestWatchEndTimeMs, TimeUnit.MINUTES.toMillis(10));
144
145        // Score must be increased because total watch duration of the channel increases.
146        assertTrue(previousScore <= mEvaluator.evaluateChannel(channelId));
147    }
148}
149