1 /*
2  * Copyright (C) 2012 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.cts.verifier.p2p.testcase;
18 
19 import java.util.ArrayList;
20 import java.util.List;
21 
22 import android.util.Log;
23 
24 /**
25  * The utility class for callback function.
26  */
27 public abstract class ListenerTest {
28 
29     private static final String TAG = "ListenerTest";
30 
31     /**
32      * stop flag
33      */
34     protected boolean mStopFlag = false;
35 
36     /**
37      * if true, error occurred.
38      */
39     protected boolean mIsError = false;
40 
41     /**
42      * The expected argument list.
43      */
44     private List<ListenerArgument> mExArgList = null;
45 
46     /**
47      * The received argument list before check() is called.
48      */
49     private List<ListenerArgument> mReceivedArgList = new ArrayList<ListenerArgument>();
50 
51     /**
52      * The reason of failure.
53      */
54     private String mReason;
55 
56     /**
57      * Check the callback with the expected argument is invoked successfully within
58      * the specified timeout.
59      *
60      * @param arg the expected callback argument.
61      * @param msec timeout.
62      * @return if true, the appropriate callback is invoked successfully.
63      * @throws InterruptedException
64      */
check(ListenerArgument arg, long msec)65     public boolean check(ListenerArgument arg, long msec) throws InterruptedException {
66         ArrayList<ListenerArgument> argList = new ArrayList<ListenerArgument>();
67         argList.add(arg);
68         return check(argList, msec);
69     }
70 
71     /**
72      * Check the callbacks with the expected argument are all invoked successfully
73      * within the specified timeout.
74      *
75      * @param argList the expected callback argument list.
76      * @param msec timeout.
77      * @return if true, the all appropriate callbacks are invoked successfully.
78      * @throws InterruptedException
79      */
check(List<ListenerArgument> argList, long msec)80     public synchronized boolean check(List<ListenerArgument> argList, long msec)
81         throws InterruptedException {
82 
83         StringBuilder sb = new StringBuilder();
84         createResultString(sb, "Expected", argList);
85 
86         try {
87             mStopFlag = false;
88             mExArgList = new ArrayList<ListenerArgument>(argList);
89             if (mReceivedArgList.size() > 0) {
90                 for (ListenerArgument arg: mReceivedArgList) {
91                     if (!mExArgList.remove(arg)) {
92                         // the invalid callback is invoked before.
93                         Log.d(TAG, " received an invalid response. " + arg);
94                         return false;
95                     }
96                 }
97                 if (mExArgList.isEmpty()) {
98                     return true;
99                 }
100             }
101 
102             waitCallback(msec);
103 
104             if (mIsError) {
105                 return false;
106             }
107             if (!mExArgList.isEmpty()) {
108                 Log.d(TAG, "could not received the expected response. " + mExArgList);
109                 return false;
110             }
111         } finally {
112             createResultString(sb, "Received", mReceivedArgList);
113             mReason = sb.toString();
114             mReceivedArgList.clear();
115             mExArgList = null;
116         }
117 
118         return true;
119     }
120 
121     /**
122      * Get the reason of the failure.
123      * @return
124      */
getReason()125     public synchronized String getReason() {
126         return mReason;
127     }
128 
129     /**
130      * This function must be called from sub class on the callback invocation.
131      * @param arg
132      */
receiveCallback(ListenerArgument arg)133     protected synchronized void receiveCallback(ListenerArgument arg) {
134         mReceivedArgList.add(arg);
135         if (mExArgList == null) {
136             return;
137         }
138 
139         if (!mExArgList.remove(arg)) {
140             Log.d(TAG, "received invalid response. " + arg);
141             mIsError = true;
142             wakeup();
143             return;
144         }
145         if (mExArgList.isEmpty()) {
146             wakeup();
147         }
148     }
149 
150     /**
151      * Wake up main thread.
152      */
wakeup()153     private synchronized void wakeup() {
154         mStopFlag = true;
155         notifyAll();
156     }
157 
158     /**
159      * Wait for the result.
160      * @param msec
161      */
waitCallback(long msec)162     private synchronized void waitCallback(long msec) throws InterruptedException {
163         Timeout t = new Timeout(msec);
164         while (!t.isTimeout()) {
165             if (mStopFlag) {
166                 return;
167             }
168             wait(t.getRemainTime());
169         }
170     }
171 
createResultString(StringBuilder sb, String tag, List<ListenerArgument> args)172     private void createResultString(StringBuilder sb, String tag,
173             List<ListenerArgument> args) {
174         sb.append(tag);
175         sb.append(": ");
176         if (args.size() == 0) {
177             sb.append("None\n");
178         }
179         boolean isInitialTry = true;
180         for (ListenerArgument arg: args) {
181             if (!isInitialTry) {
182                 sb.append(",\n");
183             }
184             isInitialTry = false;
185             sb.append("\"");
186             sb.append(arg);
187             sb.append("\"");
188         }
189         sb.append("\n\n");
190     }
191 
192     static abstract class ListenerArgument {
193     }
194 }
195