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.nn.crashtest.app;
18 
19 import android.annotation.SuppressLint;
20 import android.util.Log;
21 
22 import com.android.nn.crashtest.core.CrashTestCoordinator;
23 
24 import java.util.Optional;
25 import java.util.concurrent.CountDownLatch;
26 import java.util.concurrent.TimeUnit;
27 import java.util.concurrent.atomic.AtomicReference;
28 import java.util.function.Consumer;
29 
30 class CrashTestStatus implements CrashTestCoordinator.CrashTestCompletionListener {
31     public static enum TestResult {
32         SUCCESS,
33         FAILURE,
34         CRASH,
35         HANG
36     }
37 
38     private final String TAG = "CrashTestStatus";
39 
40     private final Consumer<String> mDisplayMessages;
41 
42     // Not using AtomicBoolean to have the concept of unset status
43     private final AtomicReference<TestResult>
44             mTestResult = new AtomicReference<>(null);
45     private final CountDownLatch mParallelTestComplete = new CountDownLatch(1);
46 
CrashTestStatus(Consumer<String> displayMessages)47     CrashTestStatus(Consumer<String> displayMessages) {
48         mDisplayMessages = displayMessages;
49     }
50 
51     @SuppressLint("DefaultLocale")
handleCompletionNotification(TestResult testResult, String reason)52     private void handleCompletionNotification(TestResult testResult,
53             String reason) {
54         Log.d(TAG,
55                 String.format("Received crash test notification: %s and extra msg %s.\n",
56                         testResult,
57                         reason));
58         if (mTestResult.compareAndSet(null, testResult)) {
59             if (reason != null) {
60                 mDisplayMessages.accept(
61                         String.format("Test completed with result %s and msg: %s.\n", testResult,
62                                 reason));
63             } else {
64                 mDisplayMessages.accept(String.format("Test completed with result %s\n", testResult));
65             }
66             mParallelTestComplete.countDown();
67             mDisplayMessages.accept(
68                     String.format("mParallelTestComplete count is now %d, test result is %s\n",
69                             mParallelTestComplete.getCount(), mTestResult.get()));
70         } else {
71             Log.d(TAG, "Ignored, another completion notification was sent before");
72         }
73     }
74 
75     @Override
testCrashed()76     public void testCrashed() {
77         handleCompletionNotification(TestResult.CRASH, null);
78     }
79 
80     @Override
testSucceeded()81     public void testSucceeded() {
82         handleCompletionNotification(TestResult.SUCCESS, null);
83     }
84 
85     @Override
testFailed(String reason)86     public void testFailed(String reason) {
87         handleCompletionNotification(TestResult.FAILURE, reason);
88     }
89 
90     @Override
testProgressing(Optional<String> description)91     public void testProgressing(Optional<String> description) {
92         mDisplayMessages.accept(".");
93     }
94 
isTestCompleted()95     public boolean isTestCompleted() {
96         return mParallelTestComplete.getCount() == 0;
97     }
98 
waitForCompletion(long timeout, TimeUnit timeUnit)99     public boolean waitForCompletion(long timeout, TimeUnit timeUnit) throws InterruptedException {
100         return mParallelTestComplete.await(timeout, timeUnit);
101     }
102 
compareAndSetResult(TestResult expect, TestResult update)103     public boolean compareAndSetResult(TestResult expect, TestResult update) {
104         return mTestResult.compareAndSet(expect, update);
105     }
106 
result()107     public TestResult result() {
108         return mTestResult.get();
109     }
110 }
111