/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package vogar; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.LinkedHashMap; import java.util.Map; import java.util.TimeZone; import vogar.commands.Mkdir; import vogar.commands.Rm; public final class OutcomeStore { private static final String FILE_NAME_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssz"; private static final int PRESERVE_TOTAL = 10; private static final Comparator ORDER_BY_LAST_MODIFIED = new Comparator() { @Override public int compare(File a, File b) { if (a.lastModified() != b.lastModified()) { return a.lastModified() < b.lastModified() ? -1 : 1; } return 0; } }; private final Log log; private final Mkdir mkdir; private final Rm rm; private final File resultsDir; private final boolean recordResults; private final ExpectationStore expectationStore; private final Date date; public OutcomeStore(Log log, Mkdir mkdir, Rm rm, File resultsDir, boolean recordResults, ExpectationStore expectationStore, Date date) { this.log = log; this.mkdir = mkdir; this.rm = rm; this.resultsDir = resultsDir; this.recordResults = recordResults; this.expectationStore = expectationStore; this.date = date; } public Map read(Map outcomes) { Map result = new LinkedHashMap(); for (Map.Entry entry : outcomes.entrySet()) { Outcome outcome = entry.getValue(); Expectation expectation = expectationStore.get(outcome); result.put(entry.getKey(), new AnnotatedOutcome(outcome, expectation)); } try { File[] oldOutcomes = getOutcomeFiles(); log.verbose("parsing outcomes from " + oldOutcomes.length + " files"); for (File file : oldOutcomes) { if (!file.getName().endsWith(".json")) { continue; } loadOutcomes(result, file, file.lastModified()); } } catch (IOException e) { log.info("Failed to read outcomes from " + resultsDir, e); } return result; } private void loadOutcomes(Map map, File file, long fileDate) throws IOException { JsonReader in = new JsonReader(new FileReader(file)); in.beginObject(); while (in.hasNext()) { String outcomeName = in.nextName(); AnnotatedOutcome annotatedOutcome = map.get(outcomeName); if (annotatedOutcome == null) { in.skipValue(); continue; } Result result = null; in.beginObject(); while (in.hasNext()) { String fieldName = in.nextName(); if (fieldName.equals("result")) { result = Result.valueOf(in.nextString()); } else { in.skipValue(); } } in.endObject(); annotatedOutcome.add(fileDate, new Outcome(outcomeName, result, Collections.emptyList())); } in.endObject(); in.close(); } public void write(Map outcomes) { if (!recordResults) { return; } makeRoom(); File outputFile = getOutputFile(); try { mkdir.mkdirs(outputFile.getParentFile()); JsonWriter out = new JsonWriter(new FileWriter(outputFile)); out.setIndent(" "); out.beginObject(); for (Map.Entry entry : outcomes.entrySet()) { out.name(entry.getKey()); out.beginObject(); out.name("result"); out.value(entry.getValue().getResult().toString()); out.endObject(); } out.endObject(); out.close(); } catch (IOException e) { log.info("Failed to write outcomes to " + outputFile, e); } } private File[] getOutcomeFiles() { File[] result = resultsDir.listFiles(); if (result == null) { return new File[0]; } Arrays.sort(result, ORDER_BY_LAST_MODIFIED); return result; } private File getOutputFile() { SimpleDateFormat dateFormat = new SimpleDateFormat(FILE_NAME_DATE_FORMAT); dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); dateFormat.setLenient(true); String timestamp = dateFormat.format(date); return new File(resultsDir, timestamp + ".json"); } /** * Removes the oldest result files until only (PRESERVE_TOTAL - 1) remain. */ private void makeRoom() { File[] outcomeFiles = getOutcomeFiles(); for (int i = 0; i <= (outcomeFiles.length - PRESERVE_TOTAL); i++) { rm.file(outcomeFiles[i]); log.verbose("garbage collected results file: " + outcomeFiles[i]); } } }