add more data integrity tests for NotificationListenerService.

cleanup: remove start state
cleanup: more test-like: bundle setup and test together

Bug: 8555705
Change-Id: I00361efd70c11b2fb2ad44c823b1cdeb6ed2205f
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nls/MockListener.java b/apps/CtsVerifier/src/com/android/cts/verifier/nls/MockListener.java
index 62a09c9..8549214 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nls/MockListener.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nls/MockListener.java
@@ -16,7 +16,6 @@
 package com.android.cts.verifier.nls;
 
 import android.app.Activity;
-import android.app.Notification;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -26,6 +25,9 @@
 import android.service.notification.StatusBarNotification;
 import android.util.Log;
 
+import org.json.JSONException;
+import org.json.JSONObject;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -47,6 +49,13 @@
     static final int RESULT_TIMEOUT = Activity.RESULT_FIRST_USER;
     static final int RESULT_NO_SERVER = Activity.RESULT_FIRST_USER + 1;
 
+    static final String JSON_FLAGS = "flag";
+    static final String JSON_ICON = "icon";
+    static final String JSON_ID = "id";
+    static final String JSON_PACKAGE = "pkg";
+    static final String JSON_WHEN = "when";
+    static final String JSON_TAG = "tag";
+
     private ArrayList<String> mPosted = new ArrayList<String>();
     private ArrayList<String> mPayloads = new ArrayList<String>();
     private ArrayList<String> mRemoved = new ArrayList<String>();
@@ -126,20 +135,24 @@
         mPosted.clear();
         mPayloads.clear();
         mRemoved.clear();
-        Log.d(TAG, "reset");
     }
 
     @Override
     public void onNotificationPosted(StatusBarNotification sbn) {
         Log.d(TAG, "posted: " + sbn.getTag());
         mPosted.add(sbn.getTag());
-        StringBuilder payload = new StringBuilder();
-        payload.append(sbn.getTag());
-        payload.append(":");
-        payload.append(sbn.getId());
-        payload.append(":");
-        payload.append(sbn.getPackageName());
-        mPayloads.add(payload.toString());
+        JSONObject payload = new JSONObject();
+        try {
+            payload.put(JSON_TAG, sbn.getTag());
+            payload.put(JSON_ID, sbn.getId());
+            payload.put(JSON_PACKAGE, sbn.getPackageName());
+            payload.put(JSON_WHEN, sbn.getNotification().when);
+            payload.put(JSON_ICON, sbn.getNotification().icon);
+            payload.put(JSON_FLAGS, sbn.getNotification().flags);
+            mPayloads.add(payload.toString());
+        } catch (JSONException e) {
+            Log.e(TAG, "failed to pack up notification payload", e);
+        }
     }
 
     @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nls/NotificationListenerVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nls/NotificationListenerVerifierActivity.java
index 7c64eb6..0f6eaad 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nls/NotificationListenerVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nls/NotificationListenerVerifierActivity.java
@@ -16,6 +16,13 @@
 
 package com.android.cts.verifier.nls;
 
+import static com.android.cts.verifier.nls.MockListener.JSON_FLAGS;
+import static com.android.cts.verifier.nls.MockListener.JSON_ICON;
+import static com.android.cts.verifier.nls.MockListener.JSON_ID;
+import static com.android.cts.verifier.nls.MockListener.JSON_PACKAGE;
+import static com.android.cts.verifier.nls.MockListener.JSON_TAG;
+import static com.android.cts.verifier.nls.MockListener.JSON_WHEN;
+
 import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.app.Notification;
@@ -29,6 +36,7 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.provider.Settings.Secure;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -39,7 +47,12 @@
 import com.android.cts.verifier.R;
 import com.android.cts.verifier.nfc.TagVerifierActivity;
 
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.LinkedBlockingQueue;
 
@@ -49,13 +62,17 @@
     private static final String STATE = "state";
     private static final String LISTENER_PATH = "com.android.cts.verifier/" + 
             "com.android.cts.verifier.nls.MockListener";
+    private static final int SETUP = 0;
     private static final int PASS = 1;
     private static final int FAIL = 2;
     private static final int WAIT_FOR_USER = 3;
+    private static final int CLEARED = 4;
+    private static final int READY = 5;
+    private static final int RETRY = 6;
     private static final int NOTIFICATION_ID = 1001;
     private static LinkedBlockingQueue<String> sDeletedQueue = new LinkedBlockingQueue<String>();
 
-    private int mState = -1;
+    private int mState;
     private int[] mStatus;
     private LayoutInflater mInflater;
     private ViewGroup mItemList;
@@ -67,8 +84,19 @@
     private Context mContext;
     private Runnable mRunner;
     private View mHandler;
-    private String mIdString;
     private String mPackageString;
+    private int mIcon1;
+    private int mIcon2;
+    private int mIcon3;
+    private int mId1;
+    private int mId2;
+    private int mId3;
+    private long mWhen1;
+    private long mWhen2;
+    private long mWhen3;
+    private int mFlag1;
+    private int mFlag2;
+    private int mFlag3;
 
     public static class DismissService extends Service {
         @Override
@@ -87,7 +115,7 @@
         super.onCreate(savedInstanceState);
 
         if (savedInstanceState != null) {
-            mState = savedInstanceState.getInt(STATE, -1);
+            mState = savedInstanceState.getInt(STATE, 0);
         }
         mContext = this;
         mRunner = this;
@@ -115,7 +143,7 @@
     @Override
     protected void onResume() {
         super.onResume();
-        mHandler.post(mRunner);
+        next();
     }
 
     // Interface Utilities
@@ -133,15 +161,20 @@
     }
 
     private void setItemState(int index, boolean passed) {
-        if (index != -1) {
-            ViewGroup item = (ViewGroup) mItemList.getChildAt(index);
-            ImageView status = (ImageView) item.findViewById(R.id.nls_status);
-            status.setImageResource(passed ? R.drawable.fs_good : R.drawable.fs_error);
-            View button = item.findViewById(R.id.nls_launch_settings);
-            button.setClickable(false);
-            button.setEnabled(false);
-            status.invalidate();
-        }
+        ViewGroup item = (ViewGroup) mItemList.getChildAt(index);
+        ImageView status = (ImageView) item.findViewById(R.id.nls_status);
+        status.setImageResource(passed ? R.drawable.fs_good : R.drawable.fs_error);
+        View button = item.findViewById(R.id.nls_launch_settings);
+        button.setClickable(false);
+        button.setEnabled(false);
+        status.invalidate();
+    }
+
+    private void markItemWaiting(int index) {
+        ViewGroup item = (ViewGroup) mItemList.getChildAt(index);
+        ImageView status = (ImageView) item.findViewById(R.id.nls_status);
+        status.setImageResource(R.drawable.fs_warning);
+        status.invalidate();
     }
 
     private View createUserItem(int stringId) {
@@ -165,7 +198,7 @@
     // Test management
 
     public void run() {
-        while (mState >= 0 && mState < mStatus.length && mStatus[mState] != WAIT_FOR_USER) {
+        while (mState < mStatus.length && mStatus[mState] != WAIT_FOR_USER) {
             if (mStatus[mState] == PASS) {
                 setItemState(mState, true);
                 mState++;
@@ -177,11 +210,11 @@
             }
         }
 
+        if (mState < mStatus.length && mStatus[mState] == WAIT_FOR_USER) {
+            markItemWaiting(mState);
+        }
+
         switch (mState) {
-            case -1:
-                mState++;
-                mHandler.post(mRunner);
-                break;
             case 0:
                 testIsEnabled(0);
                 break;
@@ -211,6 +244,7 @@
                 break;
             case 9:
                 getPassButton().setEnabled(true);
+                mNm.cancelAll();
                 break;
         }
     }
@@ -236,41 +270,109 @@
 
         mNm.cancelAll();
 
+        mWhen1 = System.currentTimeMillis() + 1;
+        mWhen2 = System.currentTimeMillis() + 2;
+        mWhen3 = System.currentTimeMillis() + 3;
+
+        mIcon1 = R.drawable.fs_good;
+        mIcon2 = R.drawable.fs_error;
+        mIcon3 = R.drawable.fs_warning;
+
+        mId1 = NOTIFICATION_ID + 1;
+        mId2 = NOTIFICATION_ID + 2;
+        mId3 = NOTIFICATION_ID + 3;
+
+        mPackageString = "com.android.cts.verifier";
+
         Notification n1 = new Notification.Builder(mContext)
         .setContentTitle("ClearTest 1")
         .setContentText(mTag1.toString())
         .setPriority(Notification.PRIORITY_LOW)
-        .setSmallIcon(R.drawable.fs_good)
+        .setSmallIcon(mIcon1)
+        .setWhen(mWhen1)
         .setDeleteIntent(makeIntent(1, mTag1))
+        .setOnlyAlertOnce(true)
         .build();
-        mNm.notify(mTag1, NOTIFICATION_ID + 1, n1);
-        mIdString = Integer.toString(NOTIFICATION_ID + 1);
-        mPackageString = "com.android.cts.verifier";
+        mNm.notify(mTag1, mId1, n1);
+        mFlag1 = Notification.FLAG_ONLY_ALERT_ONCE;
 
         Notification n2 = new Notification.Builder(mContext)
         .setContentTitle("ClearTest 2")
         .setContentText(mTag2.toString())
-        .setPriority(Notification.PRIORITY_LOW)
-        .setSmallIcon(R.drawable.fs_good)
+        .setPriority(Notification.PRIORITY_HIGH)
+        .setSmallIcon(mIcon2)
+        .setWhen(mWhen2)
         .setDeleteIntent(makeIntent(2, mTag2))
+        .setAutoCancel(true)
         .build();
-        mNm.notify(mTag2, NOTIFICATION_ID + 2, n2);
+        mNm.notify(mTag2, mId2, n2);
+        mFlag2 = Notification.FLAG_AUTO_CANCEL;
 
         Notification n3 = new Notification.Builder(mContext)
         .setContentTitle("ClearTest 3")
         .setContentText(mTag3.toString())
         .setPriority(Notification.PRIORITY_LOW)
-        .setSmallIcon(R.drawable.fs_good)
+        .setSmallIcon(mIcon3)
+        .setWhen(mWhen3)
         .setDeleteIntent(makeIntent(3, mTag3))
+        .setAutoCancel(true)
+        .setOnlyAlertOnce(true)
         .build();
-        mNm.notify(mTag3, NOTIFICATION_ID + 3, n3);
+        mNm.notify(mTag3, mId3, n3);
+        mFlag3 = Notification.FLAG_ONLY_ALERT_ONCE | Notification.FLAG_AUTO_CANCEL;
+    }
+
+    /**
+     * Return to the state machine to progress through the tests.
+     */
+    private void next() {
+        mHandler.post(mRunner);
+    }
+
+    /**
+     * Wait for things to settle before returning to the state machine.
+     */
+    private void delay() {
+        mHandler.postDelayed(mRunner, 2000);
+    }
+
+    boolean checkEquals(long expected, long actual, String message) {
+        if (expected == actual) {
+            return true;
+        }
+        logWithStack(String.format(message, expected, actual));
+        return false;
+    }
+
+    boolean checkEquals(String expected, String actual, String message) {
+        if (expected.equals(actual)) {
+            return true;
+        }
+        logWithStack(String.format(message, expected, actual));
+        return false;
+    }
+
+    boolean checkFlagSet(int expected, int actual, String message) {
+        if ((expected & actual) != 0) {
+            return true;
+        }
+        logWithStack(String.format(message, expected, actual));
+        return false;
+    };
+
+    private void logWithStack(String message) {
+        Throwable stackTrace = new Throwable();
+        stackTrace.fillInStackTrace();
+        Log.e(TAG, message, stackTrace);
     }
 
     // Tests
 
     private void testIsEnabled(int i) {
+        // no setup required
         Intent settings = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
         if (settings.resolveActivity(mPackageManager) == null) {
+            logWithStack("failed testIsEnabled: no settings activity");
             mStatus[i] = FAIL;
         } else {
             // TODO: find out why Secure.ENABLED_NOTIFICATION_LISTENERS is hidden
@@ -282,139 +384,244 @@
                 mStatus[i] = WAIT_FOR_USER;
             }
         }
-        mHandler.postDelayed(mRunner, 2000);
+        next();
     }
 
     private void testIsStarted(final int i) {
-        MockListener.resetListenerData(this);
-        MockListener.probeListenerStatus(mContext,
-                new MockListener.IntegerResultCatcher() {
-            @Override
-            public void accept(int result) {
-                if (result == Activity.RESULT_OK) {
-                    mStatus[i] = PASS;
-                    // setup for testNotificationRecieved
-                    sendNotificaitons();
-                } else {
-                    mStatus[i] = FAIL;
+        if (mStatus[i] == SETUP) {
+            mStatus[i] = READY;
+            // wait for the service to start
+            delay();
+        } else {
+            MockListener.probeListenerStatus(mContext,
+                    new MockListener.IntegerResultCatcher() {
+                @Override
+                public void accept(int result) {
+                    if (result == Activity.RESULT_OK) {
+                        mStatus[i] = PASS;
+                    } else {
+                        logWithStack("failed testIsStarted: " + result);
+                        mStatus[i] = FAIL;
+                    }
+                    next();
                 }
-                mHandler.postDelayed(mRunner, 2000);
-            }
-        });
+            });
+        }
     }
 
     private void testNotificationRecieved(final int i) {
-        MockListener.probeListenerPosted(mContext,
-                new MockListener.StringListResultCatcher() {
-            @Override
-            public void accept(List<String> result) {
-                if (result.size() > 0 && result.contains(mTag1)) {
-                    mStatus[i] = PASS;
-                } else {
-                    mStatus[i] = FAIL;
-                }
-                mHandler.post(mRunner);
-            }});
+        if (mStatus[i] == SETUP) {
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            sendNotificaitons();
+            mStatus[i] = READY;
+            // wait for notifications to move through the system
+            delay();
+        } else {
+            MockListener.probeListenerPosted(mContext,
+                    new MockListener.StringListResultCatcher() {
+                @Override
+                public void accept(List<String> result) {
+                    if (result.size() > 0 && result.contains(mTag1)) {
+                        mStatus[i] = PASS;
+                    } else {
+                        logWithStack("failed testNotificationRecieved");
+                        mStatus[i] = FAIL;
+                    }
+                    next();
+                }});
+        }
     }
 
     private void testDataIntact(final int i) {
+        // no setup required
         MockListener.probeListenerPayloads(mContext,
                 new MockListener.StringListResultCatcher() {
             @Override
             public void accept(List<String> result) {
-                mStatus[i] = FAIL;
+                boolean pass = false;
+                Set<String> found = new HashSet<String>();
                 if (result.size() > 0) {
-                    for(String payload : result) {
-                        if (payload.contains(mTag1) &&
-                                payload.contains(mIdString) &&
-                                payload.contains(mPackageString)) {
-                            mStatus[i] = PASS;
+                    pass = true;
+                    for(String payloadData : result) {
+                        try {
+                            JSONObject payload = new JSONObject(payloadData);
+                            pass &= checkEquals(mPackageString, payload.getString(JSON_PACKAGE),
+                                    "data integrity test fail: notificaiton package (%s, %s)");
+                            String tag = payload.getString(JSON_TAG);
+                            if (mTag1.equals(tag)) {
+                                found.add(mTag1);
+                                pass &= checkEquals(mIcon1, payload.getInt(JSON_ICON),
+                                        "data integrity test fail: notificaiton icon (%d, %d)");
+                                pass &= checkFlagSet(mFlag1, payload.getInt(JSON_FLAGS),
+                                        "data integrity test fail: notificaiton flags (%d, %d)");
+                                pass &= checkEquals(mId1, payload.getInt(JSON_ID),
+                                        "data integrity test fail: notificaiton ID (%d, %d)");
+                                pass &= checkEquals(mWhen1, payload.getLong(JSON_WHEN),
+                                        "data integrity test fail: notificaiton when (%d, %d)");
+                            } else if (mTag2.equals(tag)) {
+                                found.add(mTag2);
+                                pass &= checkEquals(mIcon2, payload.getInt(JSON_ICON),
+                                        "data integrity test fail: notificaiton icon (%d, %d)");
+                                pass &= checkFlagSet(mFlag2, payload.getInt(JSON_FLAGS),
+                                        "data integrity test fail: notificaiton flags (%d, %d)");
+                                pass &= checkEquals(mId2, payload.getInt(JSON_ID),
+                                        "data integrity test fail: notificaiton ID (%d, %d)");
+                                pass &= checkEquals(mWhen2, payload.getLong(JSON_WHEN),
+                                        "data integrity test fail: notificaiton when (%d, %d)");
+                            } else if (mTag3.equals(tag)) {
+                                found.add(mTag3);
+                                pass &= checkEquals(mIcon3, payload.getInt(JSON_ICON),
+                                        "data integrity test fail: notificaiton icon (%d, %d)");
+                                pass &= checkFlagSet(mFlag3, payload.getInt(JSON_FLAGS),
+                                        "data integrity test fail: notificaiton flags (%d, %d)");
+                                pass &= checkEquals(mId3, payload.getInt(JSON_ID),
+                                        "data integrity test fail: notificaiton ID (%d, %d)");
+                                pass &= checkEquals(mWhen3, payload.getLong(JSON_WHEN),
+                                        "data integrity test fail: notificaiton when (%d, %d)");
+                            } else {
+                                pass = false;
+                                logWithStack("failed on unexpected notification tag: " + tag);
+                            }
+                        } catch (JSONException e) {
+                            pass = false;
+                            Log.e(TAG, "failed to unpack data from mocklistener", e);
                         }
                     }
                 }
-                // setup for testDismissOne
-                MockListener.resetListenerData(mContext);
-                MockListener.clearOne(mContext, mTag1, NOTIFICATION_ID + 1);
-                mHandler.postDelayed(mRunner, 1000);
+                pass &= found.size() == 3;
+                mStatus[i] = pass ? PASS : FAIL;
+                next();
             }});
     }
 
     private void testDismissOne(final int i) {
-        MockListener.probeListenerRemoved(mContext,
-                new MockListener.StringListResultCatcher() {
-            @Override
-            public void accept(List<String> result) {
-                if (result.size() > 0 && result.contains(mTag1)) {
-                    mStatus[i] = PASS;
-                } else {
-                    mStatus[i] = FAIL;
-                }
+        if (mStatus[i] == SETUP) {
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            MockListener.clearOne(mContext, mTag1, NOTIFICATION_ID + 1);
+            mStatus[i] = READY;
+            delay();
+        } else {
+            MockListener.probeListenerRemoved(mContext,
+                    new MockListener.StringListResultCatcher() {
+                @Override
+                public void accept(List<String> result) {
+                    if (result.size() > 0 && result.contains(mTag1)) {
+                        mStatus[i] = PASS;
+                    } else {
+                        if (mStatus[i] == RETRY) {
+                            logWithStack("failed testDismissOne");
+                            mStatus[i] = FAIL;
+                        } else {
+                            logWithStack("failed testDismissOne, once: retrying");
+                            mStatus[i] = RETRY;
+                        }
+                    }
 
-                // setup for testDismissAll
-                MockListener.resetListenerData(mContext);
-                MockListener.clearAll(mContext);
-                mHandler.postDelayed(mRunner, 1000);
-            }});
+                    next();
+                }});
+        }
     }
 
     private void testDismissAll(final int i) {
-        MockListener.probeListenerRemoved(mContext,
-                new MockListener.StringListResultCatcher() {
-            @Override
-            public void accept(List<String> result) {
-                if (result.size() == 2 && result.contains(mTag2) && result.contains(mTag3)) {
-                    mStatus[i] = PASS;
-                } else {
-                    mStatus[i] = FAIL;
+        if (mStatus[i] == SETUP) {
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            MockListener.clearAll(mContext);
+            mStatus[i] = READY;
+            delay();
+        } else {
+            MockListener.probeListenerRemoved(mContext,
+                    new MockListener.StringListResultCatcher() {
+                @Override
+                public void accept(List<String> result) {
+                    if (result.size() == 2 && result.contains(mTag2) && result.contains(mTag3)) {
+                        mStatus[i] = PASS;
+                    } else {
+                        if (mStatus[i] == RETRY) {
+                            logWithStack("failed testDismissAll");
+                            mStatus[i] = FAIL;
+                        } else {
+                            logWithStack("failed testDismissAll, once: retrying");
+                            mStatus[i] = RETRY;
+                        }
+                    }
+                    next();
                 }
-                mHandler.post(mRunner);
-            }
-        });   
+            });
+        }
     }
 
     private void testIsDisabled(int i) {
-        MockListener.resetListenerData(this);
+        // no setup required
         // TODO: find out why Secure.ENABLED_NOTIFICATION_LISTENERS is hidden
         String listeners = Secure.getString(getContentResolver(),
                 "enabled_notification_listeners");
         if (listeners == null || !listeners.contains(LISTENER_PATH)) {
             mStatus[i] = PASS;
+            next();
         } else {
             mStatus[i] = WAIT_FOR_USER;
+            delay();
         }
-        mHandler.postDelayed(mRunner, 2000);
     }
 
     private void testIsStopped(final int i) {
-        MockListener.probeListenerStatus(mContext,
-                new MockListener.IntegerResultCatcher() {
-            @Override
-            public void accept(int result) {
-                if (result == Activity.RESULT_OK) {
-                    MockListener.resetListenerData(mContext);
-                    sendNotificaitons();
-                    mStatus[i] = FAIL;
-                } else {
-                    mStatus[i] = PASS;
+        if (mStatus[i] == SETUP) {
+            mStatus[i] = READY;
+            // wait for the service to start
+            delay();
+        } else {
+            MockListener.probeListenerStatus(mContext,
+                    new MockListener.IntegerResultCatcher() {
+                @Override
+                public void accept(int result) {
+                    if (result == Activity.RESULT_OK) {
+                        logWithStack("failed testIsStopped");
+                        mStatus[i] = FAIL;
+                    } else {
+                        mStatus[i] = PASS;
+                    }
+                    next();
                 }
-                // setup for testNotificationRecieved
-                sendNotificaitons();
-                mHandler.postDelayed(mRunner, 1000);
-            }
-        });
+            });
+        }
     }
 
     private void testNotificationNotRecieved(final int i) {
-        MockListener.probeListenerPosted(mContext,
-                new MockListener.StringListResultCatcher() {
-            @Override
-            public void accept(List<String> result) {
-                if (result == null || result.size() == 0) {
-                    mStatus[i] = PASS;
-                } else {
-                    mStatus[i] = FAIL;
-                }
-                mHandler.post(mRunner);
-            }});
+        if (mStatus[i] == SETUP) {
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            // setup for testNotificationRecieved
+            sendNotificaitons();
+            mStatus[i] = READY;
+            delay();
+        } else {
+            MockListener.probeListenerPosted(mContext,
+                    new MockListener.StringListResultCatcher() {
+                @Override
+                public void accept(List<String> result) {
+                    if (result == null || result.size() == 0) {
+                        mStatus[i] = PASS;
+                    } else {
+                        logWithStack("failed testNotificationNotRecieved");
+                        mStatus[i] = FAIL;
+                    }
+                    next();
+                }});
+        }
     }
 }