public void testLooperDestruction() {

    final BlockingQueue<JSONObject> messages = new LinkedBlockingQueue<JSONObject>();

    // If something terrible happens in the worker thread, we
    // should make sure
    final MPDbAdapter explodingDb =
        new MPDbAdapter(getContext()) {
          @Override
          public int addJSON(JSONObject message, MPDbAdapter.Table table) {
            messages.add(message);
            throw new RuntimeException("BANG!");
          }
        };
    final AnalyticsMessages explodingMessages =
        new AnalyticsMessages(getContext()) {
          // This will throw inside of our worker thread.
          @Override
          public MPDbAdapter makeDbAdapter(Context context) {
            return explodingDb;
          }
        };
    MixpanelAPI mixpanel =
        new TestUtils.CleanMixpanelAPI(
            getContext(), mMockPreferences, "TEST TOKEN testLooperDisaster") {
          @Override
          protected AnalyticsMessages getAnalyticsMessages() {
            return explodingMessages;
          }
        };

    try {
      mixpanel.clearPreferences();
      assertFalse(explodingMessages.isDead());

      mixpanel.track("event1", null);
      JSONObject found = messages.poll(1, TimeUnit.SECONDS);
      assertNotNull(found);
      Thread.sleep(1000);
      assertTrue(explodingMessages.isDead());

      mixpanel.track("event2", null);
      JSONObject shouldntFind = messages.poll(1, TimeUnit.SECONDS);
      assertNull(shouldntFind);
      assertTrue(explodingMessages.isDead());
    } catch (InterruptedException e) {
      fail("Unexpected interruption");
    }
  }
Beispiel #2
0
 @Override
 public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   mixpanelAPI.track(ROUTING_START, null);
   createGroup();
   bus.register(this);
 }
  private void parseFBData(JSONObject jsonObject, AccessToken token) {
    try {
      String id = jsonObject.getString("id");
      String email = jsonObject.getString("email");
      //                            String name = jsonObject.getString("name");
      String gender = jsonObject.getString("gender");
      String first_name = jsonObject.getString("first_name");
      String last_name = jsonObject.getString("last_name");

      Intent mIntent = new Intent(getActivity(), LoginUserDetails.class);
      mIntent.putExtra("login_method", "facebook");
      mIntent.putExtra("email", email);
      mIntent.putExtra("first_name", first_name);
      mIntent.putExtra("last_name", last_name);
      //            mIntent.putExtra("id", id);
      mIntent.putExtra("id", token.getUserId());
      //                            mIntent.putExtra("name",name);
      if (jsonObject.has("birthday")) {
        String birthday = jsonObject.getString("birthday");
        mIntent.putExtra("birthday", birthday);
      }

      mixpanel.track("Login - Facebook");
      mIntent.putExtra("gender", gender);
      startActivity(mIntent);
    } catch (JSONException e) {
      e.printStackTrace();
    }
  }
  @Override
  public void onConnected(Bundle bundle) {
    if (Plus.PeopleApi.getCurrentPerson(mGoogleApiClient) != null) {
      Person currentPerson = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
      String personName = currentPerson.getDisplayName();
      String personPhoto = currentPerson.getImage().getUrl();
      String firstName = currentPerson.getName().getGivenName();
      String lastName = currentPerson.getName().getFamilyName();
      String personGooglePlusProfile = currentPerson.getUrl();
      String date = currentPerson.getBirthday();
      if (date == null) {
        date = "";
      }
      int gender = currentPerson.getGender();
      String email = Plus.AccountApi.getAccountName(mGoogleApiClient);

      Intent mIntent = new Intent(getActivity(), LoginUserDetails.class);
      mIntent.putExtra("login_method", "google");
      mIntent.putExtra("email", email);
      mIntent.putExtra("first_name", firstName);
      mIntent.putExtra("gender", gender);
      mIntent.putExtra("last_name", lastName);
      mIntent.putExtra("photo", personPhoto);

      mixpanel.track("Login - Google");
      startActivity(mIntent);
    } else {
      Toast.makeText(getContext(), "You do not have a google+ account", Toast.LENGTH_SHORT).show();
      showSocialLoginDialog();
    }

    Log.d(TAG, "onConnected:" + bundle);
    mShouldResolve = false;
  }
      @Override
      public void run() {

        final MPDbAdapter dbMock =
            new MPDbAdapter(getContext()) {
              @Override
              public int addJSON(JSONObject message, MPDbAdapter.Table table) {
                mMessages.add(message);
                return 1;
              }
            };

        final AnalyticsMessages analyticsMessages =
            new AnalyticsMessages(getContext()) {
              @Override
              public MPDbAdapter makeDbAdapter(Context context) {
                return dbMock;
              }
            };

        MixpanelAPI mixpanel =
            new TestUtils.CleanMixpanelAPI(getContext(), mMockPreferences, "TEST TOKEN") {
              @Override
              protected AnalyticsMessages getAnalyticsMessages() {
                return analyticsMessages;
              }
            };
        mixpanel.clearPreferences();
        mixpanel.track("test in thread", new JSONObject());
      }
  public void trackEvent(String eventName) {
    JSONObject props = new JSONObject();

    try {
      props.put("Email", InfoUtil.getEmailAddress(context));
      props.put("Date", new Date().toString());
      mixpanelAPI.track(eventName, props);
    } catch (JSONException e) {
      // e.printStackTrace();
    }
  }
  @Override
  public void onActivityStopped(Activity activity) {
    // Remove from the current list of running activities
    status.remove(activity.toString());

    // If there are no running activities, the app is backgrounded
    // In this scenario, log the event to Mixpanel
    if (status.isEmpty()) {
      // Send the session tracking information to Mixpanel
      mixpanelCallbacks.track("$app_open");

      // Mark the current session as inactive so we properly start a new one
      mixpanelCallbacks.unregisterSuperProperty("Session");

      // Force all queued Mixpanel data to be sent to Mixpanel
      mixpanelCallbacks.flush();
    }

    Log.d("Current Activities", "onStop() " + status.toString());
  }
  public static void sendEvent(android.content.Context context, String eventTitle) {

    MixpanelAPI mixpanel = MixpanelAPI.getInstance(context, MIXPANEL_TOKEN);

    mixpanel.track(eventTitle, null);
  }
 /**
  * Tracks a Mixpanel event with properties. (for compatibilty with iOS version)
  *
  * @param event
  * @param properties
  */
 @ReactMethod
 public void trackWithProperties(String event, ReadableMap properties) {
   mixpanel.track(event, this.readableMapToJson(properties));
 }
 /**
  * Tracks a Mixpanel event.
  *
  * @param event
  * @param properties
  */
 @ReactMethod
 public void track(String event) {
   mixpanel.track(event);
 }
  public void testPersistence() {
    MixpanelAPI metricsOne = new MixpanelAPI(getContext(), mMockPreferences, "SAME TOKEN");
    metricsOne.clearPreferences();

    JSONObject props;
    try {
      props = new JSONObject("{ 'a' : 'value of a', 'b' : 'value of b' }");
    } catch (JSONException e) {
      throw new RuntimeException("Can't construct fixture for super properties test.");
    }

    metricsOne.clearSuperProperties();
    metricsOne.registerSuperProperties(props);
    metricsOne.identify("Expected Events Identity");
    metricsOne.getPeople().identify("Expected People Identity");

    // We exploit the fact that any metrics object with the same token
    // will get their values from the same persistent store.

    final List<Object> messages = new ArrayList<Object>();
    final AnalyticsMessages listener =
        new AnalyticsMessages(getContext()) {
          @Override
          public void eventsMessage(EventDescription heard) {
            messages.add(heard);
          }

          @Override
          public void peopleMessage(JSONObject heard) {
            messages.add(heard);
          }
        };

    class ListeningAPI extends MixpanelAPI {
      public ListeningAPI(Context c, Future<SharedPreferences> prefs, String token) {
        super(c, prefs, token);
      }

      @Override
      protected AnalyticsMessages getAnalyticsMessages() {
        return listener;
      }
    }

    MixpanelAPI differentToken =
        new ListeningAPI(getContext(), mMockPreferences, "DIFFERENT TOKEN");

    differentToken.track("other event", null);
    differentToken.getPeople().set("other people prop", "Word"); // should be queued up.

    assertEquals(1, messages.size());

    AnalyticsMessages.EventDescription eventMessage =
        (AnalyticsMessages.EventDescription) messages.get(0);

    try {
      JSONObject eventProps = eventMessage.getProperties();
      String sentId = eventProps.getString("distinct_id");
      String sentA = eventProps.optString("a");
      String sentB = eventProps.optString("b");

      assertFalse("Expected Events Identity".equals(sentId));
      assertEquals("", sentA);
      assertEquals("", sentB);
    } catch (JSONException e) {
      fail("Event message has an unexpected shape " + e);
    }

    messages.clear();

    MixpanelAPI metricsTwo = new ListeningAPI(getContext(), mMockPreferences, "SAME TOKEN");

    metricsTwo.track("eventname", null);
    metricsTwo.getPeople().set("people prop name", "Indeed");

    assertEquals(2, messages.size());

    eventMessage = (AnalyticsMessages.EventDescription) messages.get(0);
    JSONObject peopleMessage = (JSONObject) messages.get(1);

    try {
      JSONObject eventProps = eventMessage.getProperties();
      String sentId = eventProps.getString("distinct_id");
      String sentA = eventProps.getString("a");
      String sentB = eventProps.getString("b");

      assertEquals("Expected Events Identity", sentId);
      assertEquals("value of a", sentA);
      assertEquals("value of b", sentB);
    } catch (JSONException e) {
      fail("Event message has an unexpected shape " + e);
    }

    try {
      String sentId = peopleMessage.getString("$distinct_id");
      assertEquals("Expected People Identity", sentId);
    } catch (JSONException e) {
      fail("Event message has an unexpected shape: " + peopleMessage.toString());
    }
  }
  public void testHTTPFailures() {
    final List<Object> flushResults = new ArrayList<Object>();
    final BlockingQueue<String> performRequestCalls = new LinkedBlockingQueue<String>();

    final ServerMessage mockPoster =
        new ServerMessage() {
          @Override
          public byte[] performRequest(String endpointUrl, List<NameValuePair> nameValuePairs)
              throws IOException {
            if (null == nameValuePairs) {
              assertEquals(
                  "DECIDE ENDPOINT?version=1&lib=android&token=Test+Message+Queuing&distinct_id=new+person",
                  endpointUrl);
              return TestUtils.bytes("{}");
            }

            Object obj = flushResults.remove(0);
            try {
              assertEquals(nameValuePairs.get(0).getName(), "data");
              final String jsonData = Base64Coder.decodeString(nameValuePairs.get(0).getValue());
              JSONArray msg = new JSONArray(jsonData);
              JSONObject event = msg.getJSONObject(0);
              performRequestCalls.put(event.getString("event"));

              if (obj instanceof IOException) {
                throw (IOException) obj;
              } else if (obj instanceof MalformedURLException) {
                throw (MalformedURLException) obj;
              }
            } catch (JSONException e) {
              throw new RuntimeException("Malformed data passed to test mock", e);
            } catch (InterruptedException e) {
              throw new RuntimeException(
                  "Could not write message to reporting queue for tests.", e);
            }
            return (byte[]) obj;
          }
        };

    final MPConfig config =
        new MPConfig(new Bundle()) {
          public String getDecideEndpoint() {
            return "DECIDE ENDPOINT";
          }

          public String getEventsEndpoint() {
            return "EVENTS ENDPOINT";
          }

          public boolean getDisableFallback() {
            return false;
          }
        };

    final List<String> cleanupCalls = new ArrayList<String>();
    final MPDbAdapter mockAdapter =
        new MPDbAdapter(getContext()) {
          @Override
          public void cleanupEvents(String last_id, Table table) {
            cleanupCalls.add("called");
            super.cleanupEvents(last_id, table);
          }
        };

    final AnalyticsMessages listener =
        new AnalyticsMessages(getContext()) {
          @Override
          protected MPDbAdapter makeDbAdapter(Context context) {
            return mockAdapter;
          }

          @Override
          protected ServerMessage getPoster() {
            return mockPoster;
          }

          @Override
          protected MPConfig getConfig(Context context) {
            return config;
          }
        };

    MixpanelAPI metrics =
        new TestUtils.CleanMixpanelAPI(getContext(), mMockPreferences, "Test Message Queuing") {
          @Override
          protected AnalyticsMessages getAnalyticsMessages() {
            return listener;
          }
        };

    try {
      // Basic succeed on first, non-fallback url
      cleanupCalls.clear();
      flushResults.add(TestUtils.bytes("1\n"));
      metrics.track("Should Succeed", null);
      metrics.flush();
      Thread.sleep(500);
      assertEquals("Should Succeed", performRequestCalls.poll(2, TimeUnit.SECONDS));
      assertEquals(null, performRequestCalls.poll(2, TimeUnit.SECONDS));
      assertEquals(1, cleanupCalls.size());

      // Fallback test--first URL throws IOException
      cleanupCalls.clear();
      flushResults.add(new IOException());
      flushResults.add(TestUtils.bytes("1\n"));
      metrics.track("Should Succeed", null);
      metrics.flush();
      Thread.sleep(500);
      assertEquals("Should Succeed", performRequestCalls.poll(2, TimeUnit.SECONDS));
      assertEquals("Should Succeed", performRequestCalls.poll(2, TimeUnit.SECONDS));
      assertEquals(1, cleanupCalls.size());

      // Two IOExceptions -- assume temporary network failure, no cleanup should happen until
      // second flush
      cleanupCalls.clear();
      flushResults.add(new IOException());
      flushResults.add(new IOException());
      flushResults.add(TestUtils.bytes("1\n"));
      metrics.track("Should Succeed", null);
      metrics.flush();
      Thread.sleep(500);
      assertEquals("Should Succeed", performRequestCalls.poll(2, TimeUnit.SECONDS));
      assertEquals("Should Succeed", performRequestCalls.poll(2, TimeUnit.SECONDS));
      assertEquals(0, cleanupCalls.size());
      metrics.flush();
      Thread.sleep(500);
      assertEquals("Should Succeed", performRequestCalls.poll(2, TimeUnit.SECONDS));
      assertEquals(null, performRequestCalls.poll(2, TimeUnit.SECONDS));
      assertEquals(1, cleanupCalls.size());

      // MalformedURLException -- should dump the events since this will probably never succeed
      cleanupCalls.clear();
      flushResults.add(new MalformedURLException());
      metrics.track("Should Fail", null);
      metrics.flush();
      Thread.sleep(500);
      assertEquals("Should Fail", performRequestCalls.poll(2, TimeUnit.SECONDS));
      assertEquals(null, performRequestCalls.poll(2, TimeUnit.SECONDS));
      assertEquals(1, cleanupCalls.size());
    } catch (InterruptedException e) {
      throw new RuntimeException("Test was interrupted.");
    }
  }
  public void testMessageQueuing() {
    final BlockingQueue<String> messages = new LinkedBlockingQueue<String>();
    final SynchronizedReference<Boolean> okToDecide = new SynchronizedReference<Boolean>();
    okToDecide.set(false);

    final MPDbAdapter mockAdapter =
        new MPDbAdapter(getContext()) {
          @Override
          public int addJSON(JSONObject message, MPDbAdapter.Table table) {
            try {
              messages.put("TABLE " + table.getName());
              messages.put(message.toString());
            } catch (InterruptedException e) {
              throw new RuntimeException(e);
            }

            return super.addJSON(message, table);
          }
        };
    mockAdapter.cleanupEvents(Long.MAX_VALUE, MPDbAdapter.Table.EVENTS);
    mockAdapter.cleanupEvents(Long.MAX_VALUE, MPDbAdapter.Table.PEOPLE);

    final ServerMessage mockPoster =
        new ServerMessage() {
          @Override
          public byte[] performRequest(String endpointUrl, List<NameValuePair> nameValuePairs) {
            final boolean decideIsOk = okToDecide.get();
            if (null == nameValuePairs) {
              if (decideIsOk) {
                assertEquals(
                    "DECIDE_ENDPOINT?version=1&lib=android&token=Test+Message+Queuing&distinct_id=new+person",
                    endpointUrl);
              } else {
                fail(
                    "User is unidentified, we shouldn't be checking decide. (URL WAS "
                        + endpointUrl
                        + ")");
              }
              return TestUtils.bytes("{}");
            }

            assertEquals(nameValuePairs.get(0).getName(), "data");
            final String decoded = Base64Coder.decodeString(nameValuePairs.get(0).getValue());

            try {
              messages.put("SENT FLUSH " + endpointUrl);
              messages.put(decoded);
            } catch (InterruptedException e) {
              throw new RuntimeException(e);
            }

            return TestUtils.bytes("1\n");
          }
        };

    final MPConfig mockConfig =
        new MPConfig(new Bundle()) {
          @Override
          public int getFlushInterval() {
            return -1;
          }

          @Override
          public int getBulkUploadLimit() {
            return 40;
          }

          @Override
          public String getEventsEndpoint() {
            return "EVENTS_ENDPOINT";
          }

          @Override
          public String getPeopleEndpoint() {
            return "PEOPLE_ENDPOINT";
          }

          @Override
          public String getDecideEndpoint() {
            return "DECIDE_ENDPOINT";
          }
        };

    final AnalyticsMessages listener =
        new AnalyticsMessages(getContext()) {
          @Override
          protected MPDbAdapter makeDbAdapter(Context context) {
            return mockAdapter;
          }

          @Override
          protected MPConfig getConfig(Context context) {
            return mockConfig;
          }

          @Override
          protected ServerMessage getPoster() {
            return mockPoster;
          }
        };

    MixpanelAPI metrics =
        new TestUtils.CleanMixpanelAPI(getContext(), mMockPreferences, "Test Message Queuing") {
          @Override
          protected AnalyticsMessages getAnalyticsMessages() {
            return listener;
          }
        };

    // Test filling up the message queue
    for (int i = 0; i < mockConfig.getBulkUploadLimit() - 1; i++) {
      metrics.track("frequent event", null);
    }

    metrics.track("final event", null);
    String expectedJSONMessage = "<No message actually received>";

    try {
      for (int i = 0; i < mockConfig.getBulkUploadLimit() - 1; i++) {
        String messageTable = messages.poll(1, TimeUnit.SECONDS);
        assertEquals("TABLE " + MPDbAdapter.Table.EVENTS.getName(), messageTable);

        expectedJSONMessage = messages.poll(1, TimeUnit.SECONDS);
        JSONObject message = new JSONObject(expectedJSONMessage);
        assertEquals("frequent event", message.getString("event"));
      }

      String messageTable = messages.poll(1, TimeUnit.SECONDS);
      assertEquals("TABLE " + MPDbAdapter.Table.EVENTS.getName(), messageTable);

      expectedJSONMessage = messages.poll(1, TimeUnit.SECONDS);
      JSONObject message = new JSONObject(expectedJSONMessage);
      assertEquals("final event", message.getString("event"));

      String messageFlush = messages.poll(1, TimeUnit.SECONDS);
      assertEquals("SENT FLUSH EVENTS_ENDPOINT", messageFlush);

      expectedJSONMessage = messages.poll(1, TimeUnit.SECONDS);
      JSONArray bigFlush = new JSONArray(expectedJSONMessage);
      assertEquals(mockConfig.getBulkUploadLimit(), bigFlush.length());

      metrics.track("next wave", null);
      metrics.flush();

      String nextWaveTable = messages.poll(1, TimeUnit.SECONDS);
      assertEquals("TABLE " + MPDbAdapter.Table.EVENTS.getName(), nextWaveTable);

      expectedJSONMessage = messages.poll(1, TimeUnit.SECONDS);
      JSONObject nextWaveMessage = new JSONObject(expectedJSONMessage);
      assertEquals("next wave", nextWaveMessage.getString("event"));

      String manualFlush = messages.poll(1, TimeUnit.SECONDS);
      assertEquals("SENT FLUSH EVENTS_ENDPOINT", manualFlush);

      expectedJSONMessage = messages.poll(1, TimeUnit.SECONDS);
      JSONArray nextWave = new JSONArray(expectedJSONMessage);
      assertEquals(1, nextWave.length());

      JSONObject nextWaveEvent = nextWave.getJSONObject(0);
      assertEquals("next wave", nextWaveEvent.getString("event"));

      okToDecide.set(true);
      metrics.getPeople().identify("new person");
      metrics.getPeople().set("prop", "yup");
      metrics.flush();

      String peopleTable = messages.poll(1, TimeUnit.SECONDS);
      assertEquals("TABLE " + MPDbAdapter.Table.PEOPLE.getName(), peopleTable);

      expectedJSONMessage = messages.poll(1, TimeUnit.SECONDS);
      JSONObject peopleMessage = new JSONObject(expectedJSONMessage);

      assertEquals("new person", peopleMessage.getString("$distinct_id"));
      assertEquals("yup", peopleMessage.getJSONObject("$set").getString("prop"));

      String peopleFlush = messages.poll(1, TimeUnit.SECONDS);
      assertEquals("SENT FLUSH PEOPLE_ENDPOINT", peopleFlush);

      expectedJSONMessage = messages.poll(1, TimeUnit.SECONDS);
      JSONArray peopleSent = new JSONArray(expectedJSONMessage);
      assertEquals(1, peopleSent.length());

    } catch (InterruptedException e) {
      fail("Expected a log message about mixpanel communication but did not recieve it.");
    } catch (JSONException e) {
      fail(
          "Expected a JSON object message and got something silly instead: " + expectedJSONMessage);
    }
  }