1 /*
   2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation. Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  */
  24 package test.javaclient.shared.screenshots;
  25 
  26 import com.sun.prism.GraphicsPipeline;
  27 import java.io.File;
  28 import java.io.IOException;
  29 import java.nio.file.DirectoryStream;
  30 import java.nio.file.Files;
  31 import java.nio.file.Path;
  32 import java.nio.file.Paths;
  33 import java.util.ArrayList;
  34 import java.util.Collections;
  35 import java.util.List;
  36 
  37 /**
  38  *
  39  * @author andrey.rusakov@oracle.com
  40  */
  41 public class GoldenImageManager {
  42 
  43     private static final String IMG_VERSION = "-\\d+";
  44     private static final String IMG_FOLDER = "images-svn";
  45 
  46     private static File getImagesRoot() throws IOException {
  47         return new File("../", IMG_FOLDER).getCanonicalFile();
  48     }
  49 
  50     private static String getSuiteName() throws IOException {
  51         return new File(".").getCanonicalFile().getName();
  52     }
  53 
  54     //Requires -XaddExports:javafx.graphics/com.sun.prism=ALL-UNNAMED to work in JDK9
  55     private static String getRenderingMode() {
  56         GraphicsPipeline pipeline = com.sun.prism.GraphicsPipeline.getPipeline();
  57         return pipeline.getClass().getName().endsWith("J2DPipeline")
  58                 || pipeline.getClass().getName().endsWith("SWPipeline") ? "j2d" : "prism";
  59     }
  60 
  61     private static String getPlatformAlias() {
  62         String os = System.getProperty("os.name").toLowerCase();
  63         String version = System.getProperty("os.version").toLowerCase();
  64         if (os.contains("win")) {
  65             if (version.startsWith("5.")) {
  66                 return "xp";
  67             } else if (version.startsWith("6.2")
  68                     || version.startsWith("6.3")) {
  69                 return "eight";
  70             } else if (version.startsWith("10.")) {
  71                 return "ten";
  72             }
  73 
  74         } else if (os.contains("mac")) {
  75             return "mac";
  76         } else if (os.contains("linux") || os.contains("ubuntu")) {
  77             return "linux";
  78         }
  79         return "";
  80     }
  81 
  82     public static String getDiffPath(String goldenPath) {
  83         String relativeGoldenPath = goldenPath.substring(goldenPath.indexOf(IMG_FOLDER) +
  84                 IMG_FOLDER.length());
  85         String goldenName = relativeGoldenPath.replace(File.pathSeparator, "_");
  86         String diffName = goldenName.substring(0, goldenName.lastIndexOf(".") - 1) + "-diff";
  87         return getScreenshotPath(diffName);
  88     }
  89 
  90     public static String getScreenshotPath(String testName) {
  91         return getGoldenPath(testName, "png");
  92     }
  93 
  94     public static String getGoldenPath(String testName, String extension) {
  95         String imagesOutputPath = System.getProperty("imageutils.outputpath");
  96         if (imagesOutputPath == null) {
  97             imagesOutputPath = Paths.get(".", "build").toString();
  98         }
  99         try {
 100             return new File(imagesOutputPath, testName + "." + extension).getCanonicalFile().toString();
 101         } catch (IOException ex) {
 102             System.err.println("Failed to get screenshot path: " + ex.getMessage());
 103         }
 104         return null;
 105     }
 106 
 107     public static List<String> getTestImages(String testName) {
 108         return getTestImages(testName, ".png");
 109     }
 110 
 111     /**
 112      * Retrieves images from reference image folder according to suffix (usually test name) and
 113      * postfix (usually file extension).
 114      * Files should have name that matches "suffix[-number-]postfix", e.g: "SomeTestName.png",
 115      * "SomeTestName-1.png"... "SomeTestName-NUMBER.png".  Method searches for all matching files
 116      * in "TestsuiteName/RenderingMode/Platform", "TestsuiteName/RenderingMode/" and
 117      * "TestsuiteName/".
 118      *
 119      * @param suffix filename suffix, usually test name.
 120      * @param postfix filename prefix, usually file extension.
 121      * @return Full paths to all matching files or empty list if no files matched.
 122      */
 123     public static List<String> getTestImages(String suffix, String postfix) {
 124         File imageRoot;
 125         String suiteName;
 126         try {
 127             imageRoot = getImagesRoot();
 128                     System.out.println(imageRoot.getCanonicalPath());
 129         } catch (IOException ex) {
 130             System.err.printf("Failed to get golden images folder path: %s\n", ex.getMessage());
 131             return Collections.emptyList();
 132         }
 133         try {
 134             suiteName = getSuiteName();
 135         } catch (IOException ex) {
 136             System.err.printf("Failed to get testsuite name: %s\n", ex.getMessage());
 137             return Collections.emptyList();
 138         }
 139         File currentDirectory = new File(imageRoot,
 140                 Paths.get(suiteName, getRenderingMode(), getPlatformAlias()).toString());
 141         List<String> goldenVariants = new ArrayList<>();
 142         while (!currentDirectory.equals(imageRoot)) {
 143             try (DirectoryStream<Path> stream = Files.newDirectoryStream(currentDirectory.toPath())) {
 144                 stream.forEach(path -> {
 145                     String name = path.getFileName().toString();
 146                     if (name.startsWith(suffix) && name.endsWith(postfix)) {
 147                         String imageVersion = name.substring(suffix.length(), name.lastIndexOf(postfix));
 148                         if (imageVersion.isEmpty() || imageVersion.matches(IMG_VERSION)) {
 149                             goldenVariants.add(path.toAbsolutePath().toString());
 150                         }
 151                     }
 152                 });
 153             } catch (IOException ex) {
 154                 System.err.printf("Failed to enumerate golden images at %s: %s\n",
 155                         currentDirectory, ex);
 156             }
 157             currentDirectory = currentDirectory.getParentFile();
 158         }
 159         System.out.printf("Found %d acceptable golden image(s)\n", goldenVariants.size());
 160         goldenVariants.forEach(System.out::println);
 161         return goldenVariants;
 162     }
 163 }