• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 
17 package com.android.eventlib;
18 
19 import static com.android.eventlib.truth.EventLogsSubject.assertThat;
20 
21 import static java.time.temporal.ChronoUnit.SECONDS;
22 
23 import android.util.Log;
24 
25 import com.android.bedstead.nene.TestApis;
26 import com.android.bedstead.nene.exceptions.NeneException;
27 import com.android.bedstead.nene.exceptions.PollValueFailedException;
28 
29 import java.io.Serializable;
30 import java.time.Duration;
31 import java.time.Instant;
32 
33 /** Interface to interact with the results of an {@link EventLogsQuery}. */
34 public abstract class EventLogs<E extends Event> implements Serializable {
35 
36     private static final long serialVersionUID = 1;
37 
38     static final Duration DEFAULT_POLL_TIMEOUT = Duration.ofMinutes(5);
39 
40     // We need to set this earlier than construction otherwise we will skip all events that happen
41     // before creating the first query
42     static Instant sEarliestLogTime = Instant.now().minus(30, SECONDS);
43 
44     /**
45      * Returns the {@link EventQuerier} to be used to interact with the
46      * appropriate {@link Event} store.
47      */
getQuerier()48     protected abstract EventQuerier<E> getQuerier();
49 
50     /**
51      * Ensures that future calls to {@link #get()}, {@link #next()}, and {@link #poll()} only return
52      * events which are not already logged before this call to {@link #resetLogs()}.
53      */
resetLogs()54     public static void resetLogs() {
55         // We delay 1 ms before and after to separate the cutoff from logs which are
56         // triggered immediately by the tests - this makes behaviour more predictable
57 
58         try {
59             Thread.sleep(1);
60         } catch (InterruptedException e) {
61             Log.d("EventLogs", "Interrupted when sleeping during resetLogs");
62         }
63 
64         sEarliestLogTime = Instant.now();
65 
66         try {
67             Thread.sleep(1);
68         } catch (InterruptedException e) {
69             Log.d("EventLogs", "Interrupted when sleeping during resetLogs");
70         }
71     }
72 
73     /**
74      * Gets the earliest logged event matching the query which has not be returned by a previous
75      * call to {@link #poll()}, or blocks until a matching event is logged.
76      *
77      * <p>This will timeout after {@code timeout} and return null if no matching event is logged.
78      */
poll(Duration timeout)79     public E poll(Duration timeout) {
80         return getQuerier().poll(sEarliestLogTime, timeout);
81     }
82 
83     /**
84      * Gets the earliest logged event matching the query which has not be returned by a previous
85      * call to {@link #poll()}, or blocks until a matching event is logged.
86      *
87      * <p>This will timeout after {@link #DEFAULT_POLL_TIMEOUT} and return null if no matching
88      * event is logged.
89      */
poll()90     public E poll() {
91         return poll(DEFAULT_POLL_TIMEOUT);
92     }
93 
94     /**
95      * Returns immediately if there is an existing event matching the query which has not been
96      * returned by a previous call to {@link #poll()}, or blocks until a matching event is logged.
97      *
98      * <p>This will timeout after {@code timeout} and throw an {@link AssertionError} if no
99      * matching event is logged.
100      */
waitForEvent(Duration timeout)101     public E waitForEvent(Duration timeout) {
102         try {
103             return assertThat(this).eventOccurredWithin(timeout);
104         } catch (PollValueFailedException e) {
105             if (e.getMessage().contains("No existing activity")) {
106                 String activityName = e.getMessage().split(
107                         "named ", 2)[1].split(". ", 2)[0];
108                 String packageName = e.getMessage().split("package ", 2)[1]
109                         .split(". ", 2)[0];
110 
111                 throw new NeneException("Error finding launched activity " + activityName
112                         + " in test app " + packageName
113                         + " (this could mean it didn't launch or the"
114                         + " package crashed). Relevant logs: " + TestApis.logcat().dump(
115                                 l -> l.contains(activityName) || l.contains(packageName)), e);
116             }
117             throw e;
118         }
119     }
120 
121     /**
122      * Returns immediately if there is an existing event matching the query which has not be
123      * returned by a previous call to {@link #poll()}, or blocks until a matching event is logged.
124      *
125      * <p>This will timeout after {@link #DEFAULT_POLL_TIMEOUT} and throw an {@link AssertionError}
126      * if no matching event is logged.
127      */
waitForEvent()128     public E waitForEvent() {
129         return waitForEvent(DEFAULT_POLL_TIMEOUT);
130     }
131 }
132