@Test
  public void testThreadQueueOrderSetters() throws Exception {
    FileLoggerMock mockFileLogger = setFileLoggerInstanceField(activity);
    // order in the file should reflect the order of the calls even though multi-threaded:
    LogPersister.setContext(activity);
    Logger logger = Logger.getLogger("pkg");
    final int limit = 100;
    for (int i = 0; i < limit; i++) {
      if (i % 2 == 0) {
        LogPersister.storeLogs(true);
      } else {
        LogPersister.storeLogs(false);
      }
      if (i % 2 == 0) {
        LogPersister.setLogLevel(LEVEL.DEBUG);
      } else {
        LogPersister.setLogLevel(LEVEL.WARN);
      }
      logger.debug(String.valueOf(i));
    }

    Thread.sleep(limit * 5); // hope that's long enough for all the threads to complete

    JSONArray jsonArray = mockFileLogger.getAccumulatedLogCalls();

    assertEquals(50, jsonArray.length());

    // check the order.  If you were to change the LogThreadPoolWorkQueue
    // size to something other than 1, this should fail
    for (int i = 0; i < 50; i++) {
      assertEquals(String.valueOf(i * 2), jsonArray.getJSONObject(i).getString("msg"));
    }
  }
  @Test
  public void testLevels() throws Exception {
    FileLoggerMock mockFileLogger = setFileLoggerInstanceField(activity);
    LogPersister.setContext(activity);
    Logger logger = Logger.getLogger("package");
    LogPersister.storeLogs(true);

    final String hi = "hi";

    // no calls should create a file:

    LogPersister.setLogLevel(LEVEL.ERROR);
    logger.warn(hi);
    waitForNotify(logger);
    logger.info(hi);
    waitForNotify(logger);
    logger.debug(hi);
    waitForNotify(logger);

    LogPersister.setLogLevel(LEVEL.WARN);
    logger.info(hi);
    waitForNotify(logger);
    logger.debug(hi);
    waitForNotify(logger);

    LogPersister.setLogLevel(LEVEL.INFO);
    logger.debug(hi);
    waitForNotify(logger);

    // "hi" should not appear in the file

    assertEquals(0, mockFileLogger.getAccumulatedLogCalls().length());
  }
  @Test
  public void testAString() throws Exception {
    FileLoggerMock mockFileLogger = setFileLoggerInstanceField(activity);
    LogPersister.setContext(activity);
    LogPersister.setLogLevel(LEVEL.DEBUG);
    Logger logger = Logger.getLogger("package");
    LogPersister.setAnalyticsCapture(true);

    logger.analytics("message", null);

    waitForNotify(logger);

    JSONArray jsonArray = mockFileLogger.getAccumulatedLogCalls();
    JSONObject jsonObject = jsonArray.getJSONObject(0);

    // jsonObject should have a fixed number of key/value pairs
    assertEquals(
        "resulting jsonobject in file has wrong number of key/value pairs", 6, jsonObject.length());
    // verify the key/value pairs
    assertTrue(
        jsonObject.has(TIMESTAMP_KEY)); // don't test the value, as it may differ from current
    assertEquals("package", jsonObject.get(PACKAGE_KEY));
    // WARN
    assertEquals("ANALYTICS", jsonObject.get(LEVEL_KEY));
    assertEquals("message", jsonObject.get(MESSAGE_KEY));
    // ensure no exception is thrown by parsing the threadid value:
    assertFalse(jsonObject.getLong(THREADID_KEY) == 0);
  }
  @Test
  public void testGetInstanceEmptyTag() throws Exception {
    FileLoggerMock mockFileLogger = setFileLoggerInstanceField(activity);
    LogPersister.setContext(activity);
    LogPersister.setLogLevel(LEVEL.DEBUG);
    Logger logger = Logger.getLogger("  ");
    logger.info("message 1");

    waitForNotify(logger);

    JSONArray jsonArray = mockFileLogger.getAccumulatedLogCalls();
    JSONObject jsonObject = jsonArray.getJSONObject(0);

    assertEquals("NONE", jsonObject.getString(PACKAGE_KEY));
  }
  @Test
  public void testNullContext() throws Exception {
    FileLoggerMock mockFileLogger = setFileLoggerInstanceField(activity);
    // we should not get any exceptions
    String s =
        new String(LogPersister.getByteArrayFromFile(new File(activity.getFilesDir(), FILE_NAME0)));
    assertEquals("", s);

    Logger logger = Logger.getLogger("testNullContext");
    LogPersister.storeLogs(true);
    logger.info("hi");
    // no file should exist, since we can't write to file when the static Context object in Logger
    // is null
    assertEquals(0, mockFileLogger.getAccumulatedLogCalls().length());
  }
  @Test
  public void testJULLoggerGoodMetadata() throws Exception {
    FileLoggerMock mockFileLogger = setFileLoggerInstanceField(activity);
    // test that the JUL path works, and the metadata shows the caller, not JULLogger
    LogPersister.setContext(activity);
    LogPersister.setLogLevel(LEVEL.DEBUG);
    LogPersister.storeLogs(true);

    java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger("package");

    // a trick to wait for the logger to finish in this test
    Logger logger = Logger.getLogger("package");

    // JUL API:
    julLogger.severe("JULsevere");

    // a trick to wait for the logger to finish in this test
    waitForNotify(logger);

    int foundCount = 0;

    JSONArray arr = mockFileLogger.getAccumulatedLogCalls();

    for (int i = 0; i < arr.length(); i++) {
      Object obj = null;
      try {
        obj = arr.get(i);
      } catch (JSONException e) {
        // ignore
      }
      if (obj != null) {
        String message = arr.getJSONObject(i).getString("msg");
        if (message.equals("JULsevere")) {
          // we found the right entry, now confirm the metadata
          System.out.println(arr.getJSONObject(i));
          foundCount++;
          break;
        }
      }
    }

    assertEquals(1, foundCount);
  }
  @Test
  public void testLoggerTimestampAccuracy() throws Exception {
    // make sure the threadpool and queuing inside Logger implementation don't mess with the
    // timestamps
    FileLoggerMock mockFileLogger = setFileLoggerInstanceField(activity);
    LogPersister.setContext(activity);
    LogPersister.setLogLevel(Logger.LEVEL.DEBUG);
    Logger logger = Logger.getLogger("package");
    LogPersister.storeLogs(true);

    logger.info("message");

    waitForNotify(logger);

    int timeBetween = 50;

    Thread.sleep(
        timeBetween); // make sure next log's timestamp is at least timeBetween later than the prior

    logger.info("message2");
    waitForNotify(logger);

    JSONArray jsonArray = mockFileLogger.getAccumulatedLogCalls();
    JSONObject jsonObject1 = jsonArray.getJSONObject(0);
    JSONObject jsonObject2 = jsonArray.getJSONObject(1);

    // expect Long, not String
    Long timestamp1 = jsonObject1.getLong(TIMESTAMP_KEY);
    Long timestamp2 = jsonObject2.getLong(TIMESTAMP_KEY);

    Date date1 = new Date(timestamp1);
    Date date2 = new Date(timestamp2);

    long dateDifference = date2.getTime() - date1.getTime();
    assertTrue(
        "Expected date1 to be "
            + timeBetween
            + " or more milliseconds before date2, but the difference is only "
            + dateDifference,
        dateDifference >= timeBetween);
  }
  @Test
  public void testCapture() throws Exception {
    FileLoggerMock mockFileLogger = setFileLoggerInstanceField(activity);
    System.out.println(mockFileLogger.getAccumulatedLogCalls().length());
    LogPersister.setContext(activity);
    //
    //	System.out.println(mockFileLogger.getAccumulatedLogCalls().getJSONObject(0).getString("msg"));
    //
    //	System.out.println(mockFileLogger.getAccumulatedLogCalls().getJSONObject(1).getString("msg"));
    LogPersister.setLogLevel(LEVEL.DEBUG);

    Logger logger = Logger.getLogger("tag 2");

    logger.info("message 1");
    waitForNotify(logger);

    logger.info("message 2");
    waitForNotify(logger);

    // persistence is on by default, so...
    assertEquals(2, mockFileLogger.getAccumulatedLogCalls().length());

    // this will verify file existence and the code path through 'getStringFromFile(FILE_NAME0)'

    JSONArray jsonArray = mockFileLogger.getAccumulatedLogCalls();
    JSONObject jsonObject = jsonArray.getJSONObject(1);

    // jsonObject should have a fixed number of key/value pairs
    assertEquals(
        "resulting jsonobject in file has wrong number of key/value pairs", 6, jsonObject.length());
    // verify the key/value pairs (persistence was only on for second logger call)
    assertTrue(
        jsonObject.has(TIMESTAMP_KEY)); // don't test the value, as it may differ from current
    assertEquals("tag 2", jsonObject.get(PACKAGE_KEY));

    assertEquals("INFO", jsonObject.get(LEVEL_KEY));
    assertEquals("message 2", jsonObject.get(MESSAGE_KEY));
    // ensure no exception is thrown by parsing the threadid value:
    assertFalse(jsonObject.getLong(THREADID_KEY) == 0);
  }
  @Test
  public void testJULLoggerMappings() throws Exception {
    FileLoggerMock mockFileLogger = setFileLoggerInstanceField(activity);
    // test that the JUL path works, and the mappings are good
    LogPersister.setContext(activity);
    LogPersister.setLogLevel(LEVEL.DEBUG);
    LogPersister.storeLogs(true);

    HashMap<String, LEVEL> messagesMapping = new HashMap<String, LEVEL>();
    messagesMapping.put("JULsevere", LEVEL.ERROR);
    messagesMapping.put("JULwarning", LEVEL.WARN);
    messagesMapping.put("JULinfo", LEVEL.INFO);
    messagesMapping.put("JULconfig", LEVEL.DEBUG);
    messagesMapping.put("JULfine", LEVEL.DEBUG);
    messagesMapping.put("JULfiner", LEVEL.DEBUG);
    messagesMapping.put("JULfinest", LEVEL.DEBUG);
    messagesMapping.put("ENTRY", LEVEL.DEBUG);
    messagesMapping.put("RETURN", LEVEL.DEBUG);
    messagesMapping.put("ENTRY {0}", LEVEL.DEBUG);
    messagesMapping.put("RETURN {0}", LEVEL.DEBUG);

    java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger("package");

    // a trick to get this test to wait
    Logger logger = Logger.getLogger("package");

    // JUL API:
    julLogger.severe("JULsevere");
    waitForNotify(logger);
    julLogger.warning("JULwarning");
    waitForNotify(logger);
    julLogger.info("JULinfo");
    waitForNotify(logger);
    julLogger.config("JULconfig");
    waitForNotify(logger);
    julLogger.fine("JULfine");
    waitForNotify(logger);
    julLogger.finer("JULfiner");
    waitForNotify(logger);
    julLogger.finest("JULfinest");
    waitForNotify(logger);
    julLogger.entering("enteringClass", "enteringMethod");
    waitForNotify(logger);
    julLogger.exiting("exitingClass", "exitingMethod");
    waitForNotify(logger);
    julLogger.entering("enteringClass", "enteringMethod", new String("param"));
    waitForNotify(logger);
    julLogger.exiting("exitingClass", "exitingMethod", new String("param"));
    waitForNotify(logger);

    int foundCount = 0;

    JSONArray arr = mockFileLogger.getAccumulatedLogCalls();

    for (int i = 0; i < arr.length(); i++) {
      Object obj = null;
      try {
        obj = arr.get(i);
      } catch (JSONException e) {
        // ignore
      }
      if (obj != null) {
        String message = arr.getJSONObject(i).getString("msg");
        LEVEL l = LEVEL.fromString(arr.getJSONObject(i).getString("level"));
        if (messagesMapping
            .get(message)
            .equals(l /*LEVEL.fromString(arr.getJSONObject(i).getString("level"))*/)) {
          foundCount++;
        }
      }
    }

    assertEquals(messagesMapping.size(), foundCount);
  }