View Javadoc
1   package com.atlassian.streams.refapp;
2   
3   
4   import com.atlassian.sal.api.ApplicationProperties;
5   import com.atlassian.streams.api.ActivityRequest;
6   import com.atlassian.streams.api.ActivityVerb;
7   import com.atlassian.streams.api.StreamsEntry;
8   import com.atlassian.streams.api.StreamsFilterType;
9   import com.atlassian.streams.api.common.Pair;
10  import com.atlassian.streams.refapp.api.StreamsEntryRequest;
11  import com.atlassian.streams.spi.StreamsI18nResolver;
12  import com.google.common.base.Function;
13  import com.google.common.base.Predicate;
14  import com.google.common.collect.ImmutableList;
15  import com.google.common.collect.ImmutableMultimap;
16  import com.google.common.collect.Iterables;
17  import com.google.common.collect.Multimap;
18  import org.joda.time.DateTime;
19  import org.junit.Before;
20  import org.junit.Test;
21  import org.junit.runner.RunWith;
22  import org.mockito.Mock;
23  import org.mockito.runners.MockitoJUnitRunner;
24  
25  import javax.annotation.Nullable;
26  import java.util.Arrays;
27  
28  import static com.atlassian.streams.api.ActivityObjectTypes.article;
29  import static com.atlassian.streams.api.ActivityVerbs.like;
30  import static com.atlassian.streams.api.ActivityVerbs.post;
31  import static com.atlassian.streams.api.StreamsFilterType.Operator.AFTER;
32  import static com.atlassian.streams.api.StreamsFilterType.Operator.BEFORE;
33  import static com.atlassian.streams.api.StreamsFilterType.Operator.BETWEEN;
34  import static com.atlassian.streams.api.StreamsFilterType.Operator.IS;
35  import static com.atlassian.streams.api.StreamsFilterType.Operator.NOT;
36  import static com.atlassian.streams.api.common.Pair.pair;
37  import static com.atlassian.streams.refapp.RefappStreamsActivityManager.BUFFER_SIZE;
38  import static com.atlassian.streams.spi.StandardStreamsFilterOption.ACTIVITY_KEY;
39  import static com.atlassian.streams.spi.StandardStreamsFilterOption.UPDATE_DATE;
40  import static com.atlassian.streams.spi.StandardStreamsFilterOption.USER;
41  import static com.google.common.collect.Iterables.size;
42  import static org.hamcrest.MatcherAssert.assertThat;
43  import static org.hamcrest.Matchers.is;
44  import static org.hamcrest.Matchers.notNullValue;
45  import static org.hamcrest.Matchers.nullValue;
46  import static org.mockito.Mockito.mock;
47  import static org.mockito.Mockito.when;
48  
49  @RunWith(MockitoJUnitRunner.class)
50  public class RefappStreamsActivityManagerTest {
51      private static final ImmutableMultimap<String, Pair<StreamsFilterType.Operator, Iterable<String>>> EMPTY_FILTER = ImmutableMultimap.<String, Pair<StreamsFilterType.Operator, Iterable<String>>>builder().build();
52      private RefappStreamsActivityManager refappStreamsActivityManager;
53  
54      @Mock
55      private ApplicationProperties applicationProperties;
56      @Mock
57      private StreamsI18nResolver i18nResolver;
58      @Mock
59      private RefappRenderer refappRenderer;
60  
61      private DateTime today;
62  
63      @Before
64      public void setup() {
65          refappStreamsActivityManager = new RefappStreamsActivityManager(applicationProperties, i18nResolver, refappRenderer);
66          today = new DateTime();
67          // Fill the buffer:
68          // Prepare N (0...N-1) entries that date are today, today + 1days, ..... today + N - 1, where N is the buffer size.
69          // With first 5 entries are post, the rest are like activities.
70          for (int i = 0; i < BUFFER_SIZE; i++) {
71              final ActivityVerb verb = i < 5 ? post() : like();
72              refappStreamsActivityManager.addEntry(new StreamsEntryRequest()
73                      .id(i)
74                      .title("Title " + i)
75                      .postedDate(today.plusDays(i))
76                      .type(article())
77                      .verb(verb)
78                      .user("User" + i));
79          }
80  
81      }
82  
83      @Test
84      public void getEntriesTestNoFilter() {
85          // Restrict small result.
86          getEntriesNoFilterAndAssert(5, 5);
87  
88          // With maximum result.
89          getEntriesNoFilterAndAssert(BUFFER_SIZE, BUFFER_SIZE);
90      }
91  
92      @Test
93      public void getEntriesTestFilterDateDefore() {
94          // Filter entries BEFORE(today + 2 days) => expect return 2 entries (today, today + 1)
95          Pair<StreamsFilterType.Operator, Iterable<String>> dateFilter = pairDateFilter(BEFORE, today.plusDays(2));
96          Iterable<StreamsEntry> entries = getStreamsEntriesWithDateFilter(dateFilter);
97  
98          assertThat(size(entries), is(2));
99          // Assert the two entry is today (id = 0) and today + 1 (id=1)
100         assertThat(find(entries, 0), notNullValue());
101         assertThat(find(entries, 1), notNullValue());
102     }
103 
104     @Test
105     public void getEntriesTestFilterDateAfter() {
106         // Filter entries AFTER(today + 2 days) => expect return BUFFER_SIZE - 3 entries (today + 3, today + 4 ... today + BUFFER - 1)
107         Pair<StreamsFilterType.Operator, Iterable<String>> dateFilter = pairDateFilter(AFTER, today.plusDays(2));
108         Iterable<StreamsEntry> entries = getStreamsEntriesWithDateFilter(dateFilter);
109 
110         assertThat(size(entries), is(BUFFER_SIZE - 3));
111         // Assert the two entry is today (id = 0) and today + 1 (id=1)
112         assertThat(find(entries, 2), nullValue());
113         assertThat(find(entries, 3), notNullValue());
114         assertThat(find(entries, BUFFER_SIZE - 1), notNullValue());
115     }
116 
117     private Pair<StreamsFilterType.Operator, Iterable<String>> pairDateFilter(final StreamsFilterType.Operator operator, final DateTime... dates) {
118         Iterable<String> dateStrings = Iterables.<DateTime, String>transform(Arrays.asList(dates), new Function<DateTime, String>() {
119             @Override
120             public String apply(@Nullable final DateTime input) {
121                 return String.valueOf(input.toDate().getTime());
122             }
123         });
124         return Pair.<StreamsFilterType.Operator, Iterable<String>>pair(operator, dateStrings);
125     }
126 
127     @Test
128     public void getEntriesTestFilterDateBetween() {
129         // Filter entries AFTER(today + 2 days, today + 5) => expect return 2 entries (today + 3, today + 4 )
130         Pair<StreamsFilterType.Operator, Iterable<String>> dateFilter = pairDateFilter(BETWEEN, today.plusDays(2), today.plusDays(5));
131         Iterable<StreamsEntry> entries = getStreamsEntriesWithDateFilter(dateFilter);
132 
133         assertThat(size(entries), is(2));
134         assertThat(find(entries, 3), notNullValue());
135         assertThat(find(entries, 4), notNullValue());
136     }
137 
138     @Test
139     public void getEntriesTestFilterUserIs() {
140         Iterable<String> users = ImmutableList.of("User6");
141         Pair<StreamsFilterType.Operator, Iterable<String>> dateFilter = pair(IS, users);
142         Iterable<StreamsEntry> entries = getStreamsEntriesWithUserFilter(dateFilter);
143 
144         assertThat(size(entries), is(1));
145         assertThat(find(entries, 6), notNullValue());
146     }
147 
148     @Test
149     public void getEntriesTestFilterUserIsNot() {
150         Iterable<String> users = ImmutableList.of("User6");
151         Pair<StreamsFilterType.Operator, Iterable<String>> dateFilter = pair(NOT, users);
152         Iterable<StreamsEntry> entries = getStreamsEntriesWithUserFilter(dateFilter);
153 
154         assertThat(size(entries), is(BUFFER_SIZE - 1));
155         assertThat(find(entries, 6), nullValue());
156     }
157 
158     @Test
159     public void getEntriesTestFilterActivity() {
160         // Filter with type article post => assert 5 is found.
161         Iterable<StreamsEntry> entries = getStreamsEntriesWithActivityFilter("article:post");
162         assertThat(size(entries), is(5));
163 
164         // And the rest are article like activities.
165         entries = getStreamsEntriesWithActivityFilter("article:like");
166         assertThat(size(entries), is(BUFFER_SIZE - 5));
167     }
168 
169     @Test
170     public void addEntryTest() {
171         // Add a new entry, while the buffer is already full.
172         StreamsEntryRequest entryRequest = new StreamsEntryRequest()
173                 .id(BUFFER_SIZE)
174                 .postedDate(new DateTime().plusDays(BUFFER_SIZE))
175                 .title("Title" + BUFFER_SIZE)
176                 .user("User" + BUFFER_SIZE)
177                 .type(article())
178                 .verb(post());
179         refappStreamsActivityManager.addEntry(entryRequest);
180 
181         // The oldest entry should be removed from buffer.
182         assertThat(refappStreamsActivityManager.getEntry(0), nullValue());
183 
184         // The new entry should be found from the buffer.
185         StreamsEntry entry = refappStreamsActivityManager.getEntry(entryRequest.getId());
186         assertThat(entry, notNullValue());
187         assertThat(entry.getPostedDate(), is(entryRequest.getPostedDate()));
188         assertThat(entry.getVerb(), is(entryRequest.getVerb()));
189         assertThat(entry.getActivityObjects().iterator().next().getActivityObjectType().get(), is(entryRequest.getType()));
190         assertThat(entry.getAuthors().iterator().next().getUsername(), is(entryRequest.getUser()));
191     }
192 
193     @Test
194     public void removeEntryTest() {
195         removeEntryAndAssert(5);
196 
197         getEntriesNoFilterAndAssert(BUFFER_SIZE, BUFFER_SIZE - 1);
198 
199         removeEntryAndAssert(6);
200 
201         getEntriesNoFilterAndAssert(BUFFER_SIZE, BUFFER_SIZE - 2);
202     }
203 
204     private void removeEntryAndAssert(final int removedId) {
205         assertThat(refappStreamsActivityManager.getEntry(removedId), notNullValue());
206         assertThat(refappStreamsActivityManager.removeEntry(removedId), is(true));
207         assertThat(refappStreamsActivityManager.getEntry(removedId), nullValue());
208         assertThat(refappStreamsActivityManager.removeEntry(removedId), is(false));
209     }
210 
211     private Iterable<StreamsEntry> getStreamsEntriesWithUserFilter(final Pair<StreamsFilterType.Operator, Iterable<String>> dateFilter) {
212         ImmutableMultimap<String, Pair<StreamsFilterType.Operator, Iterable<String>>> standardFilters = ImmutableMultimap.<String, Pair<StreamsFilterType.Operator, Iterable<String>>>builder()
213                 .put(USER.getKey(), dateFilter).build();
214 
215         ActivityRequest request = mockActivityRequest(BUFFER_SIZE, standardFilters, EMPTY_FILTER);
216 
217         return refappStreamsActivityManager.getEntries(request);
218     }
219 
220     private Iterable<StreamsEntry> getStreamsEntriesWithDateFilter(final Pair<StreamsFilterType.Operator, Iterable<String>> dateFilter) {
221         ImmutableMultimap<String, Pair<StreamsFilterType.Operator, Iterable<String>>> standardFilters = ImmutableMultimap.<String, Pair<StreamsFilterType.Operator, Iterable<String>>>builder()
222                 .put(UPDATE_DATE.getKey(), dateFilter).build();
223 
224         ActivityRequest request = mockActivityRequest(BUFFER_SIZE, standardFilters, EMPTY_FILTER);
225 
226         return refappStreamsActivityManager.getEntries(request);
227     }
228 
229     public StreamsEntry find(Iterable<StreamsEntry> entries, final int id) {
230         return (StreamsEntry) Iterables.find(entries, new Predicate<StreamsEntry>() {
231             @Override
232             public boolean apply(@Nullable final StreamsEntry input) {
233                 return input.getId().equals(refappStreamsActivityManager.buildUriId(id));
234             }
235         }, null);
236     }
237 
238     private ActivityRequest mockActivityRequest(final int maxResult,
239                                                 final Multimap<String, Pair<StreamsFilterType.Operator, Iterable<String>>> standardFilters,
240                                                 final Multimap<String, Pair<StreamsFilterType.Operator, Iterable<String>>> providerFilters) {
241         ActivityRequest request = mock(ActivityRequest.class);
242         when(request.getMaxResults()).thenReturn(maxResult);
243 
244         when(request.getStandardFilters()).thenReturn(standardFilters);
245         when(request.getProviderFilters()).thenReturn(providerFilters);
246         return request;
247     }
248 
249     private void getEntriesNoFilterAndAssert(final int maxResult, final int expectedResult) {
250         // Empty filter.
251         ActivityRequest request = mockActivityRequest(maxResult, EMPTY_FILTER, EMPTY_FILTER);
252 
253         Iterable<StreamsEntry> entries = refappStreamsActivityManager.getEntries(request);
254         assertThat(size(entries), is(expectedResult));
255     }
256 
257 
258     private Iterable<StreamsEntry> getStreamsEntriesWithActivityFilter(final String activity) {
259         Iterable<String> activities = ImmutableList.of(activity);
260         Pair<StreamsFilterType.Operator, Iterable<String>> activityFilter = pair(IS, activities);
261         ImmutableMultimap<String, Pair<StreamsFilterType.Operator, Iterable<String>>> providerFilter = ImmutableMultimap.<String, Pair<StreamsFilterType.Operator, Iterable<String>>>builder()
262                 .put(ACTIVITY_KEY, activityFilter).build();
263 
264         ActivityRequest request = mockActivityRequest(BUFFER_SIZE, EMPTY_FILTER, providerFilter);
265 
266         return refappStreamsActivityManager.getEntries(request);
267     }
268 
269 }