blob: f3fb494821f5d1e81c5d6153b771207ed3b557af [file] [log] [blame]
/*
* 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<Integer> readFiles(String prefix, int count) throws IOException {
Set<Integer> 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<Integer> setHashes = readFiles("set.", count);
Set<Integer> 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"
};
}