Merge branch 'master' of https://code.google.com/p/plexi
diff --git a/resources/com/google/enterprise/adaptor/TranslationStrings.properties b/resources/com/google/enterprise/adaptor/TranslationStrings.properties
index 38b4c82..47a9e43 100644
--- a/resources/com/google/enterprise/adaptor/TranslationStrings.properties
+++ b/resources/com/google/enterprise/adaptor/TranslationStrings.properties
@@ -38,6 +38,8 @@
   HTTP header.
 # The server encountered an error of some sort while processing the request.
 HTTP_INTERNAL_ERROR=Error 500: Internal Server Error
+# What to display as the configuration filename when no file was used.
+STATS_CONFIG_NONE=none
 # Shown when adaptor version is not known.
 STATS_VERSION_UNKNOWN=Unknown
 # The name of a status that monitors whether the GSA has made a request
@@ -55,5 +57,3 @@
 STATUS_FEED=Feed Pushing
 # The last data feed was interrupted before completion.
 STATUS_FEED_INTERRUPTED=Push was interrupted
-# What to display as the configure filename when none exists.
-STATUS_NONE=none
diff --git a/src/com/google/enterprise/adaptor/DownloadDumpHandler.java b/src/com/google/enterprise/adaptor/DownloadDumpHandler.java
index 6547b12..e97acb4 100644
--- a/src/com/google/enterprise/adaptor/DownloadDumpHandler.java
+++ b/src/com/google/enterprise/adaptor/DownloadDumpHandler.java
@@ -15,6 +15,7 @@
 package com.google.enterprise.adaptor;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableSet;
 
 import com.sun.net.httpserver.HttpExchange;
 import com.sun.net.httpserver.HttpHandler;
@@ -24,8 +25,9 @@
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Date;
-import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Set;
+import java.util.TimeZone;
 import java.util.TreeMap;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -48,7 +50,7 @@
   private String feedName;
 
   /** Used to obtain statistics for one file in the .zip */
-  private StatRpcMethod statRpcMethod;
+  private final StatRpcMethod statRpcMethod;
 
   /** Used to specify the top-level directory where logs are kept */
   private final File logsDir;
@@ -217,9 +219,6 @@
    */
   private void dumpStats(ZipOutputStream zos) throws IOException {
     PrintWriter writer = new PrintWriter(new OutputStreamWriter(zos, "UTF-8"));
-    String newline = "\n"; // so our support folks always see the same results
-    // LinkedHashMap maintains put() -> get() order of elements.
-    LinkedHashMap<String, String> stats = new LinkedHashMap<String, String>();
     if (statRpcMethod == null) {
       return;  // don't generate empty stats file
     }
@@ -231,53 +230,43 @@
     if (null != map.get("versionStats")) {
       @SuppressWarnings("unchecked")
       Map<String, Object> vMap = (Map<String, Object>) map.get("versionStats");
-      // TODO(myk): determine if these strings can be shared with the CSS code
-      // that displays these in the dashboard
-      stats.put("JVM version", vMap.get("versionJvm").toString());
-      stats.put("Adaptor library version",
-          vMap.get("versionAdaptorLibrary").toString());
-      stats.put("Adaptor type", vMap.get("typeAdaptor").toString());
-      stats.put("Adaptor version", vMap.get("versionAdaptor").toString());
-      stats.put("Configuration file", vMap.get("configFileName").toString());
-      stats.put("current directory", vMap.get("cwd").toString());
-      prettyPrintMap(writer, stats);
-      stats.clear();
+      prettyPrintMap(writer, vMap);
     }
 
     if (null != map.get("simpleStats")) {
       @SuppressWarnings("unchecked")
       Map<String, Object> sMap = (Map<String, Object>) map.get("simpleStats");
-      stats.put("Program started at",
-          prettyDate(sMap.get("whenStarted"), "Unknown"));
-      stats.put("Last successful full push start",
-          prettyDate(sMap.get("lastSuccessfulFullPushStart"), "None yet"));
-      stats.put("Last successful full push end",
-          prettyDate(sMap.get("lastSuccessfulFullPushEnd"), "None yet"));
-      stats.put("Current full push",
-          prettyDate(sMap.get("currentFullPushStart"), "None in progress"));
-      stats.put("Last successful incremental push start",
-          prettyDate(sMap.get("lastSuccessfulIncrementalPushStart"),
-              "None yet"));
-      stats.put("Last successful incremental push end",
-          prettyDate(sMap.get("lastSuccessfulIncrementalPushEnd"), "None yet"));
-      stats.put("Current incremental push",
-          prettyDate(sMap.get("currentIncrementalPushStart"),
-              "None in progress"));
-      stats.put("Total document ids pushed",
-          sMap.get("numTotalDocIdsPushed").toString());
-      stats.put("Unique document ids pushed",
-          sMap.get("numUniqueDocIdsPushed").toString());
-      stats.put("GSA document requests",
-          sMap.get("numTotalGsaRequests").toString());
-      stats.put("GSA Unique document requests",
-          sMap.get("numUniqueGsaRequests").toString());
-      stats.put("Non-GSA document requests",
-          sMap.get("numTotalNonGsaRequests").toString());
-      stats.put("Non-GSA Unique document requests",
-          sMap.get("numUniqueNonGsaRequests").toString());
-      stats.put("Time resolution", sMap.get("timeResolution") + " ms");
-      prettyPrintMap(writer, stats);
-      stats.clear();
+      Set<String> expectedDateAttrs = ImmutableSet.of("whenStarted",
+          "lastSuccessfulFullPushStart", "lastSuccessfulFullPushEnd",
+          "currentFullPushStart", "lastSuccessfulIncremementalPushStart",
+          "lastSuccessfulIncremementalPushEnd", "currentIncrementalPushEnd");
+      DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss Z");
+      dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
+      for (String key : expectedDateAttrs) {
+        if (!sMap.containsKey(key)) {
+          log.log(Level.INFO,
+              "Did not find expected key \"{0}\" in simpleStats", key);
+          continue;
+        }
+        Object value = sMap.get(key);
+        if (value == null) {
+          continue;
+        }
+        if (!(value instanceof Number)) {
+          log.log(Level.INFO,
+              "Key \"{0}\" contained non-date value \"{1}\" in simpleStats",
+              new Object[] {key, value});
+          continue;
+        }
+        long date = ((Number) value).longValue();
+        if (date <= 0) {
+          continue;
+        }
+        // It's a number > 0 -- assume it's a date.
+        // Replace value in map with a formatted date.
+        sMap.put(key, dateFormat.format(new Date(date)));
+      }
+      prettyPrintMap(writer, sMap);
     }
 
     writer.flush();
@@ -287,7 +276,7 @@
   /**
    * Pretty-prints a map
    */
-  void prettyPrintMap(PrintWriter writer, Map<String, String> map) {
+  void prettyPrintMap(PrintWriter writer, Map<String, ?> map) {
     int maxKeyLength = 0;
 
     for (String key : map.keySet()) {
@@ -297,28 +286,13 @@
     }
 
     String outputFormat = "%-" + (maxKeyLength + 1) + "s= %s%n";
-    for (Map.Entry<String, String> me : map.entrySet()) {
+    for (Map.Entry<String, ?> me : map.entrySet()) {
       writer.format(outputFormat, me.getKey(),
-          (me.getValue() == null ? "[null]" : me.getValue()));
+          (me.getValue() == null ? "[null]" : me.getValue().toString()));
     }
     writer.format("%n");
   }
 
-  private String prettyDate(Object date, String defaultText) {
-    if (null == date) {
-      return defaultText;
-    }
-    try {
-      long value = new Long(date.toString());
-      if (value == 0) {
-        return defaultText;
-      }
-      return new Date(value).toString();
-    } catch (NumberFormatException e) {
-      return defaultText;
-    }
-  }
-
   /**
    * Method gets overriden in test class to avoid using "real" IO.
    */
diff --git a/src/com/google/enterprise/adaptor/StatRpcMethod.java b/src/com/google/enterprise/adaptor/StatRpcMethod.java
index fe53810..ae1e519 100644
--- a/src/com/google/enterprise/adaptor/StatRpcMethod.java
+++ b/src/com/google/enterprise/adaptor/StatRpcMethod.java
@@ -22,6 +22,8 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.TreeMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 /**
  * Provides performance data when responding to 
@@ -33,6 +35,8 @@
   private Journal journal;
   private boolean isAdaptorIncremental;
   private File configFile;
+  private static final Logger log
+      = Logger.getLogger(StatRpcMethod.class.getName());
 
   public StatRpcMethod(Journal journal, Adaptor adaptor,
       boolean isAdaptorIncremental, File configFile) {
@@ -154,11 +158,13 @@
         canonicalConfigFile = configFile.getCanonicalFile();
       }
     } catch (IOException e) {
-      // ignore error; treat file as null
+      log.log(Level.WARNING, "Could not determine file location for \""
+          + configFile + "\"", e);
+      // treat file as if it were not specified -- leave it null below
     }
 
     return canonicalConfigFile == null ?
-        Translation.STATUS_NONE.toString(locale) :
+        Translation.STATS_CONFIG_NONE.toString(locale) :
         canonicalConfigFile.toString();
   }
 }
diff --git a/src/com/google/enterprise/adaptor/Translation.java b/src/com/google/enterprise/adaptor/Translation.java
index 06c0e9a..0ac47db 100644
--- a/src/com/google/enterprise/adaptor/Translation.java
+++ b/src/com/google/enterprise/adaptor/Translation.java
@@ -38,6 +38,7 @@
   HTTP_BAD_METHOD,
   HTTP_CONFLICT_INVALID_HEADER,
   HTTP_INTERNAL_ERROR,
+  STATS_CONFIG_NONE,
   STATS_VERSION_UNKNOWN,
   STATUS_CRAWLING,
   STATUS_CRAWLING_NO_ACCESSES_IN_PAST_DAY,
@@ -45,7 +46,6 @@
   STATUS_ERROR_RATE_RATE,
   STATUS_FEED,
   STATUS_FEED_INTERRUPTED,
-  STATUS_NONE,
   ;
 
   /**
diff --git a/test/com/google/enterprise/adaptor/DownloadDumpHandlerTest.java b/test/com/google/enterprise/adaptor/DownloadDumpHandlerTest.java
index be693ed..e8514ac 100644
--- a/test/com/google/enterprise/adaptor/DownloadDumpHandlerTest.java
+++ b/test/com/google/enterprise/adaptor/DownloadDumpHandlerTest.java
@@ -16,6 +16,7 @@
 
 import static org.junit.Assert.*;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -25,31 +26,45 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.charset.Charset;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.TimeZone;
+import java.util.TreeMap;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
+
 /**
  * Tests for {@link DownloadDumpHandler}.
  */
 public class DownloadDumpHandlerTest {
-  private Config config;
-  private DownloadDumpHandler handler;
+  private final Config config = new Config();
+  private DownloadDumpHandler handler =
+      new ModifiedDownloadDumpHandler(config, "adaptor");
   private final String pathPrefix = "/";
-  private MockHttpContext httpContext;
-  private MockHttpExchange ex;
+  private final MockHttpContext httpContext =
+      new MockHttpContext(handler, pathPrefix);
+  private MockHttpExchange ex = createExchange("");
+  private TimeZone previousTimeZone;
 
   @Rule
   public ExpectedException thrown = ExpectedException.none();
 
   @Before
   public void setUp() {
-    config = new Config();
     // problems arise if gsa.version is left unset
     config.setValue("gsa.version", "7.0.14-114");
-    handler = new ModifiedDownloadDumpHandler(config, "adaptor");
-    httpContext = new MockHttpContext(handler, pathPrefix);
-    ex = createExchange("");
+    previousTimeZone = TimeZone.getDefault();
+    TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+  }
+
+  @After
+  public void tearDown() {
+    TimeZone.setDefault(previousTimeZone);
   }
 
   @Test
@@ -87,8 +102,6 @@
   @Test
   public void testLogFilesWithCannedLogsDir() throws Exception {
     // set up File using MockFile
-    TimeZone previousTimeZone = TimeZone.getDefault();
-    TimeZone.setDefault(TimeZone.getTimeZone("PST"));
     MockFile mockLogsDir = new MockFile("parentDir").setChildren(new File[] {
       new MockFile("log1.log").setFileContents("Log file 1"),
       new MockFile("log1.log.lck").setFileContents("skipped lock file"),
@@ -98,39 +111,149 @@
       })});
     MockTimeProvider timeProvider = new MockTimeProvider();
     timeProvider.time = 1383763470000L; // November 6, 2013 @ 10:44:30
-    try {
-      handler = new ModifiedDownloadDumpHandler(config, "adaptor", mockLogsDir,
-          timeProvider);
-      handler.handle(ex);
-      assertEquals(200, ex.getResponseCode());
-      assertEquals("application/zip",
-          ex.getResponseHeaders().getFirst("Content-Type"));
-      assertEquals("attachment; filename=\"adaptor-20131106.zip\"",
-          ex.getResponseHeaders().getFirst("Content-Disposition"));
-      // extract the zip contents and just count the number of entries
-      int entries = countZipEntries(ex.getResponseBytes());
-      assertEquals(4, entries); /* 2 log files + thread dump + config */
-    } finally {
-       TimeZone.setDefault(previousTimeZone);
-    }
+    StatRpcMethod statRpcMethod = new MockStatRpcMethod(
+        new MockJournal(new MockTimeProvider()),
+        new MockAdaptor(),
+        /*isAdaptorIncremental=*/ false,
+        /*configFile=*/ new MockFile("no-such-dir").setExists(false));
+    handler = new ModifiedDownloadDumpHandler(config, "adaptor",
+        statRpcMethod, mockLogsDir, timeProvider);
+    handler.handle(ex);
+    assertEquals(200, ex.getResponseCode());
+    assertEquals("application/zip",
+        ex.getResponseHeaders().getFirst("Content-Type"));
+    assertEquals("attachment; filename=\"adaptor-20131106.zip\"",
+        ex.getResponseHeaders().getFirst("Content-Disposition"));
+    // extract the zip contents and just count the number of entries
+    byte[] zipContents = ex.getResponseBytes();
+    int entries = countZipEntries(zipContents);
+    assertEquals(5, entries); /* 2 log files + thread dump + config + stats */
+
+    // verify contents of thread dump
+    String threadContents = extractFileFromZip("threaddump.txt", zipContents);
+    assertTrue(threadContents.contains("Thread[Signal Dispatcher,"));
+    assertTrue(threadContents.contains("Thread[main,"));
+
+    // verify contents of config file
+    String configContents = extractFileFromZip("config.txt", zipContents);
+    // search for: \ngsa.version[spaces]= 7.0.14-114\n
+    int position = configContents.indexOf("\ngsa.version");
+    assertTrue(position > 0);
+    int equals = configContents.indexOf("=", position);
+    assertTrue(equals > 0);
+    assertEquals("= 7.0.14-114\n",
+        configContents.substring(equals, equals + 13));
+
+    // verify contents of stats file
+    String goldenStats = "versionJvm = 1.6.0\n\n"
+        + "isIncrementalSupported = false\n"
+        + "numTotalDocIdsPushed   = 0\n\n";
+    String statsContents = extractFileFromZip("stats.txt", zipContents);
+    assertEquals(goldenStats, statsContents);
   }
 
   @Test
   public void testLogFilesWithNoLogsDir() throws Exception {
-    TimeZone previousTimeZone = TimeZone.getDefault();
-    TimeZone.setDefault(TimeZone.getTimeZone("PST"));
-    try {
-      handler = new ModifiedDownloadDumpHandler(config, "myadaptor",
-          new MockFile("no-such-dir").setExists(false), new MockTimeProvider());
-      handler.handle(ex);
-      assertEquals(200, ex.getResponseCode());
-      assertEquals("attachment; filename=\"myadaptor-19691231.zip\"",
-          ex.getResponseHeaders().getFirst("Content-Disposition"));
-      int entries = countZipEntries(ex.getResponseBytes());
-      assertEquals(2, entries); /* 0 log files + thread dump + config */
-   } finally {
-      TimeZone.setDefault(previousTimeZone);
-   }
+    handler = new ModifiedDownloadDumpHandler(config, "myadaptor",
+        new MockFile("no-such-dir").setExists(false), new MockTimeProvider());
+    handler.handle(ex);
+    assertEquals(200, ex.getResponseCode());
+    assertEquals("attachment; filename=\"myadaptor-19691231.zip\"",
+        ex.getResponseHeaders().getFirst("Content-Disposition"));
+    int entries = countZipEntries(ex.getResponseBytes());
+    assertEquals(2, entries); /* 0 log files + thread dump + config */
+  }
+
+  @Test
+  public void testLogFilesWithEmptyStats() throws Exception {
+    // set up File using MockFile
+    handler = new ModifiedDownloadDumpHandler(config, "myadaptor",
+        new MockFile("no-such-dir").setExists(false), new MockTimeProvider());
+    StatRpcMethod statRpcMethod = new MockStatRpcMethod(
+        new MockJournal(new MockTimeProvider()),
+        new MockAdaptor(),
+        /*isAdaptorIncremental=*/ false,
+        /*configFile=*/ new MockFile("no-such-dir").setExists(false)) {
+
+      /** generate neither versionStats nor simpleStats maps */
+      @Override
+      public Object run(List request) {
+        Map<String, Object> results = new HashMap<String, Object>();
+        Map<String, Object> otherStats = new HashMap<String, Object>();
+        otherStats.put("someBooleanValue", false);
+        otherStats.put("someLongValue", 42L);
+        // rest omitted
+        results.put("otherStats", otherStats);
+
+        return Collections.unmodifiableMap(results);
+      }
+    };
+    handler = new ModifiedDownloadDumpHandler(config, "adaptor",
+        statRpcMethod, new MockFile("no-such-dir").setExists(false),
+        new MockTimeProvider());
+    handler.handle(ex);
+    assertEquals(200, ex.getResponseCode());
+    assertEquals("application/zip",
+        ex.getResponseHeaders().getFirst("Content-Type"));
+    // extract the zip contents and just count the number of entries
+    byte[] zipContents = ex.getResponseBytes();
+    int entries = countZipEntries(zipContents);
+    assertEquals(3, entries); /* 0 log files + thread dump + config + stats */
+
+    // verify contents of stats file
+    String goldenStats = "";
+    String statsContents = extractFileFromZip("stats.txt", zipContents);
+    assertEquals(goldenStats, statsContents);
+  }
+
+  @Test
+  public void testLogFilesWithUnusualStats() throws Exception {
+    // set up File using MockFile
+    handler = new ModifiedDownloadDumpHandler(config, "myadaptor",
+        new MockFile("no-such-dir").setExists(false), new MockTimeProvider());
+    StatRpcMethod statRpcMethod = new MockStatRpcMethod(
+        new MockJournal(new MockTimeProvider()),
+        new MockAdaptor(),
+        /*isAdaptorIncremental=*/ false,
+        /*configFile=*/ new MockFile("no-such-dir").setExists(false)) {
+
+      /** generate neither versionStats nor simpleStats maps */
+      @Override
+      public Object run(List request) {
+        Map<String, Object> results = new HashMap<String, Object>();
+        Map<String, Object> simpleStats = new TreeMap<String, Object>();
+        // keys get sorted into alphabetic order in golden map below
+        simpleStats.put("whenStarted", "non-numeric value");
+        simpleStats.put("lastSuccessfulFullPushEnd", null);
+        simpleStats.put("currentFullPushStart", 0);
+        simpleStats.put("lastSuccessfulIncremementalPushStart", -5);
+        simpleStats.put("currentIncrementalPushEnd", 1389735897000L);
+        // rest omitted
+        results.put("simpleStats", simpleStats);
+
+        return Collections.unmodifiableMap(results);
+      }
+    };
+    handler = new ModifiedDownloadDumpHandler(config, "adaptor",
+        statRpcMethod, new MockFile("no-such-dir").setExists(false),
+        new MockTimeProvider());
+    handler.handle(ex);
+    assertEquals(200, ex.getResponseCode());
+    assertEquals("application/zip",
+        ex.getResponseHeaders().getFirst("Content-Type"));
+    // extract the zip contents and just count the number of entries
+    byte[] zipContents = ex.getResponseBytes();
+    int entries = countZipEntries(zipContents);
+    assertEquals(3, entries); /* 0 log files + thread dump + config + stats */
+
+    // verify contents of stats file
+    String goldenStats = "currentFullPushStart                 = 0\n"
+        + "currentIncrementalPushEnd            = 01/14/2014 21:44:57 +0000\n"
+        + "lastSuccessfulFullPushEnd            = [null]\n"
+        + "lastSuccessfulIncremementalPushStart = -5\n"
+        + "whenStarted                          = non-numeric value\n\n";
+    String statsContents = extractFileFromZip("stats.txt", zipContents);
+    assertEquals(goldenStats, statsContents);
   }
 
   private MockHttpExchange createExchange(String path) {
@@ -151,6 +274,23 @@
     return entries;
   }
 
+  /**
+   * extracts the contents of a specified filename from a given zip (as a
+   * <code>String</code>)
+   */
+  private String extractFileFromZip(String filename, byte[] zipContents)
+      throws IOException {
+    ZipInputStream zis = new ZipInputStream(
+        new ByteArrayInputStream(zipContents));
+    ZipEntry ze = null;
+    while ((ze = zis.getNextEntry()) != null) {
+      if (ze.getName().equals(filename)) {
+        return IOHelper.readInputStreamToString(zis, Charset.forName("UTF-8"));
+      }
+    }
+    return null; // file not found
+  }
+
   private static class ModifiedDownloadDumpHandler extends DownloadDumpHandler {
     public ModifiedDownloadDumpHandler(Config config, String feedName) {
       super(config, feedName, null);
@@ -161,12 +301,42 @@
       super(config, feedName, null, logsDir, timeProvider);
     }
 
+    ModifiedDownloadDumpHandler(Config config, String feedName,
+        StatRpcMethod statRpcMethod, File logsDir, TimeProvider timeProvider) {
+      super(config, feedName, statRpcMethod, logsDir, timeProvider);
+    }
+
     @Override
-    protected InputStream createInputStream(File file) {
+    InputStream createInputStream(File file) throws IOException {
       if (!(file instanceof MockFile)) {
         throw new IllegalArgumentException("implemented only for MockFile.");
       }
       return ((MockFile) file).createInputStream();
     }
   }
+
+  private static class MockStatRpcMethod extends StatRpcMethod {
+    MockStatRpcMethod(Journal journal, Adaptor adaptor,
+        boolean isAdaptorIncremental, File configFile) {
+      super(journal, adaptor, isAdaptorIncremental, configFile);
+    }
+
+    @Override
+    public Object run(List request) {
+      Map<String, Object> golden = new HashMap<String, Object>();
+      Map<String, Object> simpleStats = new HashMap<String, Object>();
+      simpleStats.put("isIncrementalSupported", false);
+      simpleStats.put("numTotalDocIdsPushed", 0L);
+      // rest omitted
+      golden.put("simpleStats", simpleStats);
+
+      Map<String, Object> versionMap = new HashMap<String, Object>();
+      versionMap.put("versionJvm", "1.6.0");
+      // rest omitted
+
+      golden.put("versionStats", versionMap);
+
+      return Collections.unmodifiableMap(golden);
+    }
+  }
 }
diff --git a/test/com/google/enterprise/adaptor/StatRpcMethodTest.java b/test/com/google/enterprise/adaptor/StatRpcMethodTest.java
index 0475f77..d9fbe12 100644
--- a/test/com/google/enterprise/adaptor/StatRpcMethodTest.java
+++ b/test/com/google/enterprise/adaptor/StatRpcMethodTest.java
@@ -59,7 +59,7 @@
                      Translation.STATS_VERSION_UNKNOWN.toString(locale));
       versionMap.put("cwd", System.getProperty("user.dir"));
       versionMap.put("configFileName",
-                     Translation.STATUS_NONE.toString(locale));
+                     Translation.STATS_CONFIG_NONE.toString(locale));
 
       golden.put("versionStats", versionMap);