Java tutorial
/* * Copyright (C) 2015-2016 NS Solutions Corporation * * 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 com.htmlhifive.pitalium.core.io; import java.awt.image.BufferedImage; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Map; import javax.imageio.ImageIO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.core.type.TypeReference; import com.google.common.base.Strings; import com.htmlhifive.pitalium.common.exception.JSONException; import com.htmlhifive.pitalium.common.exception.TestRuntimeException; import com.htmlhifive.pitalium.common.util.JSONUtils; import com.htmlhifive.pitalium.core.config.FilePersisterConfig; import com.htmlhifive.pitalium.core.config.PtlTestConfig; import com.htmlhifive.pitalium.core.model.ScreenshotResult; import com.htmlhifive.pitalium.core.model.TargetResult; import com.htmlhifive.pitalium.core.model.TestResult; import com.htmlhifive.pitalium.core.selenium.PtlCapabilities; import com.htmlhifive.pitalium.image.model.PersistedScreenshotImage; /** * ???????Persister */ public class FilePersister implements Persister { /** * ExpectedId????? */ public static final String DEFAULT_EXPECTED_IDS_FILE_NAME = "currentExpectedIds.json"; /** * ??????? */ public static final String DEFAULT_TEST_RESULT_FILE_NAME = "result.json"; private static final Logger LOG = LoggerFactory.getLogger(FilePersister.class); private static final TypeReference<List<TargetResult>> TARGET_RESULTS_REFERENCE = new TypeReference<List<TargetResult>>() { }; private static final TypeReference<Map<String, Map<String, String>>> EXPECTED_IDS_REFERENCE = new TypeReference<Map<String, Map<String, String>>>() { }; private final FilePersisterConfig config; private final FileNameFormatter targetResultFileNameFormatter; private final FileNameFormatter screenshotFileNameFormatter; private final FileNameFormatter diffFileNameFormatter; /** * */ public FilePersister() { this(PtlTestConfig.getInstance().getPersisterConfig().getFile()); } /** * * * @param config ? */ public FilePersister(FilePersisterConfig config) { this.config = config; validateConfig(); targetResultFileNameFormatter = new FileNameFormatter(config.getTargetResultFileName()); screenshotFileNameFormatter = new FileNameFormatter(config.getScreenshotFileName()); diffFileNameFormatter = new FileNameFormatter(config.getDiffFileName()); } /** * ????? */ private void validateConfig() { if (Strings.isNullOrEmpty(config.getResultDirectory())) { throw new TestRuntimeException("ResultDirectory cannot be empty."); } if (Strings.isNullOrEmpty(config.getTargetResultFileName())) { throw new TestRuntimeException("TargetResultFileName cannot be empty."); } if (Strings.isNullOrEmpty(config.getScreenshotFileName())) { throw new TestRuntimeException("ScreenshotFileName cannot be empty."); } if (Strings.isNullOrEmpty(config.getDiffFileName())) { throw new TestRuntimeException("DiffFileName cannot be empty."); } if (config.getScreenshotFileName().equals(config.getTargetResultFileName()) || config.getScreenshotFileName().equals(config.getDiffFileName())) { throw new TestRuntimeException( "TargetResultFileName, ScreenshotFileName and DiffFileName must be different value."); } } @Override public void saveDiffImage(PersistMetadata metadata, BufferedImage image) { File file = checkParentFileAvailable(getDiffImageFile(metadata)); LOG.debug("[Save diff image] ({})", file); LOG.trace("[Save diff image] ({})]", metadata); try { ImageIO.write(image, "png", file); } catch (IOException e) { LOG.debug("Failed to save diff image.", e); throw new TestRuntimeException(e); } } @Override public BufferedImage loadDiffImage(PersistMetadata metadata) { File file = checkFileAvailable(getDiffImageFile(metadata)); LOG.debug("[Load diff image] ({})", file); LOG.trace("[Load diff image] ({})", metadata); try { return ImageIO.read(file); } catch (IOException e) { LOG.debug("Failed to load diff image.", e); throw new ResourceUnavailableException(e); } } @Override public void saveScreenshot(PersistMetadata metadata, BufferedImage image) { File file = checkParentFileAvailable(getScreenshotImageFile(metadata)); LOG.debug("[Save screenshot] ({})", file); LOG.trace("[Save screenshot] ({})", metadata); try { ImageIO.write(image, "png", file); } catch (IOException e) { LOG.debug("Failed to save screenshot.", e); throw new TestRuntimeException(e); } } @Override public InputStream getImageStream(PersistMetadata metadata) { File file = checkFileAvailable(getScreenshotImageFile(metadata)); LOG.debug("[Load image stream] ({})", file); LOG.trace("[Load image stream] ({})", metadata); try { return new BufferedInputStream(new FileInputStream(file)); } catch (FileNotFoundException e) { LOG.debug("Failed to load image stream.", e); throw new ResourceUnavailableException(String.format(Locale.US, "File %s not found", file)); } } @Override public BufferedImage loadScreenshot(PersistMetadata metadata) { File file = checkFileAvailable(getScreenshotImageFile(metadata)); LOG.debug("[Load screenshot] ({})", file); LOG.trace("[Load screenshot] ({})", metadata); try { return ImageIO.read(file); } catch (IOException e) { LOG.debug("Failed to load screenshot.", e); throw new ResourceUnavailableException(e); } } @Override public void saveTargetResults(PersistMetadata metadata, List<TargetResult> results) { File file = checkParentFileAvailable(getTargetResultsFile(metadata)); LOG.debug("[Save TargetResults] ({})", file); LOG.trace("[Save TargetResults] (results: {}; meta: {})", results, metadata); try { JSONUtils.writeValueWithIndent(file, results); } catch (JSONException e) { LOG.debug("Failed to save TargetResults.", e); throw e; } } @Override public List<TargetResult> loadTargetResults(final PersistMetadata metadata) { File file = checkFileAvailable(getTargetResultsFile(metadata)); LOG.debug("[Load TargetResults] ({})", file); LOG.trace("[Load TargetResults] ({})", metadata); try { List<TargetResult> targetResults = JSONUtils.readValue(file, TARGET_RESULTS_REFERENCE); LOG.trace("[Load TargetResults] => {}", targetResults); // Build with screenshot image return Collections.unmodifiableList(fillScreenshotImageProperty(targetResults, metadata)); } catch (JSONException e) { LOG.debug("Failed to load TargetResults.", e); throw e; } catch (Exception e) { LOG.debug("Failed to fill TargetResults object.", e); throw e; } } /** * {@list TargetResult}??????? * * @param targetResults ?{@list TargetResult} * @param metadata ? * @return ?{@list TargetResult}? */ private List<TargetResult> fillScreenshotImageProperty(List<TargetResult> targetResults, PersistMetadata metadata) { List<TargetResult> results = new ArrayList<TargetResult>(targetResults.size()); for (TargetResult targetResult : targetResults) { PersistMetadata imageMetadata; if (targetResult.getTarget().getSelector() == null) { imageMetadata = new PersistMetadata(metadata.getExpectedId(), metadata.getClassName(), metadata.getMethodName(), metadata.getScreenshotId(), null, targetResult.getTarget().getRectangle(), metadata.getCapabilities()); } else { imageMetadata = new PersistMetadata(metadata.getExpectedId(), metadata.getClassName(), metadata.getMethodName(), metadata.getScreenshotId(), targetResult.getTarget().getSelector(), null, metadata.getCapabilities()); } results.add( new TargetResult(targetResult.getResult(), targetResult.getTarget(), targetResult.getExcludes(), targetResult.isMoveTarget(), targetResult.getHiddenElementSelectors(), new PersistedScreenshotImage(this, imageMetadata), targetResult.getOptions())); } return results; } @Override public void saveTestResult(PersistMetadata metadata, TestResult result) { File file = checkParentFileAvailable(getTestResultFile(metadata)); LOG.debug("[Save TestResult] ({})", file); LOG.trace("[Save TestResult] (result: {}; meta: {})", result, metadata); try { JSONUtils.writeValueWithIndent(file, result); } catch (JSONException e) { LOG.debug("Failed to save TestResult.", e); throw e; } } @Override public TestResult loadTestResult(PersistMetadata metadata) { File file = checkFileAvailable(getTestResultFile(metadata)); LOG.debug("[Load TestResult] ({})", file); LOG.trace("[Load TestResult] ({})", metadata); try { TestResult testResult = JSONUtils.readValue(file, TestResult.class); LOG.trace("[Load TestResult] => {}", testResult); // Build with screenshot image List<ScreenshotResult> results = new ArrayList<ScreenshotResult>( testResult.getScreenshotResults().size()); for (ScreenshotResult r : testResult.getScreenshotResults()) { PersistMetadata m = new PersistMetadata(metadata.getExpectedId(), metadata.getClassName(), r.getTestMethod(), r.getScreenshotId(), new PtlCapabilities(r.getCapabilities())); List<TargetResult> targetResults = fillScreenshotImageProperty(r.getTargetResults(), m); results.add(new ScreenshotResult(r.getScreenshotId(), r.getResult(), r.getExpectedId(), targetResults, r.getTestClass(), r.getTestMethod(), r.getCapabilities(), null)); } return new TestResult(testResult.getResultId(), testResult.getResult(), results); } catch (JSONException e) { LOG.debug("Failed to load TestResult.", e); throw e; } catch (Exception e) { LOG.debug("Failed to fill TestResult object.", e); throw e; } } @Override public void saveExpectedIds(Map<String, Map<String, String>> expectedIds) { File file = checkParentFileAvailable(getExpectedIdsFile()); LOG.debug("[Save ExpectedIds] ({})", file); LOG.trace("[Save ExpectedIds] ({})", expectedIds); try { JSONUtils.writeValueWithIndent(file, expectedIds); } catch (JSONException e) { LOG.debug("Failed to save ExpectedIds.", e); throw e; } } @Override public Map<String, Map<String, String>> loadExpectedIds() { File file = checkFileAvailable(getExpectedIdsFile()); LOG.debug("[Load ExpectedIds] ({})", file); try { Map<String, Map<String, String>> ids = JSONUtils.readValue(file, EXPECTED_IDS_REFERENCE); LOG.trace("[Load ExpectedIds] => {}", ids); return ids; } catch (JSONException e) { LOG.debug("Failed to load ExpectedIds.", e); throw e; } } /** * ??????????????<br> * ????????? * * @param file ? * @return ? */ private File checkParentFileAvailable(File file) { File parent = file.getParentFile(); if (!parent.exists() && !parent.mkdirs()) { throw new TestRuntimeException(String.format(Locale.US, "mkdir error \"%s\"", parent)); } if (!parent.canWrite()) { throw new TestRuntimeException(String.format(Locale.US, "No write permission at \"%s\"", parent)); } return file; } /** * ????????????? * * @param file ? * @return ? */ private File checkFileAvailable(File file) { if (!file.exists()) { throw new ResourceUnavailableException(String.format(Locale.UK, "File \"%s\" not found", file)); } if (!file.canRead()) { throw new ResourceUnavailableException(String.format(Locale.UK, "File \"%s\" cannot read", file)); } return file; } /** * ??????? * * @return ???? */ public File getResultDirectoryFile() { return new File(config.getResultDirectory()); } /** * ?ID??????? * * @return ?ID? */ public File getExpectedIdsFile() { return new File(config.getResultDirectory(), getExpectedIdsFileName()); } /** * ?????? * * @param metadata * @return ?? */ public File getTestResultFile(PersistMetadata metadata) { return new File(getFilePath(metadata, getTestResultFileName())); } /** * ????????? * * @param metadata * @return ?? */ public File getTargetResultsFile(PersistMetadata metadata) { return new File(getFilePath(metadata, getTargetResultsFileName(metadata))); } /** * ??????? * * @param metadata * @return ?? */ public File getScreenshotImageFile(PersistMetadata metadata) { return new File(getFilePath(metadata, getScreenshotImageFileName(metadata))); } /** * ?????? * * @param metadata * @return ?? */ public File getDiffImageFile(PersistMetadata metadata) { return new File(getFilePath(metadata, getDiffImageFileName(metadata))); } /** * ?ID????????? * * @return ???? */ public String getExpectedIdsFileName() { return DEFAULT_EXPECTED_IDS_FILE_NAME; } /** * ??????????? * * @return ???? */ public String getTestResultFileName() { return DEFAULT_TEST_RESULT_FILE_NAME; } /** * ??????????? * * @param metadata * @return ???? */ public String getTargetResultsFileName(PersistMetadata metadata) { return targetResultFileNameFormatter.format(metadata); } /** * ???????? * * @param metadata * @return ???? */ public String getScreenshotImageFileName(PersistMetadata metadata) { return screenshotFileNameFormatter.format(metadata); } /** * ???????? * * @param metadata * @return ???? */ public String getDiffImageFileName(PersistMetadata metadata) { return diffFileNameFormatter.format(metadata); } /** * ????????? * * @param metadata * @param fileName ?? * @return ? */ protected String getFilePath(PersistMetadata metadata, String fileName) { return config.getResultDirectory() + File.separator + metadata.getExpectedId() + File.separator + File.separator + metadata.getClassName() + File.separator + fileName; } }