/* * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 8201518 * @key randomness * @summary Ensure that randomized iteration order of unmodifiable sets * and maps is actually randomized. Must be run othervm so that * the per-VM-instance salt value differs. * @run main/othervm RandomizedIteration 0 * @run main/othervm RandomizedIteration 1 * @run main/othervm RandomizedIteration 2 * @run main/othervm RandomizedIteration 3 * @run main/othervm RandomizedIteration 4 * @run main/othervm RandomizedIteration verify 5 */ import java.io.IOException; import java.io.PrintStream; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.HashSet; import java.util.Map; import java.util.Set; import static java.util.stream.Collectors.toUnmodifiableMap; /** * Test of randomized iteration of unmodifiable sets and maps. * * Usage: RandomizedIteration n * - writes files suffixed with 'n' containing set elements and map keys * in iteration order * RandomizedIteration "verify" count * - reads files 0..count-1 and checks to ensure that their orders differ * * The idea is to generate several test files by invoking this test with an arg * of 0 through count-1. Then invoke the test once more with two args, the first being * the word "verify" and the second arg being the count. This will read all the generated * files and perform verification. * * The test is considered to pass if any of the runs result in different iteration * orders. The randomization is not actually very random, so over many runs there is * the possibility of a couple of the test files having the same order. That's ok, as * long as the iteration order is usually different. The test fails if *all* of the * iteration orders are the same. */ public class RandomizedIteration { /** * Generates a set and a map from the word array, and then writes * text files "set.#" and "map.#" containing the set elements and * map keys in iteration order. * * @param suffix number used for the file suffix */ static void writeFiles(int suffix) throws IOException { try (PrintStream setOut = new PrintStream("set." + suffix)) { Set.of(WORDS) .forEach(setOut::println); } try (PrintStream mapOut = new PrintStream("map." + suffix)) { var map = Map.ofEntries(Arrays.stream(WORDS) .map(word -> Map.entry(word, "")) .toArray(Map.Entry[]::new)); map.keySet() .forEach(mapOut::println); } } /** * Reads lines from each file derived from the prefix and index from 0..count-1 * into a list, computes its hashcode, and returns a set of those hashcodes. * The hashcode of the list is order sensitive, so the same lines in a different * order should have different hashcodes. * * @param prefix the file prefix * @param count the number of files to read * @return a set of hashcodes of each file */ static Set readFiles(String prefix, int count) throws IOException { Set hashes = new HashSet<>(); for (int suffix = 0; suffix < count; suffix++) { String name = prefix + suffix; int hash = Files.readAllLines(Paths.get(name)).hashCode(); System.out.println(name + ": " + hash); hashes.add(hash); } return hashes; } /** * Test main routine. * * @param args n | "verify" count * @throws IOException if an error occurred */ public static void main(String[] args) throws IOException { if ("verify".equals(args[0])) { int count = Integer.parseInt(args[1]); System.out.println("Verifying " + count + " files."); Set setHashes = readFiles("set.", count); Set mapHashes = readFiles("map.", count); if (setHashes.size() > 1 && mapHashes.size() > 1) { System.out.println("Passed: differing iteration orders were detected."); } else { throw new AssertionError("FAILED: iteration order not randomized!"); } } else { int suffix = Integer.parseInt(args[0]); System.out.println("Generating files: " + suffix); writeFiles(suffix); } } /** * List of 63 words of 22 or more letters from BSD /usr/share/dict/words. */ static final String[] WORDS = { "anatomicophysiological", "anthropomorphologically", "aquopentamminecobaltic", "blepharoconjunctivitis", "blepharosphincterectomy", "cholecystenterorrhaphy", "cholecystoduodenostomy", "choledochoduodenostomy", "counterexcommunication", "dacryocystoblennorrhea", "dacryocystosyringotomy", "deanthropomorphization", "duodenocholecystostomy", "electroencephalography", "electrotelethermometer", "epididymodeferentectomy", "formaldehydesulphoxylate", "formaldehydesulphoxylic", "gastroenteroanastomosis", "hematospectrophotometer", "hexamethylenetetramine", "hexanitrodiphenylamine", "historicocabbalistical", "hydropneumopericardium", "hyperconscientiousness", "laparocolpohysterotomy", "lymphangioendothelioma", "macracanthrorhynchiasis", "microcryptocrystalline", "naphthylaminesulphonic", "nonrepresentationalism", "omnirepresentativeness", "pancreaticoduodenostomy", "pancreaticogastrostomy", "pathologicohistological", "pathologicopsychological", "pericardiomediastinitis", "phenolsulphonephthalein", "philosophicohistorical", "philosophicotheological", "photochronographically", "photospectroheliograph", "pneumohydropericardium", "pneumoventriculography", "polioencephalomyelitis", "Prorhipidoglossomorpha", "Pseudolamellibranchiata", "pseudolamellibranchiate", "pseudomonocotyledonous", "pyopneumocholecystitis", "scientificogeographical", "scientificophilosophical", "scleroticochorioiditis", "stereophotomicrography", "tetraiodophenolphthalein", "theologicoastronomical", "theologicometaphysical", "thymolsulphonephthalein", "thyroparathyroidectomize", "thyroparathyroidectomy", "transubstantiationalist", "ureterocystanastomosis", "zoologicoarchaeologist" }; }