From e4d9fc811e0ef0eb9b097e06525a1183445d8d79 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Tue, 1 Mar 2022 03:49:18 +0000 Subject: [PATCH] 8282023: PropertiesStoreTest and StoreReproducibilityTest jtreg failures due to en_CA locale Reviewed-by: naoto, rriggs --- .../util/Properties/PropertiesStoreTest.java | 83 ++++++++++++++----- .../Properties/StoreReproducibilityTest.java | 18 ++-- 2 files changed, 72 insertions(+), 29 deletions(-) diff --git a/test/jdk/java/util/Properties/PropertiesStoreTest.java b/test/jdk/java/util/Properties/PropertiesStoreTest.java index da2be3b7cb5..ab58ea78903 100644 --- a/test/jdk/java/util/Properties/PropertiesStoreTest.java +++ b/test/jdk/java/util/Properties/PropertiesStoreTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -37,21 +37,28 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; +import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TreeSet; +import java.util.stream.Collectors; /* * @test * @summary tests the order in which the Properties.store() method writes out the properties - * @bug 8231640 - * @run testng PropertiesStoreTest + * @bug 8231640 8282023 + * @run testng/othervm PropertiesStoreTest */ public class PropertiesStoreTest { private static final String DATE_FORMAT_PATTERN = "EEE MMM dd HH:mm:ss zzz uuuu"; + // use a neutral locale, since when the date comment was written by Properties.store(...), + // it internally calls the Date.toString() which always writes in a locale insensitive manner + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN, Locale.ROOT); + private static final Locale PREV_LOCALE = Locale.getDefault(); @DataProvider(name = "propsProvider") private Object[][] createProps() { @@ -91,6 +98,26 @@ private Object[][] createProps() { }; } + /** + * Returns a {@link Locale} to use for testing + */ + @DataProvider(name = "localeProvider") + private Object[][] provideLocales() { + // pick a non-english locale for testing + Set locales = Arrays.stream(Locale.getAvailableLocales()) + .filter(l -> !l.getLanguage().isEmpty() && !l.getLanguage().equals("en")) + .limit(1) + .collect(Collectors.toCollection(HashSet::new)); + locales.add(Locale.getDefault()); // always test the default locale + locales.add(Locale.US); // guaranteed to be present + locales.add(Locale.ROOT); // guaranteed to be present + + // return the chosen locales + return locales.stream() + .map(m -> new Locale[] {m}) + .toArray(n -> new Object[n][0]); + } + /** * Tests that the {@link Properties#store(Writer, String)} API writes out the properties * in the expected order @@ -153,29 +180,45 @@ private void testStoreKeyOrder(final Properties props, final Path storedProps, /** * Tests that {@link Properties#store(Writer, String)} writes out a proper date comment */ - @Test - public void testStoreWriterDateComment() throws Exception { - final Properties props = new Properties(); - props.setProperty("a", "b"); - final Path tmpFile = Files.createTempFile("8231640", "props"); - try (final Writer writer = Files.newBufferedWriter(tmpFile)) { - props.store(writer, null); + @Test(dataProvider = "localeProvider") + public void testStoreWriterDateComment(final Locale testLocale) throws Exception { + // switch the default locale to the one being tested + Locale.setDefault(testLocale); + System.out.println("Using locale: " + testLocale + " for Properties#store(Writer) test"); + try { + final Properties props = new Properties(); + props.setProperty("a", "b"); + final Path tmpFile = Files.createTempFile("8231640", "props"); + try (final Writer writer = Files.newBufferedWriter(tmpFile)) { + props.store(writer, null); + } + testDateComment(tmpFile); + } finally { + // reset to the previous one + Locale.setDefault(PREV_LOCALE); } - testDateComment(tmpFile); } /** * Tests that {@link Properties#store(OutputStream, String)} writes out a proper date comment */ - @Test - public void testStoreOutputStreamDateComment() throws Exception { - final Properties props = new Properties(); - props.setProperty("a", "b"); - final Path tmpFile = Files.createTempFile("8231640", "props"); - try (final Writer writer = Files.newBufferedWriter(tmpFile)) { - props.store(writer, null); + @Test(dataProvider = "localeProvider") + public void testStoreOutputStreamDateComment(final Locale testLocale) throws Exception { + // switch the default locale to the one being tested + Locale.setDefault(testLocale); + System.out.println("Using locale: " + testLocale + " for Properties#store(OutputStream) test"); + try { + final Properties props = new Properties(); + props.setProperty("a", "b"); + final Path tmpFile = Files.createTempFile("8231640", "props"); + try (final Writer writer = Files.newBufferedWriter(tmpFile)) { + props.store(writer, null); + } + testDateComment(tmpFile); + } finally { + // reset to the previous one + Locale.setDefault(PREV_LOCALE); } - testDateComment(tmpFile); } /** @@ -199,7 +242,7 @@ private void testDateComment(Path file) throws Exception { Assert.fail("No comment line found in the stored properties file " + file); } try { - DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN).parse(comment); + FORMATTER.parse(comment); } catch (DateTimeParseException pe) { Assert.fail("Unexpected date comment: " + comment, pe); } diff --git a/test/jdk/java/util/Properties/StoreReproducibilityTest.java b/test/jdk/java/util/Properties/StoreReproducibilityTest.java index 5f865c29328..c4b1853a1d6 100644 --- a/test/jdk/java/util/Properties/StoreReproducibilityTest.java +++ b/test/jdk/java/util/Properties/StoreReproducibilityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -44,7 +44,7 @@ /* * @test * @summary Tests that the Properties.store() APIs generate output that is reproducible - * @bug 8231640 + * @bug 8231640 8282023 * @library /test/lib * @run driver StoreReproducibilityTest */ @@ -52,8 +52,8 @@ public class StoreReproducibilityTest { private static final String DATE_FORMAT_PATTERN = "EEE MMM dd HH:mm:ss zzz uuuu"; private static final String SYS_PROP_JAVA_PROPERTIES_DATE = "java.properties.date"; - private static final DateTimeFormatter reproducibleDateTimeFormatter = DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN) - .withLocale(Locale.ROOT).withZone(ZoneOffset.UTC); + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN, Locale.ROOT) + .withZone(ZoneOffset.UTC); public static void main(final String[] args) throws Exception { // no security manager enabled @@ -88,7 +88,7 @@ public static void main(final String[] args) throws Exception { */ private static void testWithoutSecurityManager() throws Exception { final List storedFiles = new ArrayList<>(); - final String sysPropVal = reproducibleDateTimeFormatter.format(Instant.ofEpochSecond(243535322)); + final String sysPropVal = FORMATTER.format(Instant.ofEpochSecond(243535322)); for (int i = 0; i < 5; i++) { final Path tmpFile = Files.createTempFile("8231640", ".props"); storedFiles.add(tmpFile); @@ -130,7 +130,7 @@ private static void testWithSecMgrExplicitPermission() throws Exception { }; """)); final List storedFiles = new ArrayList<>(); - final String sysPropVal = reproducibleDateTimeFormatter.format(Instant.ofEpochSecond(1234342423)); + final String sysPropVal = FORMATTER.format(Instant.ofEpochSecond(1234342423)); for (int i = 0; i < 5; i++) { final Path tmpFile = Files.createTempFile("8231640", ".props"); storedFiles.add(tmpFile); @@ -174,7 +174,7 @@ private static void testWithSecMgrNoSpecificPermission() throws Exception { }; """)); final List storedFiles = new ArrayList<>(); - final String sysPropVal = reproducibleDateTimeFormatter.format(Instant.ofEpochSecond(1234342423)); + final String sysPropVal = FORMATTER.format(Instant.ofEpochSecond(1234342423)); for (int i = 0; i < 5; i++) { final Path tmpFile = Files.createTempFile("8231640", ".props"); storedFiles.add(tmpFile); @@ -425,10 +425,10 @@ private static void assertCurrentDate(final Path destFile, final Date date) thro System.out.println("Found date comment " + dateComment + " in file " + destFile); final Date parsedDate; try { - Instant instant = Instant.from(DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN).parse(dateComment)); + Instant instant = Instant.from(FORMATTER.parse(dateComment)); parsedDate = new Date(instant.toEpochMilli()); } catch (DateTimeParseException pe) { - throw new RuntimeException("Unexpected date " + dateComment + " in stored properties " + destFile); + throw new RuntimeException("Unexpected date " + dateComment + " in stored properties " + destFile, pe); } if (!parsedDate.after(date)) { throw new RuntimeException("Expected date comment " + dateComment + " to be after " + date