diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-01-04 20:03:24 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-01-04 20:03:24 +0000 |
commit | 0a310095af0fa59a8a813c9b8d3f1c0ae615ad09 (patch) | |
tree | ab8add0e1979a4e9d6d99310a6450db084168da9 | |
parent | 2a7ff2090a040021a9b64c553893930dd9b253d0 (diff) | |
parent | 5e1bee230f5fdb38b09b4e07f197684c76ec4c85 (diff) | |
download | libcore-aml_ips_341510000.tar.gz |
Snap for 11273583 from 5e1bee230f5fdb38b09b4e07f197684c76ec4c85 to mainline-ipsec-releaseaml_ips_341510000
Change-Id: Ibf1f16d68757085dac4545433083d736ffa923ac
170 files changed, 23507 insertions, 1039 deletions
diff --git a/JavaLibrary.bp b/JavaLibrary.bp index 095e67ef47c..4b289bbf407 100644 --- a/JavaLibrary.bp +++ b/JavaLibrary.bp @@ -533,6 +533,7 @@ java_library_static { "//frameworks/base/location/tests/locationtests", "//frameworks/base/core/tests/coretests", "//frameworks/base/wifi/tests", + "//libcore/ojluni/src/test", "//libcore/luni/src/test/java9compatibility", "//packages/modules/Wifi/framework/tests", ], @@ -541,8 +542,10 @@ java_library_static { "dalvik/test-rules/src/main/**/*.java", "test-rules/src/main/**/*.java", ], - static_libs: ["junit"], - + static_libs: [ + "junit", + "platform-test-annotations", + ], sdk_version: "none", system_modules: "core-all-system-modules", } diff --git a/api/current.txt b/api/current.txt index a61a7234788..d459f728340 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2880,7 +2880,7 @@ package java.lang { } public enum Character.UnicodeScript { - method @NonNull public static java.lang.Character.UnicodeScript forName(@NonNull String); + method @NonNull public static final java.lang.Character.UnicodeScript forName(@NonNull String); method @NonNull public static java.lang.Character.UnicodeScript of(int); enum_constant public static final java.lang.Character.UnicodeScript ADLAM; enum_constant public static final java.lang.Character.UnicodeScript AHOM; @@ -3095,8 +3095,10 @@ package java.lang { method @Nullable public Object[] getSigners(); method @NonNull public String getSimpleName(); method @Nullable public Class<? super T> getSuperclass(); + method @NonNull public String getTypeName(); method @NonNull public java.lang.reflect.TypeVariable<java.lang.Class<T>>[] getTypeParameters(); method public boolean isAnnotation(); + method public boolean isAnnotationPresent(@NonNull Class<? extends java.lang.annotation.Annotation>); method public boolean isAnonymousClass(); method public boolean isArray(); method public boolean isAssignableFrom(@NonNull Class<?>); @@ -3695,6 +3697,7 @@ package java.lang { method public String getSpecificationTitle(); method public String getSpecificationVendor(); method public String getSpecificationVersion(); + method public boolean isAnnotationPresent(Class<? extends java.lang.annotation.Annotation>); method public boolean isCompatibleWith(String) throws java.lang.NumberFormatException; method public boolean isSealed(); method public boolean isSealed(java.net.URL); @@ -4046,9 +4049,11 @@ package java.lang { ctor public String(@NonNull StringBuffer); ctor public String(@NonNull StringBuilder); method public char charAt(int); + method @NonNull public java.util.stream.IntStream chars(); method public int codePointAt(int); method public int codePointBefore(int); method public int codePointCount(int, int); + method @NonNull public java.util.stream.IntStream codePoints(); method public int compareTo(@NonNull String); method public int compareToIgnoreCase(@NonNull String); method @NonNull public String concat(@NonNull String); @@ -4106,6 +4111,7 @@ package java.lang { method public char[] toCharArray(); method @NonNull public String toLowerCase(@NonNull java.util.Locale); method @NonNull public String toLowerCase(); + method @NonNull public String toString(); method @NonNull public String toUpperCase(@NonNull java.util.Locale); method @NonNull public String toUpperCase(); method public <R> R transform(@NonNull java.util.function.Function<? super java.lang.String,? extends R>); @@ -4144,9 +4150,11 @@ package java.lang { method @NonNull public StringBuffer appendCodePoint(int); method public int capacity(); method public char charAt(int); + method @NonNull public java.util.stream.IntStream chars(); method public int codePointAt(int); method public int codePointBefore(int); method public int codePointCount(int, int); + method @NonNull public java.util.stream.IntStream codePoints(); method public int compareTo(@NonNull StringBuffer); method @NonNull public StringBuffer delete(int, int); method @NonNull public StringBuffer deleteCharAt(int); @@ -4177,6 +4185,7 @@ package java.lang { method @NonNull public CharSequence subSequence(int, int); method @NonNull public String substring(int); method @NonNull public String substring(int, int); + method @NonNull public String toString(); method public void trimToSize(); } @@ -4201,9 +4210,11 @@ package java.lang { method @NonNull public StringBuilder appendCodePoint(int); method public int capacity(); method public char charAt(int); + method @NonNull public java.util.stream.IntStream chars(); method public int codePointAt(int); method public int codePointBefore(int); method public int codePointCount(int, int); + method @NonNull public java.util.stream.IntStream codePoints(); method public int compareTo(@NonNull StringBuilder); method @NonNull public StringBuilder delete(int, int); method @NonNull public StringBuilder deleteCharAt(int); @@ -4234,6 +4245,7 @@ package java.lang { method @NonNull public CharSequence subSequence(int, int); method @NonNull public String substring(int); method @NonNull public String substring(int, int); + method @NonNull public String toString(); method public void trimToSize(); } @@ -4561,8 +4573,8 @@ package java.lang.invoke { method public java.lang.invoke.MethodHandle asType(java.lang.invoke.MethodType); method public java.lang.invoke.MethodHandle asVarargsCollector(Class<?>); method public java.lang.invoke.MethodHandle bindTo(Object); - method public final Object invoke(java.lang.Object...) throws java.lang.Throwable; - method public final Object invokeExact(java.lang.Object...) throws java.lang.Throwable; + method public final native Object invoke(java.lang.Object...) throws java.lang.Throwable; + method public final native Object invokeExact(java.lang.Object...) throws java.lang.Throwable; method public Object invokeWithArguments(java.lang.Object...) throws java.lang.Throwable; method public Object invokeWithArguments(java.util.List<?>) throws java.lang.Throwable; method public boolean isVarargsCollector(); @@ -4735,45 +4747,45 @@ package java.lang.invoke { public abstract class VarHandle { method public final java.lang.invoke.MethodType accessModeType(java.lang.invoke.VarHandle.AccessMode); method public static void acquireFence(); - method public final Object compareAndExchange(java.lang.Object...); - method public final Object compareAndExchangeAcquire(java.lang.Object...); - method public final Object compareAndExchangeRelease(java.lang.Object...); - method public final boolean compareAndSet(java.lang.Object...); + method public final native Object compareAndExchange(java.lang.Object...); + method public final native Object compareAndExchangeAcquire(java.lang.Object...); + method public final native Object compareAndExchangeRelease(java.lang.Object...); + method public final native boolean compareAndSet(java.lang.Object...); method public final java.util.List<java.lang.Class<?>> coordinateTypes(); method public static void fullFence(); - method public final Object get(java.lang.Object...); - method public final Object getAcquire(java.lang.Object...); - method public final Object getAndAdd(java.lang.Object...); - method public final Object getAndAddAcquire(java.lang.Object...); - method public final Object getAndAddRelease(java.lang.Object...); - method public final Object getAndBitwiseAnd(java.lang.Object...); - method public final Object getAndBitwiseAndAcquire(java.lang.Object...); - method public final Object getAndBitwiseAndRelease(java.lang.Object...); - method public final Object getAndBitwiseOr(java.lang.Object...); - method public final Object getAndBitwiseOrAcquire(java.lang.Object...); - method public final Object getAndBitwiseOrRelease(java.lang.Object...); - method public final Object getAndBitwiseXor(java.lang.Object...); - method public final Object getAndBitwiseXorAcquire(java.lang.Object...); - method public final Object getAndBitwiseXorRelease(java.lang.Object...); - method public final Object getAndSet(java.lang.Object...); - method public final Object getAndSetAcquire(java.lang.Object...); - method public final Object getAndSetRelease(java.lang.Object...); - method public final Object getOpaque(java.lang.Object...); - method public final Object getVolatile(java.lang.Object...); + method public final native Object get(java.lang.Object...); + method public final native Object getAcquire(java.lang.Object...); + method public final native Object getAndAdd(java.lang.Object...); + method public final native Object getAndAddAcquire(java.lang.Object...); + method public final native Object getAndAddRelease(java.lang.Object...); + method public final native Object getAndBitwiseAnd(java.lang.Object...); + method public final native Object getAndBitwiseAndAcquire(java.lang.Object...); + method public final native Object getAndBitwiseAndRelease(java.lang.Object...); + method public final native Object getAndBitwiseOr(java.lang.Object...); + method public final native Object getAndBitwiseOrAcquire(java.lang.Object...); + method public final native Object getAndBitwiseOrRelease(java.lang.Object...); + method public final native Object getAndBitwiseXor(java.lang.Object...); + method public final native Object getAndBitwiseXorAcquire(java.lang.Object...); + method public final native Object getAndBitwiseXorRelease(java.lang.Object...); + method public final native Object getAndSet(java.lang.Object...); + method public final native Object getAndSetAcquire(java.lang.Object...); + method public final native Object getAndSetRelease(java.lang.Object...); + method public final native Object getOpaque(java.lang.Object...); + method public final native Object getVolatile(java.lang.Object...); method public final boolean isAccessModeSupported(java.lang.invoke.VarHandle.AccessMode); method public static void loadLoadFence(); method public static void releaseFence(); - method public final void set(java.lang.Object...); - method public final void setOpaque(java.lang.Object...); - method public final void setRelease(java.lang.Object...); - method public final void setVolatile(java.lang.Object...); + method public final native void set(java.lang.Object...); + method public final native void setOpaque(java.lang.Object...); + method public final native void setRelease(java.lang.Object...); + method public final native void setVolatile(java.lang.Object...); method public static void storeStoreFence(); method public final java.lang.invoke.MethodHandle toMethodHandle(java.lang.invoke.VarHandle.AccessMode); method public final Class<?> varType(); - method public final boolean weakCompareAndSet(java.lang.Object...); - method public final boolean weakCompareAndSetAcquire(java.lang.Object...); - method public final boolean weakCompareAndSetPlain(java.lang.Object...); - method public final boolean weakCompareAndSetRelease(java.lang.Object...); + method public final native boolean weakCompareAndSet(java.lang.Object...); + method public final native boolean weakCompareAndSetAcquire(java.lang.Object...); + method public final native boolean weakCompareAndSetPlain(java.lang.Object...); + method public final native boolean weakCompareAndSetRelease(java.lang.Object...); } public enum VarHandle.AccessMode { @@ -4877,8 +4889,12 @@ package java.lang.reflect { ctor protected AccessibleObject(); method @Nullable public <T extends java.lang.annotation.Annotation> T getAnnotation(@NonNull Class<T>); method @NonNull public java.lang.annotation.Annotation[] getAnnotations(); + method public <T extends java.lang.annotation.Annotation> T[] getAnnotationsByType(@NonNull Class<T>); + method @Nullable public <T extends java.lang.annotation.Annotation> T getDeclaredAnnotation(@NonNull Class<T>); method @NonNull public java.lang.annotation.Annotation[] getDeclaredAnnotations(); + method public <T extends java.lang.annotation.Annotation> T[] getDeclaredAnnotationsByType(@NonNull Class<T>); method public boolean isAccessible(); + method public boolean isAnnotationPresent(@NonNull Class<? extends java.lang.annotation.Annotation>); method public static void setAccessible(java.lang.reflect.AccessibleObject[], boolean) throws java.lang.SecurityException; method public void setAccessible(boolean) throws java.lang.SecurityException; } @@ -5070,7 +5086,10 @@ package java.lang.reflect { public final class Parameter implements java.lang.reflect.AnnotatedElement { method @Nullable public <T extends java.lang.annotation.Annotation> T getAnnotation(@NonNull Class<T>); method @NonNull public java.lang.annotation.Annotation[] getAnnotations(); + method public <T extends java.lang.annotation.Annotation> T[] getAnnotationsByType(@NonNull Class<T>); + method @Nullable public <T extends java.lang.annotation.Annotation> T getDeclaredAnnotation(@NonNull Class<T>); method @NonNull public java.lang.annotation.Annotation[] getDeclaredAnnotations(); + method public <T extends java.lang.annotation.Annotation> T[] getDeclaredAnnotationsByType(@NonNull Class<T>); method @NonNull public java.lang.reflect.Executable getDeclaringExecutable(); method public int getModifiers(); method @NonNull public String getName(); @@ -6289,6 +6308,7 @@ package java.nio { method public final int arrayOffset(); method public abstract java.nio.CharBuffer asReadOnlyBuffer(); method public final char charAt(int); + method public java.util.stream.IntStream chars(); method public abstract java.nio.CharBuffer compact(); method public int compareTo(java.nio.CharBuffer); method public abstract java.nio.CharBuffer duplicate(); @@ -6312,6 +6332,7 @@ package java.nio { method public abstract java.nio.CharBuffer slice(); method public abstract java.nio.CharBuffer slice(int, int); method public abstract java.nio.CharBuffer subSequence(int, int); + method public String toString(); method public static java.nio.CharBuffer wrap(char[], int, int); method public static java.nio.CharBuffer wrap(char[]); method public static java.nio.CharBuffer wrap(CharSequence, int, int); @@ -7590,6 +7611,7 @@ package java.nio.file.attribute { } public interface PosixFileAttributeView extends java.nio.file.attribute.BasicFileAttributeView java.nio.file.attribute.FileOwnerAttributeView { + method public String name(); method public java.nio.file.attribute.PosixFileAttributes readAttributes() throws java.io.IOException; method public void setGroup(java.nio.file.attribute.GroupPrincipal) throws java.io.IOException; method public void setPermissions(java.util.Set<java.nio.file.attribute.PosixFilePermission>) throws java.io.IOException; @@ -7884,10 +7906,12 @@ package java.security { method @Deprecated public final String getName(); method @Deprecated public java.security.PublicKey getPublicKey(); method @Deprecated public final java.security.IdentityScope getScope(); + method @Deprecated public int hashCode(); method @Deprecated protected boolean identityEquals(java.security.Identity); method @Deprecated public void removeCertificate(java.security.Certificate) throws java.security.KeyManagementException; method @Deprecated public void setInfo(String); method @Deprecated public void setPublicKey(java.security.PublicKey) throws java.security.KeyManagementException; + method @Deprecated public String toString(); method @Deprecated public String toString(boolean); } @@ -8069,14 +8093,17 @@ package java.security { public static class KeyStore.PasswordProtection implements javax.security.auth.Destroyable java.security.KeyStore.ProtectionParameter { ctor public KeyStore.PasswordProtection(char[]); ctor public KeyStore.PasswordProtection(char[], String, java.security.spec.AlgorithmParameterSpec); + method public void destroy() throws javax.security.auth.DestroyFailedException; method public char[] getPassword(); method public String getProtectionAlgorithm(); method public java.security.spec.AlgorithmParameterSpec getProtectionParameters(); + method public boolean isDestroyed(); } public static final class KeyStore.PrivateKeyEntry implements java.security.KeyStore.Entry { ctor public KeyStore.PrivateKeyEntry(java.security.PrivateKey, java.security.cert.Certificate[]); ctor public KeyStore.PrivateKeyEntry(java.security.PrivateKey, java.security.cert.Certificate[], java.util.Set<java.security.KeyStore.Entry.Attribute>); + method public java.util.Set<java.security.KeyStore.Entry.Attribute> getAttributes(); method public java.security.cert.Certificate getCertificate(); method public java.security.cert.Certificate[] getCertificateChain(); method public java.security.PrivateKey getPrivateKey(); @@ -8088,12 +8115,14 @@ package java.security { public static final class KeyStore.SecretKeyEntry implements java.security.KeyStore.Entry { ctor public KeyStore.SecretKeyEntry(javax.crypto.SecretKey); ctor public KeyStore.SecretKeyEntry(javax.crypto.SecretKey, java.util.Set<java.security.KeyStore.Entry.Attribute>); + method public java.util.Set<java.security.KeyStore.Entry.Attribute> getAttributes(); method public javax.crypto.SecretKey getSecretKey(); } public static final class KeyStore.TrustedCertificateEntry implements java.security.KeyStore.Entry { ctor public KeyStore.TrustedCertificateEntry(java.security.cert.Certificate); ctor public KeyStore.TrustedCertificateEntry(java.security.cert.Certificate, java.util.Set<java.security.KeyStore.Entry.Attribute>); + method public java.util.Set<java.security.KeyStore.Entry.Attribute> getAttributes(); method public java.security.cert.Certificate getTrustedCertificate(); } @@ -10797,6 +10826,7 @@ package java.text { method public abstract int compare(String, String); method public int compare(Object, Object); method public boolean equals(String, String); + method public boolean equals(Object); method public static java.util.Locale[] getAvailableLocales(); method public abstract java.text.CollationKey getCollationKey(String); method public int getDecomposition(); @@ -11131,6 +11161,7 @@ package java.text { method public java.text.CollationElementIterator getCollationElementIterator(java.text.CharacterIterator); method public java.text.CollationKey getCollationKey(String); method public String getRules(); + method public int hashCode(); } public class SimpleDateFormat extends java.text.DateFormat { @@ -11175,6 +11206,7 @@ package java.time { ctor protected Clock(); method public static java.time.Clock fixed(java.time.Instant, java.time.ZoneId); method public abstract java.time.ZoneId getZone(); + method public long millis(); method public static java.time.Clock offset(java.time.Clock, java.time.Duration); method public static java.time.Clock system(java.time.ZoneId); method public static java.time.Clock systemDefaultZone(); @@ -11276,6 +11308,7 @@ package java.time { method public java.time.ZonedDateTime atZone(java.time.ZoneId); method public int compareTo(java.time.Instant); method public static java.time.Instant from(java.time.temporal.TemporalAccessor); + method public int get(java.time.temporal.TemporalField); method public long getEpochSecond(); method public long getLong(java.time.temporal.TemporalField); method public int getNano(); @@ -11299,6 +11332,8 @@ package java.time { method public java.time.Instant plusMillis(long); method public java.time.Instant plusNanos(long); method public java.time.Instant plusSeconds(long); + method public <R> R query(java.time.temporal.TemporalQuery<R>); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); method public long toEpochMilli(); method public java.time.Instant truncatedTo(java.time.temporal.TemporalUnit); method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit); @@ -11320,6 +11355,7 @@ package java.time { } public final class LocalDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster { + method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal); method public java.time.LocalDateTime atStartOfDay(); method public java.time.ZonedDateTime atStartOfDay(java.time.ZoneId); method public java.time.LocalDateTime atTime(java.time.LocalTime); @@ -11327,18 +11363,31 @@ package java.time { method public java.time.LocalDateTime atTime(int, int, int); method public java.time.LocalDateTime atTime(int, int, int, int); method public java.time.OffsetDateTime atTime(java.time.OffsetTime); + method public int compareTo(java.time.chrono.ChronoLocalDate); method public java.util.stream.Stream<java.time.LocalDate> datesUntil(java.time.LocalDate); method public java.util.stream.Stream<java.time.LocalDate> datesUntil(java.time.LocalDate, java.time.Period); + method public boolean equals(Object); + method public String format(java.time.format.DateTimeFormatter); method public static java.time.LocalDate from(java.time.temporal.TemporalAccessor); + method public int get(java.time.temporal.TemporalField); method public java.time.chrono.IsoChronology getChronology(); method public int getDayOfMonth(); method public java.time.DayOfWeek getDayOfWeek(); method public int getDayOfYear(); + method public java.time.chrono.Era getEra(); method public long getLong(java.time.temporal.TemporalField); method public java.time.Month getMonth(); method public int getMonthValue(); method public int getYear(); + method public int hashCode(); + method public boolean isAfter(java.time.chrono.ChronoLocalDate); + method public boolean isBefore(java.time.chrono.ChronoLocalDate); + method public boolean isEqual(java.time.chrono.ChronoLocalDate); + method public boolean isLeapYear(); + method public boolean isSupported(java.time.temporal.TemporalField); + method public boolean isSupported(java.time.temporal.TemporalUnit); method public int lengthOfMonth(); + method public int lengthOfYear(); method public java.time.LocalDate minus(java.time.temporal.TemporalAmount); method public java.time.LocalDate minus(long, java.time.temporal.TemporalUnit); method public java.time.LocalDate minusDays(long); @@ -11361,7 +11410,11 @@ package java.time { method public java.time.LocalDate plusMonths(long); method public java.time.LocalDate plusWeeks(long); method public java.time.LocalDate plusYears(long); + method public <R> R query(java.time.temporal.TemporalQuery<R>); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); + method public long toEpochDay(); method public long toEpochSecond(java.time.LocalTime, java.time.ZoneOffset); + method public String toString(); method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit); method public java.time.Period until(java.time.chrono.ChronoLocalDate); method public java.time.LocalDate with(java.time.temporal.TemporalAdjuster); @@ -11376,9 +11429,14 @@ package java.time { } public final class LocalDateTime implements java.time.chrono.ChronoLocalDateTime<java.time.LocalDate> java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster { + method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal); method public java.time.OffsetDateTime atOffset(java.time.ZoneOffset); method public java.time.ZonedDateTime atZone(java.time.ZoneId); + method public int compareTo(java.time.chrono.ChronoLocalDateTime<?>); + method public boolean equals(Object); + method public String format(java.time.format.DateTimeFormatter); method public static java.time.LocalDateTime from(java.time.temporal.TemporalAccessor); + method public int get(java.time.temporal.TemporalField); method public int getDayOfMonth(); method public java.time.DayOfWeek getDayOfWeek(); method public int getDayOfYear(); @@ -11390,7 +11448,12 @@ package java.time { method public int getNano(); method public int getSecond(); method public int getYear(); + method public int hashCode(); + method public boolean isAfter(java.time.chrono.ChronoLocalDateTime<?>); + method public boolean isBefore(java.time.chrono.ChronoLocalDateTime<?>); + method public boolean isEqual(java.time.chrono.ChronoLocalDateTime<?>); method public boolean isSupported(java.time.temporal.TemporalField); + method public boolean isSupported(java.time.temporal.TemporalUnit); method public java.time.LocalDateTime minus(java.time.temporal.TemporalAmount); method public java.time.LocalDateTime minus(long, java.time.temporal.TemporalUnit); method public java.time.LocalDateTime minusDays(long); @@ -11425,8 +11488,11 @@ package java.time { method public java.time.LocalDateTime plusSeconds(long); method public java.time.LocalDateTime plusWeeks(long); method public java.time.LocalDateTime plusYears(long); + method public <R> R query(java.time.temporal.TemporalQuery<R>); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); method public java.time.LocalDate toLocalDate(); method public java.time.LocalTime toLocalTime(); + method public String toString(); method public java.time.LocalDateTime truncatedTo(java.time.temporal.TemporalUnit); method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit); method public java.time.LocalDateTime with(java.time.temporal.TemporalAdjuster); @@ -11450,6 +11516,7 @@ package java.time { method public int compareTo(java.time.LocalTime); method public String format(java.time.format.DateTimeFormatter); method public static java.time.LocalTime from(java.time.temporal.TemporalAccessor); + method public int get(java.time.temporal.TemporalField); method public int getHour(); method public long getLong(java.time.temporal.TemporalField); method public int getMinute(); @@ -11482,6 +11549,8 @@ package java.time { method public java.time.LocalTime plusMinutes(long); method public java.time.LocalTime plusNanos(long); method public java.time.LocalTime plusSeconds(long); + method public <R> R query(java.time.temporal.TemporalQuery<R>); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); method public long toEpochSecond(java.time.LocalDate, java.time.ZoneOffset); method public long toNanoOfDay(); method public int toSecondOfDay(); @@ -11534,6 +11603,7 @@ package java.time { method public int compareTo(java.time.MonthDay); method public String format(java.time.format.DateTimeFormatter); method public static java.time.MonthDay from(java.time.temporal.TemporalAccessor); + method public int get(java.time.temporal.TemporalField); method public int getDayOfMonth(); method public long getLong(java.time.temporal.TemporalField); method public java.time.Month getMonth(); @@ -11549,6 +11619,8 @@ package java.time { method public static java.time.MonthDay of(int, int); method public static java.time.MonthDay parse(CharSequence); method public static java.time.MonthDay parse(CharSequence, java.time.format.DateTimeFormatter); + method public <R> R query(java.time.temporal.TemporalQuery<R>); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); method public java.time.MonthDay with(java.time.Month); method public java.time.MonthDay withDayOfMonth(int); method public java.time.MonthDay withMonth(int); @@ -11561,6 +11633,7 @@ package java.time { method public int compareTo(java.time.OffsetDateTime); method public String format(java.time.format.DateTimeFormatter); method public static java.time.OffsetDateTime from(java.time.temporal.TemporalAccessor); + method public int get(java.time.temporal.TemporalField); method public int getDayOfMonth(); method public java.time.DayOfWeek getDayOfWeek(); method public int getDayOfYear(); @@ -11607,6 +11680,8 @@ package java.time { method public java.time.OffsetDateTime plusSeconds(long); method public java.time.OffsetDateTime plusWeeks(long); method public java.time.OffsetDateTime plusYears(long); + method public <R> R query(java.time.temporal.TemporalQuery<R>); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); method public static java.util.Comparator<java.time.OffsetDateTime> timeLineOrder(); method public long toEpochSecond(); method public java.time.Instant toInstant(); @@ -11639,6 +11714,7 @@ package java.time { method public int compareTo(java.time.OffsetTime); method public String format(java.time.format.DateTimeFormatter); method public static java.time.OffsetTime from(java.time.temporal.TemporalAccessor); + method public int get(java.time.temporal.TemporalField); method public int getHour(); method public long getLong(java.time.temporal.TemporalField); method public int getMinute(); @@ -11670,6 +11746,8 @@ package java.time { method public java.time.OffsetTime plusMinutes(long); method public java.time.OffsetTime plusNanos(long); method public java.time.OffsetTime plusSeconds(long); + method public <R> R query(java.time.temporal.TemporalQuery<R>); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); method public long toEpochSecond(java.time.LocalDate); method public java.time.LocalTime toLocalTime(); method public java.time.OffsetTime truncatedTo(java.time.temporal.TemporalUnit); @@ -11689,6 +11767,7 @@ package java.time { public final class Period implements java.time.chrono.ChronoPeriod java.io.Serializable { method public java.time.temporal.Temporal addTo(java.time.temporal.Temporal); method public static java.time.Period between(java.time.LocalDate, java.time.LocalDate); + method public boolean equals(Object); method public static java.time.Period from(java.time.temporal.TemporalAmount); method public long get(java.time.temporal.TemporalUnit); method public java.time.chrono.IsoChronology getChronology(); @@ -11696,6 +11775,9 @@ package java.time { method public int getMonths(); method public java.util.List<java.time.temporal.TemporalUnit> getUnits(); method public int getYears(); + method public int hashCode(); + method public boolean isNegative(); + method public boolean isZero(); method public java.time.Period minus(java.time.temporal.TemporalAmount); method public java.time.Period minusDays(long); method public java.time.Period minusMonths(long); @@ -11714,6 +11796,7 @@ package java.time { method public java.time.Period plusMonths(long); method public java.time.Period plusYears(long); method public java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal); + method public String toString(); method public long toTotalMonths(); method public java.time.Period withDays(int); method public java.time.Period withMonths(int); @@ -11730,6 +11813,7 @@ package java.time { method public int compareTo(java.time.Year); method public String format(java.time.format.DateTimeFormatter); method public static java.time.Year from(java.time.temporal.TemporalAccessor); + method public int get(java.time.temporal.TemporalField); method public long getLong(java.time.temporal.TemporalField); method public int getValue(); method public boolean isAfter(java.time.Year); @@ -11752,6 +11836,8 @@ package java.time { method public java.time.Year plus(java.time.temporal.TemporalAmount); method public java.time.Year plus(long, java.time.temporal.TemporalUnit); method public java.time.Year plusYears(long); + method public <R> R query(java.time.temporal.TemporalQuery<R>); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit); method public java.time.Year with(java.time.temporal.TemporalAdjuster); method public java.time.Year with(java.time.temporal.TemporalField, long); @@ -11766,6 +11852,7 @@ package java.time { method public int compareTo(java.time.YearMonth); method public String format(java.time.format.DateTimeFormatter); method public static java.time.YearMonth from(java.time.temporal.TemporalAccessor); + method public int get(java.time.temporal.TemporalField); method public long getLong(java.time.temporal.TemporalField); method public java.time.Month getMonth(); method public int getMonthValue(); @@ -11793,6 +11880,8 @@ package java.time { method public java.time.YearMonth plus(long, java.time.temporal.TemporalUnit); method public java.time.YearMonth plusMonths(long); method public java.time.YearMonth plusYears(long); + method public <R> R query(java.time.temporal.TemporalQuery<R>); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit); method public java.time.YearMonth with(java.time.temporal.TemporalAdjuster); method public java.time.YearMonth with(java.time.temporal.TemporalField, long); @@ -11818,6 +11907,7 @@ package java.time { method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal); method public int compareTo(java.time.ZoneOffset); method public static java.time.ZoneOffset from(java.time.temporal.TemporalAccessor); + method public int get(java.time.temporal.TemporalField); method public String getId(); method public long getLong(java.time.temporal.TemporalField); method public java.time.zone.ZoneRules getRules(); @@ -11828,17 +11918,23 @@ package java.time { method public static java.time.ZoneOffset ofHoursMinutes(int, int); method public static java.time.ZoneOffset ofHoursMinutesSeconds(int, int, int); method public static java.time.ZoneOffset ofTotalSeconds(int); + method public <R> R query(java.time.temporal.TemporalQuery<R>); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); field public static final java.time.ZoneOffset MAX; field public static final java.time.ZoneOffset MIN; field public static final java.time.ZoneOffset UTC; } public final class ZonedDateTime implements java.time.chrono.ChronoZonedDateTime<java.time.LocalDate> java.io.Serializable java.time.temporal.Temporal { + method public boolean equals(Object); + method public String format(java.time.format.DateTimeFormatter); method public static java.time.ZonedDateTime from(java.time.temporal.TemporalAccessor); + method public int get(java.time.temporal.TemporalField); method public int getDayOfMonth(); method public java.time.DayOfWeek getDayOfWeek(); method public int getDayOfYear(); method public int getHour(); + method public long getLong(java.time.temporal.TemporalField); method public int getMinute(); method public java.time.Month getMonth(); method public int getMonthValue(); @@ -11847,7 +11943,9 @@ package java.time { method public int getSecond(); method public int getYear(); method public java.time.ZoneId getZone(); + method public int hashCode(); method public boolean isSupported(java.time.temporal.TemporalField); + method public boolean isSupported(java.time.temporal.TemporalUnit); method public java.time.ZonedDateTime minus(java.time.temporal.TemporalAmount); method public java.time.ZonedDateTime minus(long, java.time.temporal.TemporalUnit); method public java.time.ZonedDateTime minusDays(long); @@ -11880,9 +11978,13 @@ package java.time { method public java.time.ZonedDateTime plusSeconds(long); method public java.time.ZonedDateTime plusWeeks(long); method public java.time.ZonedDateTime plusYears(long); + method public <R> R query(java.time.temporal.TemporalQuery<R>); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); method public java.time.LocalDate toLocalDate(); method public java.time.LocalDateTime toLocalDateTime(); + method public java.time.LocalTime toLocalTime(); method public java.time.OffsetDateTime toOffsetDateTime(); + method public String toString(); method public java.time.ZonedDateTime truncatedTo(java.time.temporal.TemporalUnit); method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit); method public java.time.ZonedDateTime with(java.time.temporal.TemporalAdjuster); @@ -11909,7 +12011,10 @@ package java.time.chrono { public abstract class AbstractChronology implements java.time.chrono.Chronology { ctor protected AbstractChronology(); method public int compareTo(java.time.chrono.Chronology); + method public boolean equals(Object); + method public int hashCode(); method public java.time.chrono.ChronoLocalDate resolveDate(java.util.Map<java.time.temporal.TemporalField,java.lang.Long>, java.time.format.ResolverStyle); + method public String toString(); } public interface ChronoLocalDate extends java.time.temporal.Temporal java.lang.Comparable<java.time.chrono.ChronoLocalDate> java.time.temporal.TemporalAdjuster { @@ -12090,7 +12195,9 @@ package java.time.chrono { method public java.time.chrono.HijrahChronology getChronology(); method public java.time.chrono.HijrahEra getEra(); method public long getLong(java.time.temporal.TemporalField); + method public boolean isLeapYear(); method public int lengthOfMonth(); + method public int lengthOfYear(); method public java.time.chrono.HijrahDate minus(java.time.temporal.TemporalAmount); method public java.time.chrono.HijrahDate minus(long, java.time.temporal.TemporalUnit); method public static java.time.chrono.HijrahDate now(); @@ -12099,6 +12206,9 @@ package java.time.chrono { method public static java.time.chrono.HijrahDate of(int, int, int); method public java.time.chrono.HijrahDate plus(java.time.temporal.TemporalAmount); method public java.time.chrono.HijrahDate plus(long, java.time.temporal.TemporalUnit); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); + method public long toEpochDay(); + method public String toString(); method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate); method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit); method public java.time.chrono.HijrahDate with(java.time.temporal.TemporalField, long); @@ -12122,6 +12232,7 @@ package java.time.chrono { method public java.time.LocalDate dateNow(java.time.Clock); method public java.time.LocalDate dateYearDay(java.time.chrono.Era, int, int); method public java.time.LocalDate dateYearDay(int, int); + method public long epochSecond(int, int, int, int, int, int, java.time.ZoneOffset); method public java.time.chrono.IsoEra eraOf(int); method public java.util.List<java.time.chrono.Era> eras(); method public String getCalendarType(); @@ -12174,7 +12285,9 @@ package java.time.chrono { method public java.time.chrono.JapaneseChronology getChronology(); method public java.time.chrono.JapaneseEra getEra(); method public long getLong(java.time.temporal.TemporalField); + method public boolean isSupported(java.time.temporal.TemporalField); method public int lengthOfMonth(); + method public int lengthOfYear(); method public java.time.chrono.JapaneseDate minus(java.time.temporal.TemporalAmount); method public java.time.chrono.JapaneseDate minus(long, java.time.temporal.TemporalUnit); method public static java.time.chrono.JapaneseDate now(); @@ -12184,6 +12297,9 @@ package java.time.chrono { method public static java.time.chrono.JapaneseDate of(int, int, int); method public java.time.chrono.JapaneseDate plus(java.time.temporal.TemporalAmount); method public java.time.chrono.JapaneseDate plus(long, java.time.temporal.TemporalUnit); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); + method public long toEpochDay(); + method public String toString(); method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate); method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit); method public java.time.chrono.JapaneseDate with(java.time.temporal.TemporalField, long); @@ -12191,8 +12307,10 @@ package java.time.chrono { } public final class JapaneseEra implements java.time.chrono.Era java.io.Serializable { + method public String getDisplayName(java.time.format.TextStyle, java.util.Locale); method public int getValue(); method public static java.time.chrono.JapaneseEra of(int); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); method public static java.time.chrono.JapaneseEra valueOf(String); method public static java.time.chrono.JapaneseEra[] values(); field public static final java.time.chrono.JapaneseEra HEISEI; @@ -12241,6 +12359,9 @@ package java.time.chrono { method public static java.time.chrono.MinguoDate of(int, int, int); method public java.time.chrono.MinguoDate plus(java.time.temporal.TemporalAmount); method public java.time.chrono.MinguoDate plus(long, java.time.temporal.TemporalUnit); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); + method public long toEpochDay(); + method public String toString(); method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate); method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit); method public java.time.chrono.MinguoDate with(java.time.temporal.TemporalField, long); @@ -12293,6 +12414,9 @@ package java.time.chrono { method public static java.time.chrono.ThaiBuddhistDate of(int, int, int); method public java.time.chrono.ThaiBuddhistDate plus(java.time.temporal.TemporalAmount); method public java.time.chrono.ThaiBuddhistDate plus(long, java.time.temporal.TemporalUnit); + method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField); + method public long toEpochDay(); + method public String toString(); method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate); method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit); method public java.time.chrono.ThaiBuddhistDate with(java.time.temporal.TemporalField, long); @@ -12756,6 +12880,8 @@ package java.util { ctor protected AbstractList(); method public void add(int, E); method public boolean addAll(int, @NonNull java.util.Collection<? extends E>); + method public boolean equals(@Nullable Object); + method public int hashCode(); method public int indexOf(@Nullable Object); method @NonNull public java.util.Iterator<E> iterator(); method public int lastIndexOf(@Nullable Object); @@ -12773,7 +12899,9 @@ package java.util { method public void clear(); method public boolean containsKey(@Nullable Object); method public boolean containsValue(@Nullable Object); + method public boolean equals(@Nullable Object); method @Nullable public V get(@Nullable Object); + method public int hashCode(); method public boolean isEmpty(); method @NonNull public java.util.Set<K> keySet(); method @Nullable public V put(K, V); @@ -12786,16 +12914,20 @@ package java.util { public static class AbstractMap.SimpleEntry<K, V> implements java.util.Map.Entry<K,V> java.io.Serializable { ctor public AbstractMap.SimpleEntry(K, V); ctor public AbstractMap.SimpleEntry(@NonNull java.util.Map.Entry<? extends K,? extends V>); + method public boolean equals(@Nullable Object); method public K getKey(); method public V getValue(); + method public int hashCode(); method public V setValue(V); } public static class AbstractMap.SimpleImmutableEntry<K, V> implements java.util.Map.Entry<K,V> java.io.Serializable { ctor public AbstractMap.SimpleImmutableEntry(K, V); ctor public AbstractMap.SimpleImmutableEntry(@NonNull java.util.Map.Entry<? extends K,? extends V>); + method public boolean equals(@Nullable Object); method public K getKey(); method public V getValue(); + method public int hashCode(); method public V setValue(V); } @@ -12812,6 +12944,8 @@ package java.util { public abstract class AbstractSet<E> extends java.util.AbstractCollection<E> implements java.util.Set<E> { ctor protected AbstractSet(); + method public boolean equals(@Nullable Object); + method public int hashCode(); } public class ArrayDeque<E> extends java.util.AbstractCollection<E> implements java.lang.Cloneable java.util.Deque<E> java.io.Serializable { @@ -12841,9 +12975,11 @@ package java.util { method public E remove(); method public E removeFirst(); method public boolean removeFirstOccurrence(@Nullable Object); + method public boolean removeIf(@NonNull java.util.function.Predicate<? super E>); method public E removeLast(); method public boolean removeLastOccurrence(@Nullable Object); method public int size(); + method @NonNull public java.util.Spliterator<E> spliterator(); } public class ArrayList<E> extends java.util.AbstractList<E> implements java.lang.Cloneable java.util.List<E> java.util.RandomAccess java.io.Serializable { @@ -12854,7 +12990,11 @@ package java.util { method public void ensureCapacity(int); method public void forEach(@NonNull java.util.function.Consumer<? super E>); method public E get(int); + method public boolean removeIf(@NonNull java.util.function.Predicate<? super E>); + method public void replaceAll(@NonNull java.util.function.UnaryOperator<E>); method public int size(); + method public void sort(@Nullable java.util.Comparator<? super E>); + method @NonNull public java.util.Spliterator<E> spliterator(); method public void trimToSize(); } @@ -13498,6 +13638,7 @@ package java.util { ctor public EnumMap(java.util.Map<K,? extends V>); method public java.util.EnumMap<K,V> clone(); method public java.util.Set<java.util.Map.Entry<K,V>> entrySet(); + method public V put(K, V); } public abstract class EnumSet<E extends java.lang.Enum<E>> extends java.util.AbstractSet<E> implements java.lang.Cloneable java.io.Serializable { @@ -13620,7 +13761,18 @@ package java.util { ctor public HashMap(); ctor public HashMap(@NonNull java.util.Map<? extends K,? extends V>); method @NonNull public Object clone(); + method @Nullable public V compute(K, @NonNull java.util.function.BiFunction<? super K,? super V,? extends V>); + method @Nullable public V computeIfAbsent(K, @NonNull java.util.function.Function<? super K,? extends V>); + method @Nullable public V computeIfPresent(K, @NonNull java.util.function.BiFunction<? super K,? super V,? extends V>); method @NonNull public java.util.Set<java.util.Map.Entry<K,V>> entrySet(); + method public void forEach(@NonNull java.util.function.BiConsumer<? super K,? super V>); + method @Nullable public V getOrDefault(@Nullable Object, @Nullable V); + method @Nullable public V merge(K, @NonNull V, @NonNull java.util.function.BiFunction<? super V,? super V,? extends V>); + method @Nullable public V putIfAbsent(K, V); + method public boolean remove(@Nullable Object, @Nullable Object); + method public boolean replace(K, @Nullable V, V); + method @Nullable public V replace(K, V); + method public void replaceAll(@NonNull java.util.function.BiFunction<? super K,? super V,? extends V>); } public class HashSet<E> extends java.util.AbstractSet<E> implements java.lang.Cloneable java.io.Serializable java.util.Set<E> { @@ -13631,6 +13783,7 @@ package java.util { method @NonNull public Object clone(); method @NonNull public java.util.Iterator<E> iterator(); method public int size(); + method @NonNull public java.util.Spliterator<E> spliterator(); } public class Hashtable<K, V> extends java.util.Dictionary<K,V> implements java.lang.Cloneable java.util.Map<K,V> java.io.Serializable { @@ -13640,19 +13793,32 @@ package java.util { ctor public Hashtable(java.util.Map<? extends K,? extends V>); method public void clear(); method public Object clone(); + method public V compute(K, java.util.function.BiFunction<? super K,? super V,? extends V>); + method public V computeIfAbsent(K, java.util.function.Function<? super K,? extends V>); + method public V computeIfPresent(K, java.util.function.BiFunction<? super K,? super V,? extends V>); method public boolean contains(Object); method public boolean containsKey(Object); method public boolean containsValue(Object); method public java.util.Enumeration<V> elements(); method public java.util.Set<java.util.Map.Entry<K,V>> entrySet(); + method public boolean equals(Object); + method public void forEach(java.util.function.BiConsumer<? super K,? super V>); method public V get(Object); + method public V getOrDefault(Object, V); + method public int hashCode(); method public boolean isEmpty(); method public java.util.Set<K> keySet(); method public java.util.Enumeration<K> keys(); + method public V merge(K, V, java.util.function.BiFunction<? super V,? super V,? extends V>); method public V put(K, V); method public void putAll(java.util.Map<? extends K,? extends V>); + method public V putIfAbsent(K, V); method protected void rehash(); method public V remove(Object); + method public boolean remove(Object, Object); + method public boolean replace(K, V, V); + method public V replace(K, V); + method public void replaceAll(java.util.function.BiFunction<? super K,? super V,? extends V>); method public int size(); method public java.util.Collection<V> values(); } @@ -13699,6 +13865,8 @@ package java.util { ctor public IdentityHashMap(java.util.Map<? extends K,? extends V>); method public Object clone(); method public java.util.Set<java.util.Map.Entry<K,V>> entrySet(); + method public void forEach(java.util.function.BiConsumer<? super K,? super V>); + method public void replaceAll(java.util.function.BiFunction<? super K,? super V,? extends V>); } public class IllegalFormatCodePointException extends java.util.IllegalFormatException { @@ -13792,6 +13960,7 @@ package java.util { method public E element(); method public E getFirst(); method public E getLast(); + method @NonNull public java.util.ListIterator<E> listIterator(int); method public boolean offer(E); method public boolean offerFirst(E); method public boolean offerLast(E); @@ -13809,6 +13978,7 @@ package java.util { method public E removeLast(); method public boolean removeLastOccurrence(@Nullable Object); method public int size(); + method @NonNull public java.util.Spliterator<E> spliterator(); } public interface List<E> extends java.util.Collection<E> { @@ -14243,6 +14413,7 @@ package java.util { method public boolean offer(E); method public E peek(); method public E poll(); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public int size(); method public final java.util.Spliterator<E> spliterator(); } @@ -14423,6 +14594,7 @@ package java.util { method public short nextShort(); method public short nextShort(int); method public int radix(); + method public void remove(); method public java.util.Scanner reset(); method public java.util.Scanner skip(java.util.regex.Pattern); method public java.util.Scanner skip(String); @@ -14739,6 +14911,7 @@ package java.util { method public K firstKey(); method @Nullable public java.util.Map.Entry<K,V> floorEntry(K); method @Nullable public K floorKey(K); + method public void forEach(@NonNull java.util.function.BiConsumer<? super K,? super V>); method @NonNull public java.util.NavigableMap<K,V> headMap(K, boolean); method @NonNull public java.util.SortedMap<K,V> headMap(K); method @Nullable public java.util.Map.Entry<K,V> higherEntry(K); @@ -14750,6 +14923,9 @@ package java.util { method @NonNull public java.util.NavigableSet<K> navigableKeySet(); method @Nullable public java.util.Map.Entry<K,V> pollFirstEntry(); method @Nullable public java.util.Map.Entry<K,V> pollLastEntry(); + method public boolean replace(K, @Nullable V, V); + method public V replace(K, V); + method public void replaceAll(@NonNull java.util.function.BiFunction<? super K,? super V,? extends V>); method @NonNull public java.util.NavigableMap<K,V> subMap(K, boolean, K, boolean); method @NonNull public java.util.SortedMap<K,V> subMap(K, K); method @NonNull public java.util.NavigableMap<K,V> tailMap(K, boolean); @@ -14777,6 +14953,7 @@ package java.util { method public E pollFirst(); method public E pollLast(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean); method public java.util.SortedSet<E> subSet(E, E); method public java.util.NavigableSet<E> tailSet(E, boolean); @@ -14830,9 +15007,13 @@ package java.util { method public void removeAllElements(); method public boolean removeElement(@Nullable Object); method public void removeElementAt(int); + method public boolean removeIf(@NonNull java.util.function.Predicate<? super E>); + method public void replaceAll(@NonNull java.util.function.UnaryOperator<E>); method public void setElementAt(E, int); method public void setSize(int); method public int size(); + method public void sort(@Nullable java.util.Comparator<? super E>); + method @NonNull public java.util.Spliterator<E> spliterator(); method public void trimToSize(); field protected int capacityIncrement; field protected int elementCount; @@ -14845,6 +15026,8 @@ package java.util { ctor public WeakHashMap(); ctor public WeakHashMap(@NonNull java.util.Map<? extends K,? extends V>); method @NonNull public java.util.Set<java.util.Map.Entry<K,V>> entrySet(); + method public void forEach(@NonNull java.util.function.BiConsumer<? super K,? super V>); + method public void replaceAll(@NonNull java.util.function.BiFunction<? super K,? super V,? extends V>); } } @@ -14879,17 +15062,29 @@ package java.util.concurrent { method public E poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; method public void put(E) throws java.lang.InterruptedException; method public int remainingCapacity(); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } public interface BlockingDeque<E> extends java.util.concurrent.BlockingQueue<E> java.util.Deque<E> { + method public boolean add(E); + method public boolean contains(Object); + method public E element(); + method public java.util.Iterator<E> iterator(); + method public boolean offer(E); method public boolean offerFirst(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; method public boolean offerLast(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; + method public E peek(); + method public E poll(); method public E pollFirst(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; method public E pollLast(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; method public void putFirst(E) throws java.lang.InterruptedException; method public void putLast(E) throws java.lang.InterruptedException; + method public E remove(); + method public boolean remove(Object); + method public int size(); method public E takeFirst() throws java.lang.InterruptedException; method public E takeLast() throws java.lang.InterruptedException; } @@ -15068,9 +15263,13 @@ package java.util.concurrent { ctor public ConcurrentHashMap(@NonNull java.util.Map<? extends K,? extends V>); ctor public ConcurrentHashMap(int, float); ctor public ConcurrentHashMap(int, float, int); + method @Nullable public V compute(@NonNull K, @NonNull java.util.function.BiFunction<? super K,? super V,? extends V>); + method @Nullable public V computeIfAbsent(@NonNull K, @NonNull java.util.function.Function<? super K,? extends V>); + method @Nullable public V computeIfPresent(@NonNull K, @NonNull java.util.function.BiFunction<? super K,? super V,? extends V>); method public boolean contains(@NonNull Object); method @NonNull public java.util.Enumeration<V> elements(); method @NonNull public java.util.Set<java.util.Map.Entry<K,V>> entrySet(); + method public void forEach(@NonNull java.util.function.BiConsumer<? super K,? super V>); method public void forEach(long, @NonNull java.util.function.BiConsumer<? super K,? super V>); method public <U> void forEach(long, @NonNull java.util.function.BiFunction<? super K,? super V,? extends U>, @NonNull java.util.function.Consumer<? super U>); method public void forEachEntry(long, @NonNull java.util.function.Consumer<? super java.util.Map.Entry<K,V>>); @@ -15079,11 +15278,14 @@ package java.util.concurrent { method public <U> void forEachKey(long, @NonNull java.util.function.Function<? super K,? extends U>, @NonNull java.util.function.Consumer<? super U>); method public void forEachValue(long, @NonNull java.util.function.Consumer<? super V>); method public <U> void forEachValue(long, @NonNull java.util.function.Function<? super V,? extends U>, @NonNull java.util.function.Consumer<? super U>); + method @Nullable public V getOrDefault(@NonNull Object, @Nullable V); method @NonNull public java.util.concurrent.ConcurrentHashMap.KeySetView<K,V> keySet(@NonNull V); method @NonNull public java.util.Enumeration<K> keys(); method public long mappingCount(); + method @Nullable public V merge(@NonNull K, @NonNull V, @NonNull java.util.function.BiFunction<? super V,? super V,? extends V>); method @NonNull public static <K> java.util.concurrent.ConcurrentHashMap.KeySetView<K,java.lang.Boolean> newKeySet(); method @NonNull public static <K> java.util.concurrent.ConcurrentHashMap.KeySetView<K,java.lang.Boolean> newKeySet(int); + method @Nullable public V putIfAbsent(@NonNull K, @NonNull V); method @Nullable public <U> U reduce(long, @NonNull java.util.function.BiFunction<? super K,? super V,? extends U>, @NonNull java.util.function.BiFunction<? super U,? super U,? extends U>); method @Nullable public java.util.Map.Entry<K,V> reduceEntries(long, @NonNull java.util.function.BiFunction<java.util.Map.Entry<K,V>,java.util.Map.Entry<K,V>,? extends java.util.Map.Entry<K,V>>); method @Nullable public <U> U reduceEntries(long, @NonNull java.util.function.Function<java.util.Map.Entry<K,V>,? extends U>, @NonNull java.util.function.BiFunction<? super U,? super U,? extends U>); @@ -15103,6 +15305,10 @@ package java.util.concurrent { method public double reduceValuesToDouble(long, @NonNull java.util.function.ToDoubleFunction<? super V>, double, @NonNull java.util.function.DoubleBinaryOperator); method public int reduceValuesToInt(long, @NonNull java.util.function.ToIntFunction<? super V>, int, @NonNull java.util.function.IntBinaryOperator); method public long reduceValuesToLong(long, @NonNull java.util.function.ToLongFunction<? super V>, long, @NonNull java.util.function.LongBinaryOperator); + method public boolean remove(@NonNull Object, @Nullable Object); + method public boolean replace(@NonNull K, @NonNull V, @NonNull V); + method @Nullable public V replace(@NonNull K, @NonNull V); + method public void replaceAll(@NonNull java.util.function.BiFunction<? super K,? super V,? extends V>); method @Nullable public <U> U search(long, @NonNull java.util.function.BiFunction<? super K,? super V,? extends U>); method @Nullable public <U> U searchEntries(long, @NonNull java.util.function.Function<java.util.Map.Entry<K,V>,? extends U>); method @Nullable public <U> U searchKeys(long, @NonNull java.util.function.Function<? super K,? extends U>); @@ -15115,9 +15321,11 @@ package java.util.concurrent { method public final void clear(); method public boolean contains(@NonNull Object); method public final boolean containsAll(@NonNull java.util.Collection<?>); + method public boolean equals(@Nullable Object); method public void forEach(@NonNull java.util.function.Consumer<? super K>); method @NonNull public java.util.concurrent.ConcurrentHashMap<K,V> getMap(); method @Nullable public V getMappedValue(); + method public int hashCode(); method public final boolean isEmpty(); method @NonNull public java.util.Iterator<K> iterator(); method public boolean remove(@NonNull Object); @@ -15155,9 +15363,11 @@ package java.util.concurrent { method public E remove(); method public E removeFirst(); method public boolean removeFirstOccurrence(Object); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public E removeLast(); method public boolean removeLastOccurrence(Object); method public int size(); + method public java.util.Spliterator<E> spliterator(); } public class ConcurrentLinkedQueue<E> extends java.util.AbstractQueue<E> implements java.util.Queue<E> java.io.Serializable { @@ -15168,7 +15378,9 @@ package java.util.concurrent { method public boolean offer(E); method public E peek(); method public E poll(); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public int size(); + method public java.util.Spliterator<E> spliterator(); } public interface ConcurrentMap<K, V> extends java.util.Map<K,V> { @@ -15198,6 +15410,9 @@ package java.util.concurrent { method public K ceilingKey(K); method public java.util.concurrent.ConcurrentSkipListMap<K,V> clone(); method public java.util.Comparator<? super K> comparator(); + method public V compute(K, java.util.function.BiFunction<? super K,? super V,? extends V>); + method public V computeIfAbsent(K, java.util.function.Function<? super K,? extends V>); + method public V computeIfPresent(K, java.util.function.BiFunction<? super K,? super V,? extends V>); method public java.util.NavigableSet<K> descendingKeySet(); method public java.util.concurrent.ConcurrentNavigableMap<K,V> descendingMap(); method public java.util.Set<java.util.Map.Entry<K,V>> entrySet(); @@ -15205,6 +15420,8 @@ package java.util.concurrent { method public K firstKey(); method public java.util.Map.Entry<K,V> floorEntry(K); method public K floorKey(K); + method public void forEach(java.util.function.BiConsumer<? super K,? super V>); + method public V getOrDefault(Object, V); method public java.util.concurrent.ConcurrentNavigableMap<K,V> headMap(K, boolean); method public java.util.concurrent.ConcurrentNavigableMap<K,V> headMap(K); method public java.util.Map.Entry<K,V> higherEntry(K); @@ -15214,9 +15431,15 @@ package java.util.concurrent { method public K lastKey(); method public java.util.Map.Entry<K,V> lowerEntry(K); method public K lowerKey(K); + method public V merge(K, V, java.util.function.BiFunction<? super V,? super V,? extends V>); method public java.util.NavigableSet<K> navigableKeySet(); method public java.util.Map.Entry<K,V> pollFirstEntry(); method public java.util.Map.Entry<K,V> pollLastEntry(); + method public V putIfAbsent(K, V); + method public boolean remove(Object, Object); + method public boolean replace(K, V, V); + method public V replace(K, V); + method public void replaceAll(java.util.function.BiFunction<? super K,? super V,? extends V>); method public java.util.concurrent.ConcurrentNavigableMap<K,V> subMap(K, boolean, K, boolean); method public java.util.concurrent.ConcurrentNavigableMap<K,V> subMap(K, K); method public java.util.concurrent.ConcurrentNavigableMap<K,V> tailMap(K, boolean); @@ -15244,6 +15467,7 @@ package java.util.concurrent { method public E pollFirst(); method public E pollLast(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean); method public java.util.NavigableSet<E> subSet(E, E); method public java.util.NavigableSet<E> tailSet(E, boolean); @@ -15264,8 +15488,10 @@ package java.util.concurrent { method @NonNull public Object clone(); method public boolean contains(@Nullable Object); method public boolean containsAll(@NonNull java.util.Collection<?>); + method public boolean equals(@Nullable Object); method public void forEach(@NonNull java.util.function.Consumer<? super E>); method public E get(int); + method public int hashCode(); method public int indexOf(@Nullable Object); method public int indexOf(@Nullable E, int); method public boolean isEmpty(); @@ -15277,9 +15503,13 @@ package java.util.concurrent { method public E remove(int); method public boolean remove(@Nullable Object); method public boolean removeAll(@NonNull java.util.Collection<?>); + method public boolean removeIf(@NonNull java.util.function.Predicate<? super E>); + method public void replaceAll(@NonNull java.util.function.UnaryOperator<E>); method public boolean retainAll(@NonNull java.util.Collection<?>); method public E set(int, E); method public int size(); + method public void sort(@Nullable java.util.Comparator<? super E>); + method @NonNull public java.util.Spliterator<E> spliterator(); method @NonNull public java.util.List<E> subList(int, int); method @NonNull public Object[] toArray(); method @NonNull public <T> T[] toArray(@NonNull T[]); @@ -15290,7 +15520,9 @@ package java.util.concurrent { ctor public CopyOnWriteArraySet(java.util.Collection<? extends E>); method public void forEach(java.util.function.Consumer<? super E>); method public java.util.Iterator<E> iterator(); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public int size(); + method public java.util.Spliterator<E> spliterator(); } public class CountDownLatch { @@ -15341,6 +15573,7 @@ package java.util.concurrent { public class DelayQueue<E extends java.util.concurrent.Delayed> extends java.util.AbstractQueue<E> implements java.util.concurrent.BlockingQueue<E> { ctor public DelayQueue(); ctor public DelayQueue(java.util.Collection<? extends E>); + method public boolean add(E); method public int drainTo(java.util.Collection<? super E>); method public int drainTo(java.util.Collection<? super E>, int); method public java.util.Iterator<E> iterator(); @@ -15607,9 +15840,11 @@ package java.util.concurrent { method public int remainingCapacity(); method public E removeFirst(); method public boolean removeFirstOccurrence(Object); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public E removeLast(); method public boolean removeLastOccurrence(Object); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; method public E takeFirst() throws java.lang.InterruptedException; method public E takeLast() throws java.lang.InterruptedException; @@ -15630,7 +15865,9 @@ package java.util.concurrent { method public E poll(); method public void put(E) throws java.lang.InterruptedException; method public int remainingCapacity(); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } @@ -15650,7 +15887,9 @@ package java.util.concurrent { method public E poll(); method public void put(E); method public int remainingCapacity(); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; method public void transfer(E) throws java.lang.InterruptedException; method public boolean tryTransfer(E); @@ -15698,7 +15937,9 @@ package java.util.concurrent { method public E poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; method public void put(E); method public int remainingCapacity(); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } @@ -15824,6 +16065,7 @@ package java.util.concurrent { method public void put(E) throws java.lang.InterruptedException; method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } @@ -16762,9 +17004,11 @@ package java.util.jar { method public boolean containsKey(Object); method public boolean containsValue(Object); method public java.util.Set<java.util.Map.Entry<java.lang.Object,java.lang.Object>> entrySet(); + method public boolean equals(Object); method public Object get(Object); method public String getValue(String); method public String getValue(java.util.jar.Attributes.Name); + method public int hashCode(); method public boolean isEmpty(); method public java.util.Set<java.lang.Object> keySet(); method public Object put(Object, Object); @@ -17342,6 +17586,7 @@ package java.util.prefs { method protected abstract void removeSpi(String); method public void sync() throws java.util.prefs.BackingStoreException; method protected abstract void syncSpi() throws java.util.prefs.BackingStoreException; + method public String toString(); field protected final Object lock; field protected boolean newNode; } @@ -17821,6 +18066,8 @@ package java.util.zip { method public void reset(); method public void update(int); method public void update(byte[], int, int); + method public void update(byte[]); + method public void update(java.nio.ByteBuffer); } public class CRC32 implements java.util.zip.Checksum { @@ -17829,6 +18076,8 @@ package java.util.zip { method public void reset(); method public void update(int); method public void update(byte[], int, int); + method public void update(byte[]); + method public void update(java.nio.ByteBuffer); } public final class CRC32C implements java.util.zip.Checksum { @@ -17837,6 +18086,7 @@ package java.util.zip { method public void reset(); method public void update(int); method public void update(byte[], int, int); + method public void update(java.nio.ByteBuffer); } public class CheckedInputStream extends java.io.FilterInputStream { @@ -19203,10 +19453,13 @@ package javax.security.auth.x500 { ctor public X500Principal(String, java.util.Map<java.lang.String,java.lang.String>); ctor public X500Principal(byte[]); ctor public X500Principal(java.io.InputStream); + method public boolean equals(Object); method public byte[] getEncoded(); method public String getName(); method public String getName(String); method public String getName(String, java.util.Map<java.lang.String,java.lang.String>); + method public int hashCode(); + method public String toString(); field public static final String CANONICAL = "CANONICAL"; field public static final String RFC1779 = "RFC1779"; field public static final String RFC2253 = "RFC2253"; diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt index ffb05b33aa1..df4c80611a1 100644 --- a/api/module-lib-current.txt +++ b/api/module-lib-current.txt @@ -451,7 +451,48 @@ package java.nio { public class DirectByteBuffer extends java.nio.MappedByteBuffer { ctor public DirectByteBuffer(int, long, java.io.FileDescriptor, Runnable, boolean); method public final long address(); + method public final java.nio.CharBuffer asCharBuffer(); + method public final java.nio.DoubleBuffer asDoubleBuffer(); + method public final java.nio.FloatBuffer asFloatBuffer(); + method public final java.nio.IntBuffer asIntBuffer(); + method public final java.nio.LongBuffer asLongBuffer(); + method public final java.nio.ByteBuffer asReadOnlyBuffer(); + method public final java.nio.ShortBuffer asShortBuffer(); + method public final java.nio.ByteBuffer compact(); + method public final java.nio.MappedByteBuffer duplicate(); + method public final byte get(); + method public final byte get(int); + method public final char getChar(); + method public final char getChar(int); + method public final double getDouble(); + method public final double getDouble(int); + method public final float getFloat(); + method public final float getFloat(int); + method public int getInt(); + method public int getInt(int); + method public final long getLong(); + method public final long getLong(int); + method public final short getShort(); + method public final short getShort(int); + method public final boolean isDirect(); + method public final boolean isReadOnly(); + method public final java.nio.ByteBuffer put(byte); + method public final java.nio.ByteBuffer put(int, byte); + method public final java.nio.ByteBuffer putChar(char); + method public final java.nio.ByteBuffer putChar(int, char); + method public final java.nio.ByteBuffer putDouble(double); + method public final java.nio.ByteBuffer putDouble(int, double); + method public final java.nio.ByteBuffer putFloat(float); + method public final java.nio.ByteBuffer putFloat(int, float); + method public final java.nio.ByteBuffer putInt(int); + method public final java.nio.ByteBuffer putInt(int, int); + method public final java.nio.ByteBuffer putLong(long); + method public final java.nio.ByteBuffer putLong(int, long); + method public final java.nio.ByteBuffer putShort(short); + method public final java.nio.ByteBuffer putShort(int, short); method public final void setAccessible(boolean); + method public final java.nio.MappedByteBuffer slice(); + method public final java.nio.MappedByteBuffer slice(int, int); } public final class NIOAccess { diff --git a/dalvik/src/main/java/dalvik/system/ZygoteHooks.java b/dalvik/src/main/java/dalvik/system/ZygoteHooks.java index a0a66b87219..f1de769e528 100644 --- a/dalvik/src/main/java/dalvik/system/ZygoteHooks.java +++ b/dalvik/src/main/java/dalvik/system/ZygoteHooks.java @@ -159,8 +159,9 @@ public final class ZygoteHooks { @SystemApi(client = MODULE_LIBRARIES) public static void preFork() { Daemons.stop(); + // At this point Daemons have been joined, but they may still be Unregister()ing. + // We wait for that as part of nativePreFork(). token = nativePreFork(); - waitUntilAllThreadsStopped(); } /** @@ -259,17 +260,4 @@ public final class ZygoteHooks { String instructionSet); private static native boolean nativeZygoteLongSuspendOk(); - - /** - * We must not fork until we're single-threaded again. Wait until /proc shows we're - * down to just one thread. - */ - private static void waitUntilAllThreadsStopped() { - File tasks = new File("/proc/self/task"); - // All Java daemons are stopped already. We're just waiting for their OS counterparts to - // finish as well. This shouldn't take much time so spinning is ok here. - while (tasks.list().length > 1) { - Thread.yield(); - } - } } diff --git a/expectations/skippedCtsTest.txt b/expectations/skippedCtsTest.txt index a17b67cd36a..4ee04feb36c 100644 --- a/expectations/skippedCtsTest.txt +++ b/expectations/skippedCtsTest.txt @@ -1,67 +1,131 @@ +/* Do not modify directly. + * Generated by tools/non-cts-json-generator/update_skippedCtsTest.sh + * which dumps all @NonCts tests. + */ [ -{ - bug: 287231726, - description: "This test doesn't test public APIs.", - result: EXEC_FAILED, - names: [ - "libcore.libcore.icu.DateIntervalFormatTest", - "libcore.libcore.icu.ICUTest", - "libcore.libcore.icu.LocaleDataTest", - "libcore.sun.misc.SharedSecretsTest" - ] -}, -{ - bug: 287231726, - description: "The test asserts buggy or non-breaking behaviors, but the behavior has been fixed / changed in the future ART module version.", - result: EXEC_FAILED, - names: [ - "libcore.java.lang.ClassTest#test_toGenericString", - "libcore.java.util.CurrencyTest#test_localeExtension", - "libcore.java.text.OldDecimalFormatSymbolsTest#test_RIHarmony_compatible", - "libcore.java.text.OldNumberFormatTest#test_getCurrencyInstanceLjava_util_Locale", - "org.apache.harmony.tests.java.util.ArrayDequeTest#test_forEachRemaining_CME", - "org.apache.harmony.tests.java.util.ArrayDequeTest#test_iterator", - "org.apache.harmony.tests.java.lang.Character_UnicodeBlockTest#test_ofC", - "org.apache.harmony.tests.java.lang.Character_UnicodeBlockTest#test_ofI", - "org.apache.harmony.tests.java.util.PriorityQueueTest#test_remove_Ljava_lang_Object_not_Compatible", - "org.apache.harmony.tests.java.util.PriorityQueueTest#test_spliterator_CME", - "org.apache.harmony.regex.tests.java.util.regex.PatternTest#testSplitAsStream" - ] -}, -{ - bug: 287231726, - description: "The test depends on locale, but manufacturers / CLDR improves the locale data over time", - result: EXEC_FAILED, - names: [ - "libcore.java.text.DecimalFormatTest#testLocaleGroupingSeparator", - "libcore.java.text.DecimalFormatTest#testSetGroupingSeparator" - ] -}, -{ - bug: 286802267, - description: "The test depends on internal APIs.", - result: EXEC_FAILED, - names: [ - "test.java.time.TestClock_System#test_OffsetLimits", - "test.java.time.TestClock_System#test_OffsetRegular" - ] -}, -{ - bug: 286802267, - description: "The test asserts buggy or non-breaking behaviors, but the behavior has been fixed / changed in the future ART module version.", - result: EXEC_FAILED, - names: [ - "tck.java.time.TCKYear#factory_parse_fail", - "tck.java.time.format.TCKDateTimeParseResolver#test_resolveAmPm" - ] -}, -{ - bug: 286802267, - description: "The test depends on locale, but manufacturers / CLDR improves the locale data over time", - result: EXEC_FAILED, - names: [ - "test.java.time.format.TestUnicodeExtension#test_localizedBy", - "test.java.util.TestFormatter#test" - ] -} -] + { + "description": "Algorithm might not be available in the future", + "names": [ + "libcore.java.util.random.RandomGeneratorFactoryTest#createsL64X256MixRandomInstance" + ] + }, + { + "description": "No guarantees are provided around available implementations", + "names": [ + "libcore.java.util.random.RandomGeneratorFactoryTest#checkCurrentlyAvailableImplementations" + ] + }, + { + "description": "Test for internal APIs.", + "names": [ + "libcore.libcore.icu.DecimalFormatDataTest", + "libcore.libcore.icu.SimpleDateFormatDataTest" + ] + }, + { + "bug": 259671905, + "description": "The test asserts buggy or non-breaking behaviors, but the behavior has been fixed in a new mainline module version.", + "names": [ + "org.apache.harmony.security.tests.java.security.ProviderTest#testForEachCME" + ] + }, + { + "bug": 260847206, + "description": "The test asserts buggy or non-breaking behaviors, but the behavior has been fixed in a new mainline module version.", + "names": [ + "org.apache.harmony.tests.javax.security.OldSHA1PRNGSecureRandomTest#testGenerateSeedint01" + ] + }, + { + "bug": 286802267, + "description": "Test for internal APIs.", + "names": [ + "test.java.time.TestClock_System#test_OffsetLimits", + "test.java.time.TestClock_System#test_OffsetRegular" + ] + }, + { + "bug": 286802267, + "description": "The test asserts buggy or non-breaking behaviors, but the behavior has been fixed in a new mainline module version.", + "names": [ + "tck.java.time.TCKYear#factory_parse_fail", + "tck.java.time.format.TCKDateTimeParseResolver#test_resolveAmPm" + ] + }, + { + "bug": 286802267, + "description": "The test depends on locale, but manufacturers \/ CLDR improves the locale data over time.", + "names": [ + "test.java.time.format.TestUnicodeExtension#test_localizedBy", + "test.java.util.TestFormatter#test" + ] + }, + { + "bug": 287231726, + "description": "Test for internal APIs.", + "names": [ + "libcore.jdk.internal.access.SharedSecretsTest", + "libcore.libcore.icu.DateIntervalFormatTest", + "libcore.libcore.icu.ICUTest", + "libcore.libcore.icu.LocaleDataTest" + ] + }, + { + "bug": 287231726, + "description": "The test asserts buggy or non-breaking behaviors, but the behavior has been fixed in a new mainline module version.", + "names": [ + "libcore.java.lang.ClassTest#test_toGenericString", + "libcore.java.lang.ClassTest#toGenericString", + "libcore.java.text.OldDecimalFormatSymbolsTest#test_RIHarmony_compatible", + "libcore.java.text.OldNumberFormatTest#test_getCurrencyInstanceLjava_util_Locale", + "libcore.java.util.CurrencyTest#test_localeExtension", + "org.apache.harmony.regex.tests.java.util.regex.PatternTest#testSplitAsStream", + "org.apache.harmony.tests.java.lang.Character_UnicodeBlockTest#test_ofC", + "org.apache.harmony.tests.java.lang.Character_UnicodeBlockTest#test_ofI", + "org.apache.harmony.tests.java.util.ArrayDequeTest#test_forEachRemaining_CME", + "org.apache.harmony.tests.java.util.ArrayDequeTest#test_iterator", + "org.apache.harmony.tests.java.util.PriorityQueueTest#test_remove_Ljava_lang_Object_not_Compatible" + ] + }, + { + "bug": 287231726, + "description": "The test depends on locale, but manufacturers \/ CLDR improves the locale data over time.", + "names": [ + "libcore.java.text.DecimalFormatTest#testLocaleGroupingSeparator", + "libcore.java.text.DecimalFormatTest#testSetGroupingSeparator" + ] + }, + { + "bug": 310050493, + "description": "Test for internal APIs.", + "names": [ + "libcore.java.util.UUIDTest#testCurrentImplementation_invalidInputs", + "libcore.java.util.UUIDTest#testJava11Implementation_invalidInputs", + "libcore.java.util.UUIDTest#testJava8Implementation_allowsLongInputs" + ] + }, + { + "bug": 310050493, + "description": "The test asserts buggy or non-breaking behaviors, but the behavior has been fixed in a new mainline module version.", + "names": [ + "com.android.org.conscrypt.NativeCryptoArgTest#evpMethods", + "com.android.org.conscrypt.javax.crypto.CipherTest#test_PBKDF2WITHHMACSHA1_SKFactory_and_PBEAESCBC_Cipher_noIV", + "libcore.java.util.zip.GZIPOutputStreamTest#testShortMessage", + "org.apache.harmony.tests.java.util.zip.ZipOutputStreamTest#test_exttSupport" + ] + }, + { + "bug": 316502724, + "description": "SharedSecrets class is at different location in newer ART versions", + "names": [ + "libcore.sun.misc.SharedSecretsTest#testGetJavaIOFileDescriptorAccess_notNull" + ] + }, + { + "bug": 316502724, + "description": "The test was removed and its no longer throws CME", + "names": [ + "org.apache.harmony.tests.java.util.PriorityQueueTest#test_spliterator_CME" + ] + } +]
\ No newline at end of file diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ProcessManagerTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ProcessManagerTest.java index 477a8e2a26a..05d19929bfa 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ProcessManagerTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ProcessManagerTest.java @@ -16,6 +16,8 @@ package org.apache.harmony.tests.java.lang; +import android.platform.test.annotations.LargeTest; + import junit.framework.TestCase; import java.io.BufferedReader; @@ -25,12 +27,24 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; public class ProcessManagerTest extends TestCase { Thread thread = null; Process process = null; boolean isThrown = false; + private static final Path TEMP_DIR; + + static { + try { + TEMP_DIR = Files.createTempDirectory("process-manager-test"); + TEMP_DIR.toFile().deleteOnExit(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } public void testCat() throws IOException, InterruptedException { String[] commands = { "cat" }; @@ -156,24 +170,22 @@ public class ProcessManagerTest extends TestCase { thread.start(); } + @LargeTest public void testHeavyLoad() { int i; - for (i = 0; i < 100; i++) + for (i = 0; i < 30; i++) stuff(); } private static void stuff() { Runtime rt = Runtime.getRuntime(); try { - Process proc = rt.exec("ls"); + Process proc = rt.exec("ls " + TEMP_DIR.toString()); proc.waitFor(); - proc = null; } catch (Exception ex) { System.err.println("Failure: " + ex); throw new RuntimeException(ex); } - rt.gc(); - rt = null; } FileOutputStream out; diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/DecimalFormatTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/DecimalFormatTest.java index aca5247e8b6..d0f7430df01 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/DecimalFormatTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/DecimalFormatTest.java @@ -2053,7 +2053,8 @@ public class DecimalFormatTest extends TestCase { char current; // BigInteger. - iterator = new DecimalFormat().formatToCharacterIterator(new BigInteger("123456789")); + iterator = NumberFormat.getInstance(Locale.US) + .formatToCharacterIterator(new BigInteger("123456789")); runStarts = new int[] { 0, 0, 0, 3, 4, 4, 4, 7, 8, 8, 8 }; runLimits = new int[] { 3, 3, 3, 4, 7, 7, 7, 8, 11, 11, 11 }; result = "123,456,789"; @@ -2068,7 +2069,7 @@ public class DecimalFormatTest extends TestCase { assertEquals(11, iterator.getEndIndex()); // For BigDecimal with multiplier test. - DecimalFormat df = new DecimalFormat(); + DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(Locale.US); df.setMultiplier(10); iterator = df.formatToCharacterIterator(new BigDecimal("12345678901234567890")); result = "123,456,789,012,345,678,900"; @@ -2079,7 +2080,7 @@ public class DecimalFormatTest extends TestCase { } // For BigDecimal with multiplier test. - df = new DecimalFormat(); + df = (DecimalFormat) NumberFormat.getInstance(Locale.US); df.setMultiplier(-1); df.setMaximumFractionDigits(20); iterator = df.formatToCharacterIterator(new BigDecimal("1.23456789012345678901")); @@ -2090,7 +2091,8 @@ public class DecimalFormatTest extends TestCase { current = iterator.next(); } - iterator = new DecimalFormat().formatToCharacterIterator(new BigDecimal("1.23456789E301")); + iterator = NumberFormat.getInstance(Locale.US) + .formatToCharacterIterator(new BigDecimal("1.23456789E301")); runStarts = new int[] { 0, 0, 2, 3, 3, 3, 6, 7, 7, 7, 10, 11, 11, 11, 14 }; runLimits = new int[] { 2, 2, 3, 6, 6, 6, 7, 10, 10, 10, 11, 14, 14, 14, 15 }; result = "12,345,678,900,"; // 000,000,000,000.... @@ -2104,7 +2106,8 @@ public class DecimalFormatTest extends TestCase { assertEquals(0, iterator.getBeginIndex()); assertEquals(402, iterator.getEndIndex()); - iterator = new DecimalFormat().formatToCharacterIterator(new BigDecimal("1.2345678E4")); + iterator = NumberFormat.getInstance(Locale.US) + .formatToCharacterIterator(new BigDecimal("1.2345678E4")); runStarts = new int[] { 0, 0, 2, 3, 3, 3, 6, 7, 7, 7 }; runLimits = new int[] { 2, 2, 3, 6, 6, 6, 7, 10, 10, 10 }; result = "12,345.678"; @@ -2128,7 +2131,8 @@ public class DecimalFormatTest extends TestCase { Number number = new BigDecimal("1.23456789E1234"); assertEquals("1.23456789E+1234", number.toString()); - iterator = new DecimalFormat().formatToCharacterIterator(number); + iterator = NumberFormat.getInstance(Locale.US) + .formatToCharacterIterator(number); runStarts = new int[] { 0, 0, 2, 3, 3, 3, 6, 7, 7, 7, 10, 11, 11, 11, 14 }; runLimits = new int[] { 2, 2, 3, 6, 6, 6, 7, 10, 10, 10, 11, 14, 14, 14, 15 }; result = "12,345,678,900,"; // 000,000,000,000.... diff --git a/luni/src/main/java/javax/xml/datatype/DatatypeConfigurationException.java b/luni/src/main/java/javax/xml/datatype/DatatypeConfigurationException.java index d46d2cd6de1..f4ae2915994 100644 --- a/luni/src/main/java/javax/xml/datatype/DatatypeConfigurationException.java +++ b/luni/src/main/java/javax/xml/datatype/DatatypeConfigurationException.java @@ -149,6 +149,8 @@ public class DatatypeConfigurationException extends Exception { catch (Exception e) {} } + // BEGIN Android-removed: private method not called within the class + /* private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); @@ -167,4 +169,6 @@ public class DatatypeConfigurationException extends Exception { // Ignore exception catch (Exception e) {} } + */ + // END Android-removed: private method not called within the class } diff --git a/luni/src/main/java/libcore/net/NetworkSecurityPolicy.java b/luni/src/main/java/libcore/net/NetworkSecurityPolicy.java index aa7cde08301..f161747568d 100644 --- a/luni/src/main/java/libcore/net/NetworkSecurityPolicy.java +++ b/luni/src/main/java/libcore/net/NetworkSecurityPolicy.java @@ -48,7 +48,6 @@ public abstract class NetworkSecurityPolicy { * @hide */ @SystemApi(client = MODULE_LIBRARIES) - @libcore.api.IntraCoreApi public NetworkSecurityPolicy() { } diff --git a/luni/src/test/java/libcore/java/net/SocketTest.java b/luni/src/test/java/libcore/java/net/SocketTest.java index 8bb21eebd52..dca55a6f0c5 100644 --- a/luni/src/test/java/libcore/java/net/SocketTest.java +++ b/luni/src/test/java/libcore/java/net/SocketTest.java @@ -16,6 +16,23 @@ package libcore.java.net; +import static android.system.OsConstants.AF_INET; +import static android.system.OsConstants.AF_INET6; +import static android.system.OsConstants.SOCK_DGRAM; + +import static java.util.stream.Collectors.joining; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import android.system.ErrnoException; +import android.system.Os; + import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; @@ -48,11 +65,16 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import libcore.junit.junit3.TestCaseWithRules; import libcore.junit.util.ResourceLeakageDetector; + +import org.junit.Ignore; import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; import org.junit.rules.TestRule; - -public class SocketTest extends TestCaseWithRules { +@RunWith(JUnit4.class) +public class SocketTest { @Rule public TestRule resourceLeakageDetectorRule = ResourceLeakageDetector.getRule(); @@ -72,6 +94,7 @@ public class SocketTest extends TestCaseWithRules { private static final int INET_ECN_MASK = 0x3; // See http://b/2980559. + @Test public void test_close() throws Exception { Socket s = new Socket(); s.close(); @@ -84,6 +107,7 @@ public class SocketTest extends TestCaseWithRules { * This means they give incorrect results on closed sockets (as well * as requiring an unnecessary call into native code). */ + @Test public void test_getLocalAddress_after_close() throws Exception { Socket s = new Socket(); try { @@ -104,6 +128,7 @@ public class SocketTest extends TestCaseWithRules { } // http://code.google.com/p/android/issues/detail?id=7935 + @Test public void test_newSocket_connection_refused() throws Exception { try { new Socket("localhost", 80); @@ -114,6 +139,7 @@ public class SocketTest extends TestCaseWithRules { // http://code.google.com/p/android/issues/detail?id=3123 // http://code.google.com/p/android/issues/detail?id=1933 + @Test public void test_socketLocalAndRemoteAddresses() throws Exception { checkSocketLocalAndRemoteAddresses(false); checkSocketLocalAndRemoteAddresses(true); @@ -247,6 +273,7 @@ public class SocketTest extends TestCaseWithRules { // SocketOptions.setOption has weird behavior for setSoLinger/SO_LINGER. // This test ensures we do what the RI does. + @Test public void test_SocketOptions_setOption() throws Exception { MySocketImpl impl = new MySocketImpl(); Socket s = new MySocket(impl); @@ -295,6 +322,7 @@ public class SocketTest extends TestCaseWithRules { assertEquals(sockImpl.value, value); } + @Test public void test_setTrafficClass() throws Exception { try (Socket s = new Socket()) { for (int i = 0; i <= 255; ++i) { @@ -310,6 +338,7 @@ public class SocketTest extends TestCaseWithRules { } } + @Test public void testReadAfterClose() throws Exception { MockServer server = new MockServer(); server.enqueue(new byte[]{5, 3}, 0); @@ -332,6 +361,7 @@ public class SocketTest extends TestCaseWithRules { server.shutdown(); } + @Test public void testWriteAfterClose() throws Exception { MockServer server = new MockServer(); server.enqueue(new byte[0], 3); @@ -352,6 +382,7 @@ public class SocketTest extends TestCaseWithRules { } // http://b/5534202 + @Test public void testAvailable() throws Exception { for (int i = 0; i < 100; i++) { assertAvailableReturnsZeroAfterSocketReadsAllData(); @@ -389,6 +420,7 @@ public class SocketTest extends TestCaseWithRules { serverSocket.close(); } + @Test public void testInitialState() throws Exception { Socket s = new Socket(); try { @@ -408,6 +440,7 @@ public class SocketTest extends TestCaseWithRules { } } + @Test public void testStateAfterClose() throws Exception { Socket s = new Socket(); s.bind(new InetSocketAddress(Inet4Address.getLocalHost(), 0)); @@ -425,6 +458,7 @@ public class SocketTest extends TestCaseWithRules { assertEquals(boundAddress.getPort(), localAddressAfterClose.getPort()); } + @Test public void testCloseDuringConnect() throws Exception { // This address is reserved for documentation: should never be reachable and therefore // is expected to produce block behavior when attempting to connect(). @@ -481,6 +515,7 @@ public class SocketTest extends TestCaseWithRules { } // http://b/29092095 + @Test public void testSocketWithProxySet() throws Exception { ProxySelector ps = ProxySelector.getDefault(); try { @@ -508,6 +543,7 @@ public class SocketTest extends TestCaseWithRules { // b/25805791 + b/26470377 + @Test public void testFileDescriptorStaysSame() throws Exception { // SocketImplementation FileDescriptor object shouldn't change after calling // bind (and many other methods). @@ -571,6 +607,7 @@ public class SocketTest extends TestCaseWithRules { } // b/26354315 + @Test public void testDoNotCallCloseFromSocketCtor() { // Original openJdk7 Socket implementation may call Socket#close() inside a constructor. // In this case, classes that extend Socket wont be fully constructed when they @@ -635,6 +672,8 @@ public class SocketTest extends TestCaseWithRules { } // b/30007735 + @Ignore("b/292238663") + @Test public void testSocketTestAllAddresses() throws Exception { checkLoopbackHost(); diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java index e823777ed5f..7b00d1d5488 100644 --- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java +++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java @@ -30,6 +30,7 @@ import java.lang.reflect.Field; import java.net.ContentHandler; import java.net.ContentHandlerFactory; import org.junit.After; +import org.junit.Assume; import org.junit.Before; import org.junit.Test; @@ -3136,21 +3137,26 @@ public final class URLConnectionTest { } @Test public void noSslFallback_specifiedProtocols() throws Exception { - String[] enabledProtocols = { "TLSv1.3", "TLSv1.2", "TLSv1.1" }; + String[] platformProtocols = platformDefaultTlsProtocols(); + Assume.assumeTrue(platformProtocols.length > 1); + // Leave out one protocol. First in the array will be the oldest protocol with + // Conscrypt, but it shouldn't matter which we omit. + String[] expectedProtocols = + Arrays.copyOfRange(platformProtocols, 1, platformProtocols.length); + TestSSLContext testSSLContext = createDefaultTestSSLContext(); SSLSocketFactory serverSocketFactory = new LimitedProtocolsSocketFactory( testSSLContext.serverContext.getSocketFactory(), - enabledProtocols); + expectedProtocols); SSLSocketFactory clientSocketFactory = new LimitedProtocolsSocketFactory( - testSSLContext.clientContext.getSocketFactory(), enabledProtocols); + testSSLContext.clientContext.getSocketFactory(), expectedProtocols); checkNoFallbackOnFailedHandshake(clientSocketFactory, serverSocketFactory, - enabledProtocols); + expectedProtocols); } @Test public void noSslFallback_defaultProtocols() throws Exception { - // Will need to be updated if the enabled protocols in Android's SSLSocketFactory change - String[] expectedEnabledProtocols = { "TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1" }; + String[] expectedEnabledProtocols = platformDefaultTlsProtocols(); TestSSLContext testSSLContext = createDefaultTestSSLContext(); SSLSocketFactory serverSocketFactory = testSSLContext.serverContext.getSocketFactory(); @@ -3159,6 +3165,13 @@ public final class URLConnectionTest { expectedEnabledProtocols); } + private String[] platformDefaultTlsProtocols() throws Exception { + try (SSLSocket socket = (SSLSocket) SSLContext.getDefault().getSocketFactory() + .createSocket()) { + return socket.getEnabledProtocols(); + } + } + private static void assertSslSocket(TlsFallbackDisabledScsvSSLSocket socket, boolean expectedWasFallbackScsvSet, String... expectedEnabledProtocols) { Set<String> enabledProtocols = diff --git a/luni/src/test/java/libcore/java/nio/CharBufferTest.java b/luni/src/test/java/libcore/java/nio/CharBufferTest.java index 26e57783655..4b90444135f 100644 --- a/luni/src/test/java/libcore/java/nio/CharBufferTest.java +++ b/luni/src/test/java/libcore/java/nio/CharBufferTest.java @@ -54,4 +54,12 @@ public class CharBufferTest extends TestCase { assertEquals((int) low, cb.codePoints().toArray()[1]); // Unmatched surrogate. assertEquals((int) '0', cb.codePoints().toArray()[2]); } + + public void testEmpty() { + String s = "Hello\n\tworld"; + CharBuffer cb = CharBuffer.allocate(0); + assertTrue(cb.isEmpty()); + cb = cb.allocate(32).append(s); + assertFalse(cb.isEmpty()); + } } diff --git a/luni/src/test/java/libcore/java/nio/channels/MembershipKeyTest.java b/luni/src/test/java/libcore/java/nio/channels/MembershipKeyTest.java index 427789d48f4..42c15600222 100644 --- a/luni/src/test/java/libcore/java/nio/channels/MembershipKeyTest.java +++ b/luni/src/test/java/libcore/java/nio/channels/MembershipKeyTest.java @@ -33,24 +33,25 @@ import java.nio.channels.MembershipKey; public class MembershipKeyTest extends TestCase { - private MembershipKey key; - private final int PORT = 5000; private final String TEST_MESSAGE = "hello"; + private static final InetAddress MULTICAST_ADDRESS = getMulticastAddress(); + private static final NetworkInterface NETWORK_INTERFACE = getNetworkInterface(); + + private MembershipKey key; + private int port = -1; private DatagramChannel client; - private InetAddress sourceAddress = Inet4Address.LOOPBACK; - private final static InetAddress MULTICAST_ADDRESS = getMulticastAddress(); - private final static NetworkInterface NETWORK_INTERFACE = getNetworkInterface(); + private final InetAddress sourceAddress = Inet4Address.LOOPBACK; private void init(boolean withSource) throws Exception { client = DatagramChannel.open(StandardProtocolFamily.INET) - .bind(new InetSocketAddress(Inet4Address.ANY, PORT)); + .bind(new InetSocketAddress(Inet4Address.ANY, 0)); client.configureBlocking(false); - if (withSource) { key = client.join(MULTICAST_ADDRESS, NETWORK_INTERFACE, sourceAddress); } else { key = client.join(MULTICAST_ADDRESS, NETWORK_INTERFACE); } + port = client.socket().getLocalPort(); } @Override @@ -107,7 +108,7 @@ public class MembershipKeyTest extends TestCase { assertEquals(TEST_MESSAGE.length(), dc .bind(new InetSocketAddress(Inet4Address.LOOPBACK, 0)) .send(ByteBuffer.wrap(TEST_MESSAGE.getBytes()), - new InetSocketAddress(MULTICAST_ADDRESS, PORT))); + new InetSocketAddress(MULTICAST_ADDRESS, port))); } ByteBuffer buffer = ByteBuffer.allocate(1048); @@ -173,7 +174,7 @@ public class MembershipKeyTest extends TestCase { assertEquals(TEST_MESSAGE.length(), dc .bind(new InetSocketAddress(Inet4Address.LOOPBACK, 0)) .send(ByteBuffer.wrap(TEST_MESSAGE.getBytes()), - new InetSocketAddress(MULTICAST_ADDRESS, PORT))); + new InetSocketAddress(MULTICAST_ADDRESS, port))); } ByteBuffer buffer = ByteBuffer.allocate(1048); @@ -223,14 +224,14 @@ public class MembershipKeyTest extends TestCase { .bind(new InetSocketAddress(Inet4Address.LOOPBACK, 0)) .setOption(StandardSocketOptions.IP_MULTICAST_LOOP, true /* enable loop */) .send(ByteBuffer.wrap(TEST_MESSAGE.getBytes()), - new InetSocketAddress(MULTICAST_ADDRESS, PORT))); + new InetSocketAddress(MULTICAST_ADDRESS, port))); } ByteBuffer buffer = ByteBuffer.allocate(1048); client.receive(buffer); buffer.flip(); int limits = buffer.limit(); - byte bytes[] = new byte[limits]; + byte[] bytes = new byte[limits]; buffer.get(bytes, 0, limits); String receivedMessage = new String(bytes); assertEquals(TEST_MESSAGE, receivedMessage); diff --git a/luni/src/test/java/libcore/java/security/cert/CertPathValidatorTest.java b/luni/src/test/java/libcore/java/security/cert/CertPathValidatorTest.java index fc09ae83125..8f968fe6fd9 100644 --- a/luni/src/test/java/libcore/java/security/cert/CertPathValidatorTest.java +++ b/luni/src/test/java/libcore/java/security/cert/CertPathValidatorTest.java @@ -28,6 +28,8 @@ import java.security.cert.PKIXRevocationChecker; import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; import java.security.cert.PKIXRevocationChecker.Option; +import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -126,7 +128,11 @@ public class CertPathValidatorTest extends TestCaseWithRules { } public void test_OCSP_EndEntity_KeyCompromise_Failure() throws Exception { - runOCSPStapledTest(new RevokedStatus(new Date(), CRLReason.keyCompromise), false); + // RFC 6960 isn't specific about what happens if the revocation time is the + // current second but RevocationChecker checks whether it's strictly before, + // so we subtract one second from now to be sure of the revocation check triggering. + Date date = Date.from(Instant.now().minus(1, ChronoUnit.SECONDS)); + runOCSPStapledTest(new RevokedStatus(date, CRLReason.keyCompromise), false); } public void test_OCSP_EndEntity_Good_Success() throws Exception { diff --git a/luni/src/test/java/libcore/java/text/DateFormatTest.java b/luni/src/test/java/libcore/java/text/DateFormatTest.java index 5723b636d12..b19d55c008f 100644 --- a/luni/src/test/java/libcore/java/text/DateFormatTest.java +++ b/luni/src/test/java/libcore/java/text/DateFormatTest.java @@ -18,6 +18,11 @@ package libcore.java.text; import android.icu.util.VersionInfo; +import dalvik.annotation.compat.VersionCodes; + +import libcore.test.annotation.NonMts; +import libcore.test.reasons.NonMtsReasons; + import junit.framework.TestCase; import java.text.DateFormat; @@ -70,6 +75,8 @@ public class DateFormatTest extends TestCase { } /** Regression test for http://b/266731719. */ + @NonMts(bug = 289015017, disabledUntilSdk = VersionCodes.UPSIDE_DOWN_CAKE, + reason = NonMtsReasons.OEM_CUSTOMIZATION) public void testParse_lenient_en() throws ParseException { assertParse_lenient_en(Locale.ENGLISH); assertParse_lenient_en(Locale.US); @@ -92,6 +99,8 @@ public class DateFormatTest extends TestCase { } /** Regression test for http://b/266731719. */ + @NonMts(bug = 289015017, disabledUntilSdk = VersionCodes.UPSIDE_DOWN_CAKE, + reason = NonMtsReasons.OEM_CUSTOMIZATION) public void testFormat_forBug266731719() { assertFormat_forBug266731719(Locale.ENGLISH); assertFormat_forBug266731719(Locale.US); diff --git a/luni/src/test/java/libcore/java/time/format/DateTimeFormatterBuilderTest.java b/luni/src/test/java/libcore/java/time/format/DateTimeFormatterBuilderTest.java index 215f4837fac..653ca937b57 100644 --- a/luni/src/test/java/libcore/java/time/format/DateTimeFormatterBuilderTest.java +++ b/luni/src/test/java/libcore/java/time/format/DateTimeFormatterBuilderTest.java @@ -25,8 +25,10 @@ import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; +import java.time.format.TextStyle; import java.time.temporal.TemporalQueries; import java.util.Locale; +import java.util.Set; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; @@ -89,4 +91,29 @@ public class DateTimeFormatterBuilderTest { assertEquals(ZoneOffset.ofHours(1), formatter.parse("+01:00").query(TemporalQueries.zoneId())); } + + @Test + public void test_appendGenericZoneText() { + DateTimeFormatter formatter = new DateTimeFormatterBuilder() + .appendGenericZoneText(TextStyle.FULL) + .toFormatter(Locale.US); + + assertEquals("Pacific Time", formatter.format( + ZonedDateTime.now(ZoneId.of("America/Los_Angeles")))); + + formatter = new DateTimeFormatterBuilder() + .appendGenericZoneText(TextStyle.SHORT) + .toFormatter(Locale.US); + + assertEquals("PT", formatter.format( + ZonedDateTime.now(ZoneId.of("America/Los_Angeles")))); + + formatter = new DateTimeFormatterBuilder() + .appendGenericZoneText(TextStyle.FULL, Set.of(ZoneId.of("America/Los_Angeles"))) + .toFormatter(Locale.US); + + // "America/Los_Angeles" is expected because the zone is in the preferred set. + assertEquals(ZoneId.of("America/Los_Angeles"), + formatter.parse("Pacific Time").query(TemporalQueries.zoneId())); + } } diff --git a/luni/src/test/java/libcore/java/util/ArraysTest.java b/luni/src/test/java/libcore/java/util/ArraysTest.java index a45ccd2bf6e..c2f2c546b6b 100644 --- a/luni/src/test/java/libcore/java/util/ArraysTest.java +++ b/luni/src/test/java/libcore/java/util/ArraysTest.java @@ -566,6 +566,28 @@ public class ArraysTest { } } + /** + * java.util.Array#parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>) + */ + @Test + public void parallelPrefix$TII_biggerArray() { + String[] strings = new String[1_000]; + int begin = 0, end = strings.length; + + for (int i = 0; i < strings.length; ++i) { + strings[i] = String.valueOf(i); + } + + Arrays.parallelPrefix(strings, begin, end, (x, y) -> x + y); + + String currentPrefix = ""; + for (int i = 0; i < strings.length; ++i) { + currentPrefix += String.valueOf(i); + + assertEquals(currentPrefix, strings[i]); + } + } + // http://b/74236526 @Test public void deepEquals_nestedArraysOfDifferentTypesButEqualValues() { diff --git a/luni/src/test/java/libcore/java/util/FormatterTest.java b/luni/src/test/java/libcore/java/util/FormatterTest.java index e54428f2092..f600e3bddf7 100644 --- a/luni/src/test/java/libcore/java/util/FormatterTest.java +++ b/luni/src/test/java/libcore/java/util/FormatterTest.java @@ -16,6 +16,8 @@ package libcore.java.util; +import static org.junit.Assert.assertThrows; + import static java.nio.charset.StandardCharsets.UTF_8; import java.io.File; @@ -28,11 +30,13 @@ import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import java.util.Calendar; +import java.util.FormatFlagsConversionMismatchException; import java.util.Formatter; import java.util.GregorianCalendar; import java.util.Locale; import java.util.TimeZone; +@SuppressWarnings("FormatString") public class FormatterTest extends junit.framework.TestCase { private File aFile; @@ -292,4 +296,14 @@ public class FormatterTest extends junit.framework.TestCase { // expected } } + + public void test_floatWithAlternateForm() { + // when # flag is set, decimal separator is always present. + assertEquals("10.", new Formatter(Locale.US).format("%#.0f", 10.12).toString()); + } + + public void test_numberSignIsNotAllowed_inGeneralFormat() { + assertThrows(FormatFlagsConversionMismatchException.class, + () -> new Formatter(Locale.US).format("%#.1g", 10.1).toString()); + } } diff --git a/luni/src/test/java/libcore/java/util/LocaleTest.java b/luni/src/test/java/libcore/java/util/LocaleTest.java index f7f0074507a..2a87fc48679 100644 --- a/luni/src/test/java/libcore/java/util/LocaleTest.java +++ b/luni/src/test/java/libcore/java/util/LocaleTest.java @@ -160,13 +160,13 @@ public class LocaleTest extends junit.framework.TestCase { } public void test_getDisplayCountry_8870289() throws Exception { - assertEquals("Hong Kong", new Locale("", "HK").getDisplayCountry(Locale.US)); - assertEquals("Palestine", new Locale("", "PS").getDisplayCountry(Locale.US)); + assertTrue(new Locale("", "HK").getDisplayCountry(Locale.US).contains("Hong Kong")); + assertTrue(new Locale("", "PS").getDisplayCountry(Locale.US).contains("Palestine")); - assertEquals("Cocos (Keeling) Islands", new Locale("", "CC").getDisplayCountry(Locale.US)); - assertEquals("Falkland Islands (Islas Malvinas)", new Locale("", "FK").getDisplayCountry(Locale.US)); - assertEquals("Myanmar (Burma)", new Locale("", "MM").getDisplayCountry(Locale.US)); - assertEquals("Taiwan", new Locale("", "TW").getDisplayCountry(Locale.US)); + assertTrue(new Locale("", "CC").getDisplayCountry(Locale.US).contains("Cocos (Keeling) Islands")); + assertTrue(new Locale("", "FK").getDisplayCountry(Locale.US).contains("Falkland Islands (Islas Malvinas)")); + assertTrue(new Locale("", "MM").getDisplayCountry(Locale.US).contains("Myanmar (Burma)")); + assertTrue(new Locale("", "TW").getDisplayCountry(Locale.US).contains("Taiwan")); } public void test_tl_and_fil() throws Exception { diff --git a/luni/src/test/java/libcore/java/util/OptionalLongTest.java b/luni/src/test/java/libcore/java/util/OptionalLongTest.java index 47858f35ff4..9c761a9c3ae 100644 --- a/luni/src/test/java/libcore/java/util/OptionalLongTest.java +++ b/luni/src/test/java/libcore/java/util/OptionalLongTest.java @@ -16,9 +16,14 @@ package libcore.java.util; +import static org.junit.Assert.assertThrows; + import junit.framework.TestCase; +import org.junit.Assert; + import java.io.IOException; +import java.util.List; import java.util.NoSuchElementException; import java.util.OptionalLong; import java.util.concurrent.atomic.AtomicLong; @@ -90,6 +95,46 @@ public class OptionalLongTest extends TestCase { assertFalse(OptionalLong.of(57).equals(OptionalLong.of(56))); } + public void test_isPresentOrElse_whenEmpty() { + var heldValueHolder = new AtomicLong(-1); + var whenEmptyHolder = new AtomicLong(-1); + + OptionalLong.empty().ifPresentOrElse(heldValueHolder::set, () -> whenEmptyHolder.set(42)); + + assertEquals(42, whenEmptyHolder.get()); + assertEquals(-1, heldValueHolder.get()); + } + + public void test_isPresentOrElse_whenNonEmpty() { + var heldValueHolder = new AtomicLong(-1); + var whenEmptyHolder = new AtomicLong(-1); + + OptionalLong.of(1001L).ifPresentOrElse(heldValueHolder::set, () -> whenEmptyHolder.set(42)); + + assertEquals(-1, whenEmptyHolder.get()); + assertEquals(1001L, heldValueHolder.get()); + } + + public void test_orElseThrow_nonEmpty() { + assertEquals(43, OptionalLong.of(43).orElseThrow()); + } + + public void test_orElseThrow_empty() { + assertThrows(NoSuchElementException.class, () -> OptionalLong.empty().orElseThrow()); + } + + public void test_stream_nonEmpty() { + var elements = OptionalLong.of(42).stream().boxed().toList(); + + assertEquals(List.of(42L), elements); + } + + public void test_stream_empty() { + var elements = OptionalLong.empty().stream().boxed().toList(); + + assertEquals(List.of(), elements); + } + public void testHashCode() { assertEquals(Long.hashCode(57), OptionalLong.of(57).hashCode()); } diff --git a/luni/src/test/java/libcore/java/util/SimpleTimeZoneTest.java b/luni/src/test/java/libcore/java/util/SimpleTimeZoneTest.java index 2bedf7c9bc6..c63d53b1145 100644 --- a/luni/src/test/java/libcore/java/util/SimpleTimeZoneTest.java +++ b/luni/src/test/java/libcore/java/util/SimpleTimeZoneTest.java @@ -16,6 +16,8 @@ package libcore.java.util; +import static org.junit.Assert.assertThrows; + import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; @@ -181,6 +183,33 @@ public class SimpleTimeZoneTest extends TestCase { checkDstNewYork2014(timeZone); } + public void testNegativeDST_isNotAllowed() { + assertThrows(IllegalArgumentException.class, () -> new SimpleTimeZone( + /* rawOffset= */ 0, + /* ID= */ "ID", + /* startMonth= */ Calendar.MARCH, + /* startDay= */ 0, + /* startDayOfWeek= */ Calendar.SUNDAY, + /* startTime= */ 0, + /* startTimeMode= */ 0, + /* endMonth= */ Calendar.NOVEMBER, + /* endDay= */ 0, + /* endDayOfWeek= */ Calendar.SUNDAY, + /* endTime= */ 0, + /* endTimeMode= */ 0, + /* dstSavings= */ -36_000)); // this is not valid according to the implementation. + } + + public void testGetOffset_BC() { + var actualOffset = 123456; + TimeZone utc = new SimpleTimeZone(actualOffset, "LMT somewhere"); + + int returnedOffset = + utc.getOffset(GregorianCalendar.BC, 100, Calendar.JANUARY, 10, Calendar.SUNDAY, 0); + + assertEquals(actualOffset, returnedOffset); + } + /** * Check that the DST transitions in the supplied {@link TimeZone} are as expected for * America/New_York in 2014. diff --git a/luni/src/test/java/libcore/java/util/WeakHashMapTest.java b/luni/src/test/java/libcore/java/util/WeakHashMapTest.java index a33eb826af3..2cac89af101 100644 --- a/luni/src/test/java/libcore/java/util/WeakHashMapTest.java +++ b/luni/src/test/java/libcore/java/util/WeakHashMapTest.java @@ -16,9 +16,14 @@ package libcore.java.util; +import static org.junit.Assert.assertNotEquals; + import junit.framework.TestCase; +import java.lang.reflect.Field; import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.Map; import java.util.WeakHashMap; public class WeakHashMapTest extends TestCase { @@ -68,6 +73,114 @@ public class WeakHashMapTest extends TestCase { assertEquals(data.length, map.size()); } + public void testContainsNullValue() { + var map = new WeakHashMap<String, String>(); + + assertFalse(map.containsValue(null)); + + map.put("key", "value"); + + assertFalse(map.containsValue(null)); + + map.put("key", null); + + assertTrue(map.containsValue(null)); + } + + public void testEntrySet_removeMapping() { + var map = new WeakHashMap<String, String>(); + assertFalse(map.entrySet().remove(new Object())); + + assertFalse(map.entrySet().remove(Map.entry("key", "value"))); + + map.put("key", "value"); + + assertTrue(map.entrySet().remove(Map.entry("key", "value"))); + assertTrue(map.isEmpty()); + } + + public void testEntrySet_clear() { + var map = new WeakHashMap<String, String>(); + + map.put("key", "value"); + + map.entrySet().clear(); + + assertTrue(map.isEmpty()); + } + + public void testEntrySet_entrySetValue() { + var map = new WeakHashMap<String, String>(); + + map.put("key", "value"); + + var entry = map.entrySet().iterator().next(); + + entry.setValue("new value"); + + assertEquals("new value", map.get("key")); + } + + public void testEntrySet_entryEquals() { + var map = new WeakHashMap<String, String>(); + + map.put("key", "value"); + + var entry = map.entrySet().iterator().next(); + + assertNotEquals(entry, new Object()); + assertNotEquals(entry, Map.entry("key", "another value")); + } + + public void testKeySet_remove() { + var map = new WeakHashMap<String, String>(); + + map.put("key", "value"); + var keys = map.keySet(); + + assertFalse(keys.remove(new Object())); + } + + public void testKeySet_clear() { + var map = new WeakHashMap<String, String>(); + + map.put("key", "value"); + map.keySet().clear(); + + assertTrue(map.isEmpty()); + } + + public void testValues_clear() { + var map = new WeakHashMap<String, String>(); + + map.put("key", "value"); + map.values().clear(); + + assertTrue(map.isEmpty()); + } + + public void test_putAll() throws Throwable { + var map = new WeakHashMap<String, String>(); + + int threshold = threshold(map); + var anotherMap = new HashMap<String, String>(); + + for (int i = 0; i < 2 * threshold; ++i) { + anotherMap.put(String.valueOf(i), "value"); + } + + // This should trigger resize. + map.putAll(anotherMap); + + assertEquals(anotherMap, map); + } + + private int threshold(WeakHashMap map) throws Exception { + Field threshold = map.getClass().getDeclaredField("threshold"); + threshold.setAccessible(true); + return (int) threshold.get(map); + } + private void initializeData() { for (int i = 0; i < data.length; i++) { data[i] = new Data(); diff --git a/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConfigurationExceptionTest.java b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConfigurationExceptionTest.java index 3b6708d6b36..e26ca19a79f 100644 --- a/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConfigurationExceptionTest.java +++ b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConfigurationExceptionTest.java @@ -16,13 +16,19 @@ package libcore.javax.xml.datatype; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNull; import javax.xml.datatype.DatatypeConfigurationException; + import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; + @RunWith(JUnit4.class) public class DatatypeConfigurationExceptionTest { @@ -48,4 +54,35 @@ public class DatatypeConfigurationExceptionTest { assertEquals("java.lang.Throwable", e.getMessage()); assertEquals(t, e.getCause()); } + + @Test + public void testPrintStackTrace_noArgs() { + Throwable t = new Throwable(); + DatatypeConfigurationException e = new DatatypeConfigurationException(t); + e.printStackTrace(); + } + + @Test + public void testPrintStackTrace_withPrintStream() { + Throwable t = new Throwable(); + DatatypeConfigurationException e = new DatatypeConfigurationException(t); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(baos, true); + e.printStackTrace(ps); + + assertNotEquals(-1, baos.toString().indexOf("javax.xml.datatype.DatatypeConfigurationException")); + } + + @Test + public void testPrintStackTrace_withPrintWriter() { + Throwable t = new Throwable(); + DatatypeConfigurationException e = new DatatypeConfigurationException(t); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintWriter pw = new PrintWriter(baos, true); + e.printStackTrace(pw); + + assertNotEquals(-1, baos.toString().indexOf("javax.xml.datatype.DatatypeConfigurationException")); + } } diff --git a/luni/src/test/java/libcore/javax/xml/datatype/DatatypeFactoryTest.java b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeFactoryTest.java index d062d3cf666..59c3ba4e838 100644 --- a/luni/src/test/java/libcore/javax/xml/datatype/DatatypeFactoryTest.java +++ b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeFactoryTest.java @@ -91,6 +91,33 @@ public class DatatypeFactoryTest extends TestCase { assertNull(duration); } + public void testNewDurationDayTime_nullString() { + try { + factory.newDurationDayTime(null); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // expected + } + } + + public void testNewDurationDayTime_lexicalRepresentationContainsY() { + try { + factory.newDurationDayTime("Y"); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + // expected + } + } + + public void testNewDurationDayTime_lexicalRepresentationContainsM() { + try { + factory.newDurationDayTime("M"); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + // expected + } + } + public void testNewDurationDayTime_long() { Duration duration = factory.newDuration(1000L); assertEquals(0, duration.getYears()); @@ -107,6 +134,38 @@ public class DatatypeFactoryTest extends TestCase { assertEquals(0, duration.getHours()); assertEquals(0, duration.getMinutes()); assertEquals(1, duration.getSeconds()); + + duration = factory.newDurationDayTime(-1000L); + assertEquals(0, duration.getYears()); + assertEquals(0, duration.getMonths()); + assertEquals(0, duration.getDays()); + assertEquals(0, duration.getHours()); + assertEquals(0, duration.getMinutes()); + assertEquals(1, duration.getSeconds()); + + duration = factory.newDurationDayTime(0); + assertEquals(0, duration.getYears()); + assertEquals(0, duration.getMonths()); + assertEquals(0, duration.getDays()); + assertEquals(0, duration.getHours()); + assertEquals(0, duration.getMinutes()); + assertEquals(0, duration.getSeconds()); + + duration = factory.newDurationDayTime(Long.MIN_VALUE); + assertEquals(0, duration.getYears()); + assertEquals(0, duration.getMonths()); + assertEquals(0, duration.getDays()); + assertEquals(7, duration.getHours()); + assertEquals(12, duration.getMinutes()); + assertEquals(55, duration.getSeconds()); + + duration = factory.newDurationDayTime(12345L); + assertEquals(0, duration.getYears()); + assertEquals(0, duration.getMonths()); + assertEquals(0, duration.getDays()); + assertEquals(0, duration.getHours()); + assertEquals(0, duration.getMinutes()); + assertEquals(12, duration.getSeconds()); } public void testNewDurationYearMonth_bii() { @@ -134,6 +193,33 @@ public class DatatypeFactoryTest extends TestCase { assertNull(duration); } + public void testNewDurationYearMonth_nullString() { + try { + factory.newDurationYearMonth(null); + fail("Expected NullPointerException"); + } catch (NullPointerException e) { + // expected + } + } + + public void testNewDurationYearMonth_lexicalRepresentationContainsD() { + try { + factory.newDurationYearMonth("D"); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected + } + } + + public void testNewDurationYearMonth_lexicalRepresentationContainsT() { + try { + factory.newDurationYearMonth("T"); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected + } + } + public void testNewDurationYearMonth_long() { Duration duration = factory.newDurationYearMonth(1000); assertEquals(0, duration.getYears()); @@ -162,10 +248,33 @@ public class DatatypeFactoryTest extends TestCase { } } + public void testNewInstance_nullClassLoader() { + try { + DatatypeFactory.newInstance("factoryClassName", null); + fail("Unexpectedly created new instance"); + } catch (DatatypeConfigurationException expected) { + // class loading disabled + } + } + public void testNewXMLGregorianCalendar_iiiiiii() { XMLGregorianCalendar calendar = factory.newXMLGregorianCalendar( 1, 2, 3, 4, 5, 6, 7, 0); assertNull(calendar); + + try { + factory.newXMLGregorianCalendar(1, 2, 3, 4, 5, 6, -1, 0); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // Expected + } + + try { + factory.newXMLGregorianCalendar(1, 2, 3, 4, 5, 6, 1001, 0); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // Expected + } } public void testNewXMLGregorianCalendarDate_iiii() { @@ -181,6 +290,20 @@ public class DatatypeFactoryTest extends TestCase { public void testNewXMLGregorianCalendarTime_iiiii() { XMLGregorianCalendar calendar = factory.newXMLGregorianCalendarTime(4, 5, 6, 7, 0); assertNull(calendar); + + try { + factory.newXMLGregorianCalendarTime(4, 5, 6, -1, 0); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // Expected + } + + try { + factory.newXMLGregorianCalendarTime(4, 5, 6, 1001, 0); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // Expected + } } public void testNewXMLGregorianCalendarTime_BigDecimal() { @@ -238,6 +361,5 @@ public class DatatypeFactoryTest extends TestCase { BigDecimal fractionalSecond, int timezone) { return null; } - } } diff --git a/luni/src/test/java/libcore/javax/xml/datatype/XMLGregorianCalendarTest.java b/luni/src/test/java/libcore/javax/xml/datatype/XMLGregorianCalendarTest.java index 012facc595c..553724c72ee 100644 --- a/luni/src/test/java/libcore/javax/xml/datatype/XMLGregorianCalendarTest.java +++ b/luni/src/test/java/libcore/javax/xml/datatype/XMLGregorianCalendarTest.java @@ -15,6 +15,8 @@ */ package libcore.javax.xml.datatype; +import static org.junit.Assert.assertNotEquals; + import java.math.BigDecimal; import java.math.BigInteger; import java.util.GregorianCalendar; @@ -65,6 +67,97 @@ public class XMLGregorianCalendarTest extends TestCase { assertEquals(BigDecimal.valueOf(0.1), calendar.getFractionalSecond()); } + public void testEquals_differentObjectParam() { + assertNotEquals(Integer.valueOf(0), calendar); + } + + public void testEquals_nullObjectParam() { + assertNotEquals(null, calendar); + } + + public void testEquals_equalObjectParam() { + calendar.setYear(2023); + calendar.setMonth(6); + calendar.setDay(28); + calendar.setTime(23, 59, 59, BigDecimal.valueOf(0.1)); + + XMLGregorianCalendar anotherCalendar = new XMLGregorianCalendarImpl(); + anotherCalendar.setYear(2023); + anotherCalendar.setMonth(6); + anotherCalendar.setDay(28); + anotherCalendar.setTime(23, 59, 59, BigDecimal.valueOf(0.1)); + + assertEquals(calendar, anotherCalendar); + } + + public void testEquals_differentCalendarParam() { + calendar.setYear(2023); + calendar.setMonth(6); + calendar.setDay(28); + calendar.setTime(23, 59, 59, BigDecimal.valueOf(0.1)); + + XMLGregorianCalendar anotherCalendar = new XMLGregorianCalendarImpl(); + anotherCalendar.setYear(2023); + anotherCalendar.setMonth(7); // different month + anotherCalendar.setDay(28); + anotherCalendar.setTime(23, 59, 59, BigDecimal.valueOf(0.1)); + + assertNotEquals(calendar, anotherCalendar); + } + + public void testToString() { + calendar.setYear(2006); + calendar.setMonth(10); + calendar.setDay(23); + calendar.setTime(22, 15, 1, BigDecimal.valueOf(0.000000135)); + calendar.setTimezone(0); + + assertEquals(calendar.toXMLFormat(), calendar.toString()); + } + + public void testHashCode_sameTimeSameTimezone() { + calendar.setTimezone(0); + + XMLGregorianCalendarImpl anotherCalendar = new XMLGregorianCalendarImpl(); + anotherCalendar.setTimezone(0); + + assertEquals(calendar.hashCode(), anotherCalendar.hashCode()); + } + + public void testHashCode_differentTimeSameTimezone() { + calendar.setTimezone(0); + + XMLGregorianCalendarImpl anotherCalendar = new XMLGregorianCalendarImpl(); + anotherCalendar.setHour(1); + anotherCalendar.setTimezone(0); + + assertNotEquals(calendar.hashCode(), anotherCalendar.hashCode()); + } + + public void testHashCode_sameTimeDifferentTimezone() { + calendar.setHour(1); + calendar.setTimezone(0); + + XMLGregorianCalendarImpl anotherCalendar = new XMLGregorianCalendarImpl(); + anotherCalendar.setHour(1); + anotherCalendar.setMinute(30); + anotherCalendar.setTimezone(30); + + assertEquals(calendar.hashCode(), anotherCalendar.hashCode()); + } + + public void testHashCode_differentTimeDifferentTimezone() { + calendar.setHour(1); + calendar.setTimezone(0); + + XMLGregorianCalendarImpl anotherCalendar = new XMLGregorianCalendarImpl(); + anotherCalendar.setHour(2); + anotherCalendar.setMinute(30); + anotherCalendar.setTimezone(30); + + assertNotEquals(calendar.hashCode(), anotherCalendar.hashCode()); + } + /** * Stub implementation intended for test coverage. */ @@ -194,19 +287,26 @@ public class XMLGregorianCalendarTest extends TestCase { @Override public int compare(XMLGregorianCalendar rhs) { - if (year != rhs.getYear()) return year - rhs.getYear(); - if (month != rhs.getMonth()) return month - rhs.getMonth(); - if (day != rhs.getDay()) return day - rhs.getDay(); - if (hour != rhs.getHour()) return hour - rhs.getHour(); - if (minute != rhs.getMinute()) return minute - rhs.getMinute(); - if (second != rhs.getSecond()) return second - rhs.getSecond(); - if (millisecond != rhs.getMillisecond()) return millisecond - getMillisecond(); - return fractional.subtract(rhs.getFractionalSecond()).intValue(); + if (year != rhs.getYear()) return Integer.signum(year - rhs.getYear()); + if (month != rhs.getMonth()) return Integer.signum(month - rhs.getMonth()); + if (day != rhs.getDay()) return Integer.signum(day - rhs.getDay()); + if (hour != rhs.getHour()) return Integer.signum(hour - rhs.getHour()); + if (minute != rhs.getMinute()) return Integer.signum(minute - rhs.getMinute()); + if (second != rhs.getSecond()) return Integer.signum(second - rhs.getSecond()); + // edge case - millisecond is calculated from fractional second + if (getMillisecond() != rhs.getMillisecond()) + return Integer.signum(getMillisecond() - rhs.getMillisecond()); + return fractional.compareTo(rhs.getFractionalSecond()); } @Override public XMLGregorianCalendar normalize() { - return null; + if (this.timezoneOffset == 30) { + this.minute -= 30; + this.timezoneOffset = 0; + } + + return this; } @Override diff --git a/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderTest.java b/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderTest.java index e643bfd25ab..c7919f799c1 100644 --- a/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderTest.java +++ b/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderTest.java @@ -22,6 +22,7 @@ import static tests.support.Support_Xml.firstChildTextOf; import static tests.support.Support_Xml.firstElementOf; import javax.xml.parsers.DocumentBuilder; + import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.xml.sax.EntityResolver; @@ -29,6 +30,29 @@ import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; public class DocumentBuilderTest extends junit.framework.TestCase { + private static final DocumentBuilder BASE_DOCUMENT_BUILDER = new DocumentBuilder() { + @Override + public Document parse(InputSource is) { return null; } + + @Override + public boolean isNamespaceAware() { return false; } + + @Override + public boolean isValidating() { return false; } + + @Override + public void setEntityResolver(EntityResolver er) {} + + @Override + public void setErrorHandler(ErrorHandler eh) {} + + @Override + public Document newDocument() { return null; } + + @Override + public DOMImplementation getDOMImplementation() { return null; } + }; + // http://code.google.com/p/android/issues/detail?id=2607 public void test_characterReferences() throws Exception { assertEquals("aAb", firstChildTextOf(domOf("<p>aAb</p>"))); @@ -73,33 +97,23 @@ public class DocumentBuilderTest extends junit.framework.TestCase { } public void testGetSchema() { - DocumentBuilder db = new DocumentBuilder() { - @Override - public Document parse(InputSource is) { return null; } - - @Override - public boolean isNamespaceAware() { return false; } - - @Override - public boolean isValidating() { return false; } - - @Override - public void setEntityResolver(EntityResolver er) {} - - @Override - public void setErrorHandler(ErrorHandler eh) {} - - @Override - public Document newDocument() { return null; } - - @Override - public DOMImplementation getDOMImplementation() { return null; } - }; + try { + BASE_DOCUMENT_BUILDER.getSchema(); + fail("Unexpectedly didn't throw UnsupportedOperationException"); + } catch (UnsupportedOperationException expected) {} + } + public void testReset() { try { - db.getSchema(); + BASE_DOCUMENT_BUILDER.reset(); fail("Unexpectedly didn't throw UnsupportedOperationException"); } catch (UnsupportedOperationException expected) {} } + public void testIsXIncludeAware() { + try { + BASE_DOCUMENT_BUILDER.isXIncludeAware(); + fail("Unexpectedly didn't throw UnsupportedOperationException"); + } catch (UnsupportedOperationException expected) {} + } } diff --git a/luni/src/test/java/libcore/javax/xml/validation/SchemaFactoryTest.java b/luni/src/test/java/libcore/javax/xml/validation/SchemaFactoryTest.java new file mode 100644 index 00000000000..2f05c2e0736 --- /dev/null +++ b/luni/src/test/java/libcore/javax/xml/validation/SchemaFactoryTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * 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 libcore.javax.xml.validation; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; + +import javax.xml.transform.Source; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +@RunWith(JUnit4.class) +public class SchemaFactoryTest { + private static final SchemaFactory BASE_SCHEMA_FACTORY = new SchemaFactory() { + @Override + public boolean isSchemaLanguageSupported(String schemaLanguage) { + return false; + } + + @Override + public void setErrorHandler(ErrorHandler errorHandler) { + + } + + @Override + public ErrorHandler getErrorHandler() { + return null; + } + + @Override + public void setResourceResolver(LSResourceResolver resourceResolver) { + + } + + @Override + public LSResourceResolver getResourceResolver() { + return null; + } + + @Override + public Schema newSchema(Source[] schemas) throws SAXException { + return null; + } + + @Override + public Schema newSchema() throws SAXException { + return null; + } + }; + + @Test(expected = NullPointerException.class) + public void newInstance3_nullSchemaLanguage() { + SchemaFactory.newInstance(null, "factoryClassName", null); + } + + @Test(expected = NullPointerException.class) + public void newInstance3_nullFactoryClassName() { + SchemaFactory.newInstance("schemaLanguage", null, null); + } + + @Test(expected = IllegalArgumentException.class) + public void newInstance3_ClassNotFoundException() throws ClassNotFoundException { + ClassLoader classLoader = mock(ClassLoader.class); + when(classLoader.loadClass(eq("factoryClassName"))) + .thenThrow(new ClassNotFoundException()); + + SchemaFactory.newInstance("schemaLanguage", "factoryClassName", classLoader); + } + + @Test(expected = NullPointerException.class) + public void getFeature_nullString() throws SAXNotRecognizedException, SAXNotSupportedException { + BASE_SCHEMA_FACTORY.getFeature(null); + } + + @Test(expected = SAXNotRecognizedException.class) + public void getFeature_validString() + throws SAXNotRecognizedException, SAXNotSupportedException{ + BASE_SCHEMA_FACTORY.getFeature("myFeature"); + } + + @Test(expected = NullPointerException.class) + public void setFeature_nullString() throws SAXNotRecognizedException, SAXNotSupportedException { + BASE_SCHEMA_FACTORY.setFeature(null, true); + } + + @Test(expected = SAXNotRecognizedException.class) + public void setFeature_validString() + throws SAXNotRecognizedException, SAXNotSupportedException{ + BASE_SCHEMA_FACTORY.setFeature("myFeature", true); + } + + @Test(expected = NullPointerException.class) + public void setProperty_nullString() + throws SAXNotRecognizedException, SAXNotSupportedException { + BASE_SCHEMA_FACTORY.setProperty(null, new Object()); + } + + @Test(expected = SAXNotRecognizedException.class) + public void setProperty_validString() + throws SAXNotRecognizedException, SAXNotSupportedException{ + BASE_SCHEMA_FACTORY.setProperty("myProperty", new Object()); + } + + @Test(expected = NullPointerException.class) + public void getProperty_nullString() + throws SAXNotRecognizedException, SAXNotSupportedException { + BASE_SCHEMA_FACTORY.getProperty(null); + } + + @Test(expected = SAXNotRecognizedException.class) + public void getProperty_validString() + throws SAXNotRecognizedException, SAXNotSupportedException{ + BASE_SCHEMA_FACTORY.getProperty("myProperty"); + } +} diff --git a/luni/src/test/java/libcore/javax/xml/xpath/XPathExceptionTest.java b/luni/src/test/java/libcore/javax/xml/xpath/XPathExceptionTest.java index 79e4707b730..13c8252125f 100644 --- a/luni/src/test/java/libcore/javax/xml/xpath/XPathExceptionTest.java +++ b/luni/src/test/java/libcore/javax/xml/xpath/XPathExceptionTest.java @@ -17,12 +17,18 @@ package libcore.javax.xml.xpath; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; + import javax.xml.xpath.XPathException; @RunWith(JUnit4.class) @@ -35,10 +41,85 @@ public class XPathExceptionTest { } @Test + public void constructorWithStringNull() { + try { + XPathException unused = new XPathException((String) null); + fail("Expected NullPointerException with null String"); + } catch (NullPointerException ex) { + // Expected + } + } + + @Test public void constructorWithThrowable() { Throwable t = new Throwable(); XPathException e = new XPathException(t); assertEquals("java.lang.Throwable", e.getMessage()); assertEquals(t, e.getCause()); } + + @Test + public void constructorWithThrowableNull() { + try { + XPathException unused = new XPathException((Throwable) null); + fail("Expected NullPointerException with null Throwable"); + } catch (NullPointerException ex) { + // Expected + } + } + + @Test + public void printStackTrace_noArgs() { + XPathException e = new XPathException("message"); + e.printStackTrace(); + } + + @Test + public void printStackTraceWithPrintStream_nullCause() { + XPathException e = new XPathException("message"); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(baos, true); + e.printStackTrace(ps); + + assertNotEquals(-1, baos.toString().indexOf("javax.xml.xpath.XPathException")); + } + + @Test + public void printStackTraceWithPrintStream_nonNullCause() { + XPathException e = new XPathException(new TestCauseException()); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(baos, true); + e.printStackTrace(ps); + + assertNotEquals(-1, baos.toString().indexOf("TestCauseException")); + assertNotEquals(-1, baos.toString().indexOf("javax.xml.xpath.XPathException")); + } + + @Test + public void printStackTraceWithPrintWriter_nullCause() { + XPathException e = new XPathException("message"); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintWriter pw = new PrintWriter(baos, true); + e.printStackTrace(pw); + + assertNotEquals(-1, baos.toString().indexOf("javax.xml.xpath.XPathException")); + } + + @Test + public void printStackTraceWithPrintWriter_nonNullCause() { + XPathException e = new XPathException(new TestCauseException()); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintWriter pw = new PrintWriter(baos, true); + e.printStackTrace(pw); + + assertNotEquals(-1, baos.toString().indexOf("TestCauseException")); + assertNotEquals(-1, baos.toString().indexOf("javax.xml.xpath.XPathException")); + } + + // Defining a new exception to be used as cause in printStackTrace tests + private static class TestCauseException extends Throwable {} } diff --git a/luni/src/test/java/libcore/javax/xml/xpath/XPathFactoryTest.java b/luni/src/test/java/libcore/javax/xml/xpath/XPathFactoryTest.java index d868eea18bb..6381c2a2ee4 100644 --- a/luni/src/test/java/libcore/javax/xml/xpath/XPathFactoryTest.java +++ b/luni/src/test/java/libcore/javax/xml/xpath/XPathFactoryTest.java @@ -84,6 +84,14 @@ public class XPathFactoryTest { // Expected } + // URI with length 0 + try { + XPathFactory factory = XPathFactory.newInstance("", factoryName, classLoader); + fail("Expected IllegalArgumentException Failed for URI with length 0"); + } catch (IllegalArgumentException e) { + // Expected + } + // Bad factory name try { final String badFactoryName = factoryName + "Bad"; @@ -94,10 +102,49 @@ public class XPathFactoryTest { } catch (XPathFactoryConfigurationException e) { } + // Null FactoryClassName + try { + XPathFactory factory = XPathFactory.newInstance(SUPPORTED_URI, null, classLoader); + fail("Expected XPathFactoryConfigurationException for null factoryClassName"); + } catch (XPathFactoryConfigurationException e) { + // Expected + } + // Null ClassLoader { XPathFactory factory = XPathFactory.newInstance(SUPPORTED_URI, factoryName, null); assertNotNull(factory); } } + + @Test + public void newInstanceWithUri() throws Throwable { + // Null URI + { + try { + XPathFactory factory = XPathFactory.newInstance(null); + fail("Expected NPE Failed for null URI"); + } catch (NullPointerException e) { + // Expected + } + } + + // URI with length 0 + { + try { + XPathFactory factory = XPathFactory.newInstance(""); + fail("Expected IllegalArgumentException Failed for URI with length 0"); + } catch (IllegalArgumentException e) { + // Expected + } + } + + // Bad URI + try { + XPathFactory factory = XPathFactory.newInstance(UNSUPPORTED_URI); + fail("Failed for " + UNSUPPORTED_URI); + } catch (XPathFactoryConfigurationException e) { + // Expected + } + } } diff --git a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java index e56dab394a0..48c44b36aae 100644 --- a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java +++ b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java @@ -2220,7 +2220,7 @@ public class PatternTest extends TestCaseWithRules { } private int getExpectedEmptyStringSplitLength() { - if (VMRuntime.getSdkVersion() >= VersionCodes.UPSIDE_DOWN_CAKE + if (VMRuntime.getSdkVersion() > VersionCodes.TIRAMISU && Compatibility.isChangeEnabled( Pattern.SPLIT_AS_STREAM_RETURNS_SINGLE_EMPTY_STRING)) { // The length is 1 because the javadoc says "If this pattern does not match any diff --git a/luni/src/test/java/tests/security/interfaces/RSAKeyTest.java b/luni/src/test/java/tests/security/interfaces/RSAKeyTest.java index 619a2ad0295..7a34b9b3ff3 100644 --- a/luni/src/test/java/tests/security/interfaces/RSAKeyTest.java +++ b/luni/src/test/java/tests/security/interfaces/RSAKeyTest.java @@ -34,9 +34,9 @@ public class RSAKeyTest extends TestCase { */ public void test_getModulus() throws Exception { KeyFactory gen = KeyFactory.getInstance("RSA"); - final BigInteger n = BigInteger.valueOf(3233); - final BigInteger d = BigInteger.valueOf(2753); - final BigInteger e = BigInteger.valueOf(17); + final BigInteger n = Util.rsaCrtParam.getModulus(); + final BigInteger d = Util.rsaCrtParam.getPrivateExponent(); + final BigInteger e = Util.rsaCrtParam.getPublicExponent(); RSAKey key = null; // Case 1: check private key diff --git a/luni/src/test/java/tests/security/interfaces/RSAPrivateKeyTest.java b/luni/src/test/java/tests/security/interfaces/RSAPrivateKeyTest.java index a5035a9e677..b9afd4dfa1a 100644 --- a/luni/src/test/java/tests/security/interfaces/RSAPrivateKeyTest.java +++ b/luni/src/test/java/tests/security/interfaces/RSAPrivateKeyTest.java @@ -30,8 +30,8 @@ public class RSAPrivateKeyTest extends TestCase { */ public void test_getPrivateExponent() throws Exception { KeyFactory gen = KeyFactory.getInstance("RSA"); - final BigInteger n = BigInteger.valueOf(3233); - final BigInteger d = BigInteger.valueOf(2753); + final BigInteger n = Util.rsaCrtParam.getModulus(); + final BigInteger d = Util.rsaCrtParam.getPrivateExponent(); RSAPrivateKey key = (RSAPrivateKey) gen.generatePrivate(new RSAPrivateKeySpec( n, d)); assertEquals("invalid private exponent", d, key.getPrivateExponent()); diff --git a/luni/src/test/java/tests/security/interfaces/RSAPublicKeyTest.java b/luni/src/test/java/tests/security/interfaces/RSAPublicKeyTest.java index 09919af2edc..d56facf3695 100644 --- a/luni/src/test/java/tests/security/interfaces/RSAPublicKeyTest.java +++ b/luni/src/test/java/tests/security/interfaces/RSAPublicKeyTest.java @@ -30,8 +30,8 @@ public class RSAPublicKeyTest extends TestCase { */ public void test_getPublicExponent() throws Exception { KeyFactory gen = KeyFactory.getInstance("RSA"); - final BigInteger n = BigInteger.valueOf(3233); - final BigInteger e = BigInteger.valueOf(17); + final BigInteger n = Util.rsaCrtParam.getModulus(); + final BigInteger e = Util.rsaCrtParam.getPublicExponent(); RSAPublicKey key = (RSAPublicKey) gen.generatePublic(new RSAPublicKeySpec( n, e)); assertEquals("invalid public exponent", e, key.getPublicExponent()); diff --git a/luni/src/test/java/tests/security/interfaces/Util.java b/luni/src/test/java/tests/security/interfaces/Util.java index a6ba36d91bb..a482c52475f 100644 --- a/luni/src/test/java/tests/security/interfaces/Util.java +++ b/luni/src/test/java/tests/security/interfaces/Util.java @@ -64,10 +64,73 @@ class Util { * Valid RSA parameters */ static final RSAPrivateCrtKeySpec rsaCrtParam = new RSAPrivateCrtKeySpec( - BigInteger.valueOf(3233), BigInteger.valueOf(17), - BigInteger.valueOf(2753), BigInteger.valueOf(61), - BigInteger.valueOf(53), BigInteger.valueOf(53), - BigInteger.valueOf(49), BigInteger.valueOf(52)); + new BigInteger( + "ab07c37595818b1c0e543c8a0f157e932c7e7be59a45b7575b4101560f" + + "270bd4bc33e62da586b33baae8a51b4f30c3166e0e065984" + + "6b6915a5a8d5e50de6952989835fed9d271d371de66429d5" + + "565e8cd92f11e3c35777ae119b98c3c1d8683589e181bbc1" + + "0202db748fa07d0e81c66f33089f2641351ff85c86ede32d" + + "a17dd4398d324ea7feb9eb9341bd16f5a525a64696fbf7b1" + + "447ad227a4fd3ec95b4674a87f0fb4bf9459d812ded94437" + + "8b55e5dd2cfa9e154f0b8a606aaa7ff1411bd989d66a73e8" + + "76985d9a87c022b23997e497aa9addcbd76aabff6dc0b661" + + "53233aa4f71e63460d6a0814d19e26f91bb6cc562dc815d8" + + "0fd619d952d33cbb511c6f", + 16), + BigInteger.valueOf(65537), + new BigInteger( + "04e9fd30b4b1fb283c3529642218d101338712d23f037fc80fc42760ac" + + "a0c7933e31138cfe338794d04d4ce922f658b49d46e3e1d0" + + "8f317ec0bac0228baab3607526042c94965a1d8a4b63575c" + + "5cd5eca014dd23b92a1b3332285154568e7c380595282017" + + "e491e6724bea258db426da6d11f358ab08f6b93117636062" + + "a040383baf7f065696f0f5235be275787742c6d5a0c5052f" + + "ad6878078f8f1801f0187b8793984a31135ab522c789bdcd" + + "02b9fca48136b090b7d2b7e69f961109fa3ac7edc9c11176" + + "c719a4ba960b7cacf8af291d35f55c8427f373f019185608" + + "2a57c885b195e6350a37ef9e120fa05a0a65ece5f3124204" + + "6bd8ac9b4d0f45b94ad361", + 16), + new BigInteger( + "eb68d3cd6a402405c59e59d69ea5a998f0310a232ebcaa3bab1bec9888" + + "125ea7afb3acc65f718187c609e03d422699f387a740a929" + + "48229f0a1bf988a6cdf83b8ba989c51881af21f39519b8b4" + + "04820db3ff7e92bc691c29319f315de074d66e14ca5a67fa" + + "76eef3ebe49ca31a4bb33f56d1006d04960051524a4f0df4" + + "0838f1", + 16), + new BigInteger( + "b9fd63d45c6e921487361b25d6d4a056b27e0e62e4e1408dc80ba08c03" + + "0110a339e62ffa4a2c642497c9588e66d7c03f377f09ca95" + + "c7a1da6eb6773c9ef9e6d312bf51a15fb7f25d792990b312" + + "d2c5ed229adab2fe8258508ff193add0599dd876543f51c5" + + "1279329ccd3beb3d78542179b978cb66de27d665e7f20ff9" + + "ebab5f", + 16), + new BigInteger( + "d6d775ad5bd1abce84bb6edc1b2fafa77f56121d67d3113da17cbba1bd" + + "559e83452c227b6cb1a7786539b027d80e68a443e25575cc" + + "d2239ea7d83e1503bea85497b2a3a478282ad03e808dd7ee" + + "9acaa27ceaa8f67bf3259b46c93581aa8e97002203471cec" + + "0dcd2859d9eb46438260d5668319f364a30d292a83dcc02c" + + "3db0d1", + 16), + new BigInteger( + "94ede00866536bc9e05364fdb1bee4fd47444544cf3dc7b140647f145e" + + "3b76151e01c29d4ad3ad04d83e34192324d41e4ad4010525" + + "568bb61b3d24d1780367dfd07d3e62580135a3bfa796e4ad" + + "c7f51163ca582148471b6cb7369c286c53b65f64b1255ad6" + + "d16a172b13f44cf415ec5839de5869975f80cadf2311e3d5" + + "1def45", + 16), + new BigInteger( + "cd611f5e9698258144c87f14326ac40ef0070c447f28a20022a0fa62b2" + + "41ebce6a581bcb4754684bae886dcc893aca6390dd368718" + + "8e3b80035827a72f050f0356c784922b5d15be932658d427" + + "fa122adb87d7d1f32bdf19743c25543f3728d8f55a1d55d6" + + "b23cd8223690bd7e594c64517acd5bf925b32dfe56b09d05" + + "7b4668", + 16)); /** * Valid EC parameters diff --git a/mmodules/intracoreapi/api/intra/current.txt b/mmodules/intracoreapi/api/intra/current.txt index ca1b6748768..003c067cfb7 100644 --- a/mmodules/intracoreapi/api/intra/current.txt +++ b/mmodules/intracoreapi/api/intra/current.txt @@ -127,7 +127,6 @@ package libcore.io { package libcore.net { @libcore.api.IntraCoreApi public abstract class NetworkSecurityPolicy { - ctor @libcore.api.IntraCoreApi public NetworkSecurityPolicy(); method @libcore.api.IntraCoreApi public static libcore.net.NetworkSecurityPolicy getInstance(); method @libcore.api.IntraCoreApi public abstract boolean isCertificateTransparencyVerificationRequired(String); } diff --git a/ojluni/src/main/java/java/math/BigInteger.java b/ojluni/src/main/java/java/math/BigInteger.java index cc9b890436d..20fee1d589b 100644 --- a/ojluni/src/main/java/java/math/BigInteger.java +++ b/ojluni/src/main/java/java/math/BigInteger.java @@ -1848,6 +1848,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> { } } + // BEGIN Android-removed: Fall back to boringssl for large problems. /** * Multiplies two BigIntegers using the Karatsuba multiplication * algorithm. This is a recursive divide-and-conquer algorithm which is @@ -1863,6 +1864,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> { * * See: http://en.wikipedia.org/wiki/Karatsuba_algorithm */ + /* private static BigInteger multiplyKaratsuba(BigInteger x, BigInteger y) { int xlen = x.mag.length; int ylen = y.mag.length; @@ -1892,6 +1894,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> { return result; } } + */ /** * Multiplies two BigIntegers using a 3-way Toom-Cook multiplication @@ -1921,6 +1924,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> { * LNCS #4547. Springer, Madrid, Spain, June 21-22, 2007. * */ + /* private static BigInteger multiplyToomCook3(BigInteger a, BigInteger b) { int alen = a.mag.length; int blen = b.mag.length; @@ -1981,6 +1985,8 @@ public class BigInteger extends Number implements Comparable<BigInteger> { return result; } } + */ + // END Android-removed: Fall back to boringssl for large problems. /** @@ -2475,23 +2481,28 @@ public class BigInteger extends Number implements Comparable<BigInteger> { return a.divideKnuth(b, q).toBigInteger(this.signum); } + // BEGIN Android-removed: Fall back to boringssl for large problems. /** * Calculates {@code this / val} using the Burnikel-Ziegler algorithm. * @param val the divisor * @return {@code this / val} */ + /* private BigInteger divideBurnikelZiegler(BigInteger val) { return divideAndRemainderBurnikelZiegler(val)[0]; } + */ /** * Calculates {@code this % val} using the Burnikel-Ziegler algorithm. * @param val the divisor * @return {@code this % val} */ + /* private BigInteger remainderBurnikelZiegler(BigInteger val) { return divideAndRemainderBurnikelZiegler(val)[1]; } + */ /** * Computes {@code this / val} and {@code this % val} using the @@ -2499,6 +2510,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> { * @param val the divisor * @return an array containing the quotient and remainder */ + /* private BigInteger[] divideAndRemainderBurnikelZiegler(BigInteger val) { MutableBigInteger q = new MutableBigInteger(); MutableBigInteger r = new MutableBigInteger(this).divideAndRemainderBurnikelZiegler(new MutableBigInteger(val), q); @@ -2506,6 +2518,8 @@ public class BigInteger extends Number implements Comparable<BigInteger> { BigInteger rBigInt = r.isZero() ? ZERO : r.toBigInteger(signum); return new BigInteger[] {qBigInt, rBigInt}; } + */ + // END Android-removed: Fall back to boringssl for large problems. /** * Returns a BigInteger whose value is <code>(this<sup>exponent</sup>)</code>. diff --git a/ojluni/src/main/java/java/text/MergeCollation.java b/ojluni/src/main/java/java/text/MergeCollation.java deleted file mode 100644 index 1b092ed207a..00000000000 --- a/ojluni/src/main/java/java/text/MergeCollation.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (c) 1996, 2019, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved - * (C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved - * - * The original version of this source code and documentation is copyrighted - * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These - * materials are provided under terms of a License Agreement between Taligent - * and Sun. This technology is protected by multiple US and International - * patents. This notice and attribution to Taligent may not be removed. - * Taligent is a registered trademark of Taligent, Inc. - * - */ - -package java.text; - -import java.util.ArrayList; - -/** - * Utility class for normalizing and merging patterns for collation. - * Patterns are strings of the form <entry>*, where <entry> has the - * form: - * <pattern> := <entry>* - * <entry> := <separator><chars>{"/"<extension>} - * <separator> := "=", ",", ";", "<", "&" - * <chars>, and <extension> are both arbitrary strings. - * unquoted whitespaces are ignored. - * 'xxx' can be used to quote characters - * One difference from Collator is that & is used to reset to a current - * point. Or, in other words, it introduces a new sequence which is to - * be added to the old. - * That is: "a < b < c < d" is the same as "a < b & b < c & c < d" OR - * "a < b < d & b < c" - * XXX: make '' be a single quote. - * @see PatternEntry - * @author Mark Davis, Helena Shih - */ - -final class MergeCollation { - - /** - * Creates from a pattern - * @throws ParseException If the input pattern is incorrect. - */ - public MergeCollation(String pattern) throws ParseException - { - for (int i = 0; i < statusArray.length; i++) - statusArray[i] = 0; - setPattern(pattern); - } - - /** - * recovers current pattern - */ - public String getPattern() { - return getPattern(true); - } - - /** - * recovers current pattern. - * @param withWhiteSpace puts spacing around the entries, and \n - * before & and < - */ - public String getPattern(boolean withWhiteSpace) { - StringBuffer result = new StringBuffer(); - PatternEntry tmp = null; - ArrayList<PatternEntry> extList = null; - int i; - for (i = 0; i < patterns.size(); ++i) { - PatternEntry entry = patterns.get(i); - if (!entry.extension.isEmpty()) { - if (extList == null) - extList = new ArrayList<>(); - extList.add(entry); - } else { - if (extList != null) { - PatternEntry last = findLastWithNoExtension(i-1); - for (int j = extList.size() - 1; j >= 0 ; j--) { - tmp = extList.get(j); - tmp.addToBuffer(result, false, withWhiteSpace, last); - } - extList = null; - } - entry.addToBuffer(result, false, withWhiteSpace, null); - } - } - if (extList != null) { - PatternEntry last = findLastWithNoExtension(i-1); - for (int j = extList.size() - 1; j >= 0 ; j--) { - tmp = extList.get(j); - tmp.addToBuffer(result, false, withWhiteSpace, last); - } - extList = null; - } - return result.toString(); - } - - private final PatternEntry findLastWithNoExtension(int i) { - for (--i;i >= 0; --i) { - PatternEntry entry = patterns.get(i); - if (entry.extension.isEmpty()) { - return entry; - } - } - return null; - } - - /** - * emits the pattern for collation builder. - * @return emits the string in the format understable to the collation - * builder. - */ - public String emitPattern() { - return emitPattern(true); - } - - /** - * emits the pattern for collation builder. - * @param withWhiteSpace puts spacing around the entries, and \n - * before & and < - * @return emits the string in the format understable to the collation - * builder. - */ - public String emitPattern(boolean withWhiteSpace) { - StringBuffer result = new StringBuffer(); - for (int i = 0; i < patterns.size(); ++i) - { - PatternEntry entry = patterns.get(i); - if (entry != null) { - entry.addToBuffer(result, true, withWhiteSpace, null); - } - } - return result.toString(); - } - - /** - * sets the pattern. - */ - public void setPattern(String pattern) throws ParseException - { - patterns.clear(); - addPattern(pattern); - } - - /** - * adds a pattern to the current one. - * @param pattern the new pattern to be added - */ - public void addPattern(String pattern) throws ParseException - { - if (pattern == null) - return; - - PatternEntry.Parser parser = new PatternEntry.Parser(pattern); - - PatternEntry entry = parser.next(); - while (entry != null) { - fixEntry(entry); - entry = parser.next(); - } - } - - /** - * gets count of separate entries - * @return the size of pattern entries - */ - public int getCount() { - return patterns.size(); - } - - /** - * gets count of separate entries - * @param index the offset of the desired pattern entry - * @return the requested pattern entry - */ - public PatternEntry getItemAt(int index) { - return patterns.get(index); - } - - //============================================================ - // privates - //============================================================ - ArrayList<PatternEntry> patterns = new ArrayList<>(); // a list of PatternEntries - - private transient PatternEntry saveEntry = null; - private transient PatternEntry lastEntry = null; - - // This is really used as a local variable inside fixEntry, but we cache - // it here to avoid newing it up every time the method is called. - private transient StringBuffer excess = new StringBuffer(); - - // - // When building a MergeCollation, we need to do lots of searches to see - // whether a given entry is already in the table. Since we're using an - // array, this would make the algorithm O(N*N). To speed things up, we - // use this bit array to remember whether the array contains any entries - // starting with each Unicode character. If not, we can avoid the search. - // Using BitSet would make this easier, but it's significantly slower. - // - private transient byte[] statusArray = new byte[8192]; - private final byte BITARRAYMASK = (byte)0x1; - private final int BYTEPOWER = 3; - private final int BYTEMASK = (1 << BYTEPOWER) - 1; - - /* - If the strength is RESET, then just change the lastEntry to - be the current. (If the current is not in patterns, signal an error). - If not, then remove the current entry, and add it after lastEntry - (which is usually at the end). - */ - private final void fixEntry(PatternEntry newEntry) throws ParseException - { - // check to see whether the new entry has the same characters as the previous - // entry did (this can happen when a pattern declaring a difference between two - // strings that are canonically equivalent is normalized). If so, and the strength - // is anything other than IDENTICAL or RESET, throw an exception (you can't - // declare a string to be unequal to itself). --rtg 5/24/99 - if (lastEntry != null && newEntry.chars.equals(lastEntry.chars) - && newEntry.extension.equals(lastEntry.extension)) { - if (newEntry.strength != Collator.IDENTICAL - && newEntry.strength != PatternEntry.RESET) { - throw new ParseException("The entries " + lastEntry + " and " - + newEntry + " are adjacent in the rules, but have conflicting " - + "strengths: A character can't be unequal to itself.", -1); - } else { - // otherwise, just skip this entry and behave as though you never saw it - return; - } - } - - boolean changeLastEntry = true; - if (newEntry.strength != PatternEntry.RESET) { - int oldIndex = -1; - - if ((newEntry.chars.length() == 1)) { - - char c = newEntry.chars.charAt(0); - int statusIndex = c >> BYTEPOWER; - byte bitClump = statusArray[statusIndex]; - byte setBit = (byte)(BITARRAYMASK << (c & BYTEMASK)); - - if (bitClump != 0 && (bitClump & setBit) != 0) { - oldIndex = patterns.lastIndexOf(newEntry); - } else { - // We're going to add an element that starts with this - // character, so go ahead and set its bit. - statusArray[statusIndex] = (byte)(bitClump | setBit); - } - } else { - oldIndex = patterns.lastIndexOf(newEntry); - } - if (oldIndex != -1) { - patterns.remove(oldIndex); - } - - excess.setLength(0); - int lastIndex = findLastEntry(lastEntry, excess); - - if (excess.length() != 0) { - newEntry.extension = excess + newEntry.extension; - if (lastIndex != patterns.size()) { - lastEntry = saveEntry; - changeLastEntry = false; - } - } - if (lastIndex == patterns.size()) { - patterns.add(newEntry); - saveEntry = newEntry; - } else { - patterns.add(lastIndex, newEntry); - } - } - if (changeLastEntry) { - lastEntry = newEntry; - } - } - - private final int findLastEntry(PatternEntry entry, - StringBuffer excessChars) throws ParseException - { - if (entry == null) - return 0; - - if (entry.strength != PatternEntry.RESET) { - // Search backwards for string that contains this one; - // most likely entry is last one - - int oldIndex = -1; - if ((entry.chars.length() == 1)) { - int index = entry.chars.charAt(0) >> BYTEPOWER; - if ((statusArray[index] & - (BITARRAYMASK << (entry.chars.charAt(0) & BYTEMASK))) != 0) { - oldIndex = patterns.lastIndexOf(entry); - } - } else { - oldIndex = patterns.lastIndexOf(entry); - } - if ((oldIndex == -1)) - throw new ParseException("couldn't find last entry: " - + entry, oldIndex); - return oldIndex + 1; - } else { - int i; - for (i = patterns.size() - 1; i >= 0; --i) { - PatternEntry e = patterns.get(i); - if (e.chars.regionMatches(0,entry.chars,0, - e.chars.length())) { - excessChars.append(entry.chars, e.chars.length(), - entry.chars.length()); - break; - } - } - if (i == -1) - throw new ParseException("couldn't find: " + entry, i); - return i + 1; - } - } -} diff --git a/ojluni/src/main/java/java/text/PatternEntry.java b/ojluni/src/main/java/java/text/PatternEntry.java deleted file mode 100644 index 858c3152cb7..00000000000 --- a/ojluni/src/main/java/java/text/PatternEntry.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (c) 1996, 2000, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved - * (C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved - * - * The original version of this source code and documentation is copyrighted - * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These - * materials are provided under terms of a License Agreement between Taligent - * and Sun. This technology is protected by multiple US and International - * patents. This notice and attribution to Taligent may not be removed. - * Taligent is a registered trademark of Taligent, Inc. - * - */ - -package java.text; - -import java.lang.Character; - -/** - * Utility class for normalizing and merging patterns for collation. - * This is to be used with MergeCollation for adding patterns to an - * existing rule table. - * @see MergeCollation - * @author Mark Davis, Helena Shih - */ - -class PatternEntry { - /** - * Gets the current extension, quoted - */ - public void appendQuotedExtension(StringBuffer toAddTo) { - appendQuoted(extension,toAddTo); - } - - /** - * Gets the current chars, quoted - */ - public void appendQuotedChars(StringBuffer toAddTo) { - appendQuoted(chars,toAddTo); - } - - /** - * WARNING this is used for searching in a Vector. - * Because Vector.indexOf doesn't take a comparator, - * this method is ill-defined and ignores strength. - */ - public boolean equals(Object obj) { - if (obj == null) return false; - PatternEntry other = (PatternEntry) obj; - boolean result = chars.equals(other.chars); - return result; - } - - public int hashCode() { - return chars.hashCode(); - } - - /** - * For debugging. - */ - public String toString() { - StringBuffer result = new StringBuffer(); - addToBuffer(result, true, false, null); - return result.toString(); - } - - /** - * Gets the strength of the entry. - */ - final int getStrength() { - return strength; - } - - /** - * Gets the expanding characters of the entry. - */ - final String getExtension() { - return extension; - } - - /** - * Gets the core characters of the entry. - */ - final String getChars() { - return chars; - } - - // ===== privates ===== - - void addToBuffer(StringBuffer toAddTo, - boolean showExtension, - boolean showWhiteSpace, - PatternEntry lastEntry) - { - if (showWhiteSpace && toAddTo.length() > 0) - if (strength == Collator.PRIMARY || lastEntry != null) - toAddTo.append('\n'); - else - toAddTo.append(' '); - if (lastEntry != null) { - toAddTo.append('&'); - if (showWhiteSpace) - toAddTo.append(' '); - lastEntry.appendQuotedChars(toAddTo); - appendQuotedExtension(toAddTo); - if (showWhiteSpace) - toAddTo.append(' '); - } - var c = switch (strength) { - case Collator.IDENTICAL -> '='; - case Collator.TERTIARY -> ','; - case Collator.SECONDARY -> ';'; - case Collator.PRIMARY -> '<'; - case RESET -> '&'; - case UNSET -> '?'; - - default -> throw new IllegalStateException("Unexpected value: " + strength); - }; - toAddTo.append(c); - - if (showWhiteSpace) - toAddTo.append(' '); - appendQuoted(chars,toAddTo); - if (showExtension && !extension.isEmpty()) { - toAddTo.append('/'); - appendQuoted(extension,toAddTo); - } - } - - static void appendQuoted(String chars, StringBuffer toAddTo) { - boolean inQuote = false; - char ch = chars.charAt(0); - if (Character.isSpaceChar(ch)) { - inQuote = true; - toAddTo.append('\''); - } else { - if (PatternEntry.isSpecialChar(ch)) { - inQuote = true; - toAddTo.append('\''); - } else { - switch (ch) { - case 0x0010: case '\f': case '\r': - case '\t': case '\n': case '@': - inQuote = true; - toAddTo.append('\''); - break; - case '\'': - inQuote = true; - toAddTo.append('\''); - break; - default: - if (inQuote) { - inQuote = false; toAddTo.append('\''); - } - break; - } - } - } - toAddTo.append(chars); - if (inQuote) - toAddTo.append('\''); - } - - //======================================================================== - // Parsing a pattern into a list of PatternEntries.... - //======================================================================== - - PatternEntry(int strength, - StringBuffer chars, - StringBuffer extension) - { - this.strength = strength; - this.chars = chars.toString(); - this.extension = (extension.length() > 0) ? extension.toString() - : ""; - } - - static class Parser { - private String pattern; - private int i; - - public Parser(String pattern) { - this.pattern = pattern; - this.i = 0; - } - - public PatternEntry next() throws ParseException { - int newStrength = UNSET; - - newChars.setLength(0); - newExtension.setLength(0); - - boolean inChars = true; - boolean inQuote = false; - mainLoop: - while (i < pattern.length()) { - char ch = pattern.charAt(i); - if (inQuote) { - if (ch == '\'') { - inQuote = false; - } else { - if (newChars.length() == 0) newChars.append(ch); - else if (inChars) newChars.append(ch); - else newExtension.append(ch); - } - } else switch (ch) { - case '=': if (newStrength != UNSET) break mainLoop; - newStrength = Collator.IDENTICAL; break; - case ',': if (newStrength != UNSET) break mainLoop; - newStrength = Collator.TERTIARY; break; - case ';': if (newStrength != UNSET) break mainLoop; - newStrength = Collator.SECONDARY; break; - case '<': if (newStrength != UNSET) break mainLoop; - newStrength = Collator.PRIMARY; break; - case '&': if (newStrength != UNSET) break mainLoop; - newStrength = RESET; break; - case '\t': - case '\n': - case '\f': - case '\r': - case ' ': break; // skip whitespace TODO use Character - case '/': inChars = false; break; - case '\'': - inQuote = true; - ch = pattern.charAt(++i); - if (newChars.length() == 0) newChars.append(ch); - else if (inChars) newChars.append(ch); - else newExtension.append(ch); - break; - default: - if (newStrength == UNSET) { - throw new ParseException - ("missing char (=,;<&) : " + - pattern.substring(i, - (i+10 < pattern.length()) ? - i+10 : pattern.length()), - i); - } - if (PatternEntry.isSpecialChar(ch) && (inQuote == false)) - throw new ParseException - ("Unquoted punctuation character : " + Integer.toString(ch, 16), i); - if (inChars) { - newChars.append(ch); - } else { - newExtension.append(ch); - } - break; - } - i++; - } - if (newStrength == UNSET) - return null; - if (newChars.length() == 0) { - throw new ParseException - ("missing chars (=,;<&): " + - pattern.substring(i, - (i+10 < pattern.length()) ? - i+10 : pattern.length()), - i); - } - - return new PatternEntry(newStrength, newChars, newExtension); - } - - // We re-use these objects in order to improve performance - private StringBuffer newChars = new StringBuffer(); - private StringBuffer newExtension = new StringBuffer(); - - } - - static boolean isSpecialChar(char ch) { - return ((ch == '\u0020') || - ((ch <= '\u002F') && (ch >= '\u0022')) || - ((ch <= '\u003F') && (ch >= '\u003A')) || - ((ch <= '\u0060') && (ch >= '\u005B')) || - ((ch <= '\u007E') && (ch >= '\u007B'))); - } - - - static final int RESET = -2; - static final int UNSET = -1; - - int strength = UNSET; - String chars = ""; - String extension = ""; -} diff --git a/ojluni/src/main/java/java/util/PriorityQueue.java b/ojluni/src/main/java/java/util/PriorityQueue.java index 70c99bff9d0..264b1a8983f 100644 --- a/ojluni/src/main/java/java/util/PriorityQueue.java +++ b/ojluni/src/main/java/java/util/PriorityQueue.java @@ -25,6 +25,13 @@ package java.util; +import android.compat.Compatibility; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledSince; + +import dalvik.annotation.compat.VersionCodes; +import dalvik.system.VMRuntime; + import java.util.function.Consumer; import java.util.function.Predicate; import jdk.internal.misc.SharedSecrets; @@ -327,7 +334,18 @@ public class PriorityQueue<E> extends AbstractQueue<E> int i = size; if (i >= queue.length) grow(i + 1); - siftUp(i, e); + if (i == 0) { + // Android-changed: Keep old behavior on Android 13 or below. http://b/289878283 + boolean usePreAndroidUBehavior = VMRuntime.getSdkVersion() < VersionCodes.UPSIDE_DOWN_CAKE + || !Compatibility.isChangeEnabled(PRIORITY_QUEUE_OFFER_NON_COMPARABLE_ONE_ELEMENT); + if (usePreAndroidUBehavior) { + queue[0] = e; + } else { + siftUp(i, e); + } + } else { + siftUp(i, e); + } size = i + 1; return true; } @@ -970,4 +988,18 @@ public class PriorityQueue<E> extends AbstractQueue<E> if (expectedModCount != modCount) throw new ConcurrentModificationException(); } + + // Android-added: Backward-compatible flag for offer() API. + /** + * Since Android 14, {@link PriorityQueue#offer(E)} requires all elements to be comparable if + * there was no comparator. Previously, the first element being added did not need to be + * comparable. + * + * This flag is enabled for apps targeting Android 14+. + * + * @hide + */ + @ChangeId + @EnabledSince(targetSdkVersion = VersionCodes.UPSIDE_DOWN_CAKE) + public static final long PRIORITY_QUEUE_OFFER_NON_COMPARABLE_ONE_ELEMENT = 289878283L; } diff --git a/ojluni/src/test/Android.bp b/ojluni/src/test/Android.bp index 0eeb92c53e1..d5924a551da 100644 --- a/ojluni/src/test/Android.bp +++ b/ojluni/src/test/Android.bp @@ -57,6 +57,7 @@ java_test { ], static_libs: [ + "core-test-rules", "junit", "testng", ], @@ -143,6 +144,7 @@ java_test { system_modules: "core-all-system-modules", libs: [ "bouncycastle", + "core-test-rules", "junit", "okhttp", "testng", diff --git a/ojluni/src/test/java/math/BigInteger/BigIntegerTest.java b/ojluni/src/test/java/math/BigInteger/BigIntegerTest.java index 0e8c4cdec5b..48a819cb87e 100644 --- a/ojluni/src/test/java/math/BigInteger/BigIntegerTest.java +++ b/ojluni/src/test/java/math/BigInteger/BigIntegerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, 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 @@ -26,7 +26,7 @@ * @library /test/lib * @build jdk.test.lib.RandomFactory * @run main BigIntegerTest - * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 4837946 4026465 8074460 8078672 8032027 + * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 4837946 4026465 8074460 8078672 8032027 8229845 * @summary tests methods in BigInteger (use -Dseed=X to set PRNG seed) * @run main/timeout=400 BigIntegerTest * @author madbot @@ -648,10 +648,11 @@ public class BigIntegerTest { } } + // BEGIN Android-changed: Fix slow BigInteger string conversion test splitting into multiple. private static void stringConv_generic() { // Generic string conversion. for (int i=0; i<100; i++) { - byte[] xBytes = new byte[Math.abs(random.nextInt())%100+1]; + byte xBytes[] = new byte[Math.abs(random.nextInt())%200+1]; random.nextBytes(xBytes); BigInteger x = new BigInteger(xBytes); @@ -685,6 +686,17 @@ public class BigIntegerTest { } } + private static void stringConv_trailingZeros() { + // Check value with many trailing zeros. + String val = "123456789" + + "0".repeat(200); + BigInteger b = new BigInteger(val); + String s = b.toString(); + Assert.assertEquals( + val, s, String.format("Expected length %d but got %d%n", val.length(), s.length())); + } + // END Android-changed: Fix slow BigInteger string conversion test splitting into multiple. + private static void byteArrayConv(int order) { for (int i=0; i<SIZE; i++) { BigInteger x = fetchNumber(order); @@ -1095,6 +1107,11 @@ public class BigIntegerTest { } @Test + public void testStringConv_trailingZeros() { + stringConv_trailingZeros(); + } + + @Test public void testSerialize() throws Exception { serialize(); } diff --git a/ojluni/src/test/java/math/BigInteger/BitLengthOverflow.java b/ojluni/src/test/java/math/BigInteger/BitLengthOverflow.java new file mode 100644 index 00000000000..72d14c4a6cc --- /dev/null +++ b/ojluni/src/test/java/math/BigInteger/BitLengthOverflow.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013, 2021, 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 6910473 8272541 + * @summary Test that bitLength() is not negative + * @author Dmitry Nadezhin + */ +package test.java.math.BigInteger; + +import java.math.BigInteger; +import java.util.function.Supplier; + +public class BitLengthOverflow { + private static void test(Supplier<BigInteger> s) { + try { + BigInteger x = s.get(); + System.out.println("Surprisingly passed with correct bitLength() " + + x.bitLength()); + } catch (ArithmeticException e) { + // expected + System.out.println("Overflow reported by ArithmeticException, as expected"); + } catch (OutOfMemoryError e) { + // possible + System.err.println("BitLengthOverflow skipped: OutOfMemoryError"); + System.err.println("Run jtreg with -javaoption:-Xmx8g"); + } + } + + public static void main(String[] args) { + test(() -> { + // x = pow(2,Integer.MAX_VALUE) + BigInteger x = BigInteger.ONE.shiftLeft(Integer.MAX_VALUE); + if (x.bitLength() != (1L << 31)) { + throw new RuntimeException("Incorrect bitLength() " + + x.bitLength()); + } + return x; + }); + test(() -> { + BigInteger a = BigInteger.ONE.shiftLeft(1073742825); + BigInteger b = BigInteger.ONE.shiftLeft(1073742825); + return a.multiply(b); + }); + } +} diff --git a/ojluni/src/test/java/math/BigInteger/DoubleValueOverflow.java b/ojluni/src/test/java/math/BigInteger/DoubleValueOverflow.java new file mode 100644 index 00000000000..6d2886f1061 --- /dev/null +++ b/ojluni/src/test/java/math/BigInteger/DoubleValueOverflow.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013, 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 8021203 + * @summary Test that doubleValue() doesn't overflow + * @author Dmitry Nadezhin + */ +package test.java.math.BigInteger; + +import java.math.BigInteger; + +public class DoubleValueOverflow { + + public static void main(String[] args) { + try { + BigInteger x = BigInteger.valueOf(2).shiftLeft(Integer.MAX_VALUE); // x = pow(2,pow(2,31)) + if (x.doubleValue() != Double.POSITIVE_INFINITY) { + throw new RuntimeException("Incorrect doubleValue() " + x.doubleValue()); + } + System.out.println("Passed with correct result"); + } catch (ArithmeticException e) { + // expected + System.out.println("Overflow is reported by ArithmeticException, as expected"); + } catch (OutOfMemoryError e) { + // possible + System.err.println("DoubleValueOverflow skipped: OutOfMemoryError"); + System.err.println("Run jtreg with -javaoption:-Xmx8g"); + } + } +} diff --git a/ojluni/src/test/java/math/BigInteger/ExtremeShiftingTests.java b/ojluni/src/test/java/math/BigInteger/ExtremeShiftingTests.java new file mode 100644 index 00000000000..197e508a303 --- /dev/null +++ b/ojluni/src/test/java/math/BigInteger/ExtremeShiftingTests.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2009, 2013, 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 6371401 + * @summary Tests of shiftLeft and shiftRight on Integer.MIN_VALUE + * @requires os.maxMemory >= 1g + * @run main/othervm -Xmx512m ExtremeShiftingTests + * @author Joseph D. Darcy + */ +package test.java.math.BigInteger; + +import java.math.BigInteger; +import static java.math.BigInteger.*; + +public class ExtremeShiftingTests { + public static void main(String... args) { + // BEGIN Android-removed: Test fails on Android. + // java.lang.OutOfMemoryError: Failed to allocate a 268435472 byte allocation ... + /* + BigInteger bi = ONE.shiftLeft(Integer.MIN_VALUE); + if (!bi.equals(ZERO)) + throw new RuntimeException("1 << " + Integer.MIN_VALUE); + + bi = ZERO.shiftLeft(Integer.MIN_VALUE); + if (!bi.equals(ZERO)) + throw new RuntimeException("0 << " + Integer.MIN_VALUE); + + bi = BigInteger.valueOf(-1); + bi = bi.shiftLeft(Integer.MIN_VALUE); + if (!bi.equals(BigInteger.valueOf(-1))) + throw new RuntimeException("-1 << " + Integer.MIN_VALUE); + + try { + ONE.shiftRight(Integer.MIN_VALUE); + throw new RuntimeException("1 >> " + Integer.MIN_VALUE); + } catch (ArithmeticException ae) { + ; // Expected + } + + bi = ZERO.shiftRight(Integer.MIN_VALUE); + if (!bi.equals(ZERO)) + throw new RuntimeException("0 >> " + Integer.MIN_VALUE); + + try { + BigInteger.valueOf(-1).shiftRight(Integer.MIN_VALUE); + throw new RuntimeException("-1 >> " + Integer.MIN_VALUE); + } catch (ArithmeticException ae) { + ; // Expected + } + */ + // END Android-removed: Test fails on Android. + } +} diff --git a/ojluni/src/test/java/math/BigInteger/LargeValueExceptions.java b/ojluni/src/test/java/math/BigInteger/LargeValueExceptions.java new file mode 100644 index 00000000000..efa988c970e --- /dev/null +++ b/ojluni/src/test/java/math/BigInteger/LargeValueExceptions.java @@ -0,0 +1,200 @@ +/* + * 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 8200698 + * @summary Tests that exceptions are thrown for ops which would overflow + * @requires (sun.arch.data.model == "64" & os.maxMemory >= 4g) + * @run testng/othervm -Xmx4g LargeValueExceptions + */ +package test.java.math.BigInteger; + +import java.math.BigInteger; +import static java.math.BigInteger.ONE; +import org.testng.annotations.Test; + +// +// The intent of this test is to probe the boundaries between overflow and +// non-overflow, principally for multiplication and squaring, specifically +// the largest values which should not overflow and the smallest values which +// should. The transition values used are not necessarily at the exact +// boundaries but should be "close." Quite a few different values were used +// experimentally before settling on the ones in this test. For multiplication +// and squaring all cases are exercised: definite overflow and non-overflow +// which can be detected "up front," and "indefinite" overflow, i.e., overflow +// which cannot be detected up front so further calculations are required. +// +// Testing negative values is unnecessary. For both multiplication and squaring +// the paths lead to the Toom-Cook algorithm where the signum is used only to +// determine the sign of the result and not in the intermediate calculations. +// This is also true for exponentiation. +// +// @Test annotations with optional element "enabled" set to "false" should +// succeed when "enabled" is set to "true" but they take too to run in the +// course of the typical regression test execution scenario. +// +public class LargeValueExceptions { + // BigInteger.MAX_MAG_LENGTH + private static final int MAX_INTS = 1 << 26; + + // Number of bits corresponding to MAX_INTS + private static final long MAX_BITS = (0xffffffffL & MAX_INTS) << 5L; + + // Half BigInteger.MAX_MAG_LENGTH + private static final int MAX_INTS_HALF = MAX_INTS / 2; + + // --- squaring --- + + // Largest no overflow determined by examining data lengths alone. + @Test(enabled=false) + public void squareNoOverflow() { + BigInteger x = ONE.shiftLeft(16*MAX_INTS - 1).subtract(ONE); + BigInteger y = x.multiply(x); + } + + // Smallest no overflow determined by extra calculations. + @Test(enabled=false) + public void squareIndefiniteOverflowSuccess() { + BigInteger x = ONE.shiftLeft(16*MAX_INTS - 1); + BigInteger y = x.multiply(x); + } + + // Largest overflow detected by extra calculations. + @Test(expectedExceptions=ArithmeticException.class,enabled=false) + public void squareIndefiniteOverflowFailure() { + BigInteger x = ONE.shiftLeft(16*MAX_INTS).subtract(ONE); + BigInteger y = x.multiply(x); + } + + // Smallest overflow detected by examining data lengths alone. + // BEGIN Android-changed: Test fails on Android. + // java.lang.OutOfMemoryError: Failed to allocate a 134217744 byte allocation ... + @Test(expectedExceptions=ArithmeticException.class,enabled=false) + // END Android-changed: Test fails on Android. + public void squareDefiniteOverflow() { + BigInteger x = ONE.shiftLeft(16*MAX_INTS); + BigInteger y = x.multiply(x); + } + + // --- multiplication --- + + // Largest no overflow determined by examining data lengths alone. + @Test(enabled=false) + public void multiplyNoOverflow() { + final int halfMaxBits = MAX_INTS_HALF << 5; + + BigInteger x = ONE.shiftLeft(halfMaxBits).subtract(ONE); + BigInteger y = ONE.shiftLeft(halfMaxBits - 1).subtract(ONE); + BigInteger z = x.multiply(y); + } + + // Smallest no overflow determined by extra calculations. + @Test(enabled=false) + public void multiplyIndefiniteOverflowSuccess() { + BigInteger x = ONE.shiftLeft((int)(MAX_BITS/2) - 1); + long m = MAX_BITS - x.bitLength(); + + BigInteger y = ONE.shiftLeft((int)(MAX_BITS/2) - 1); + long n = MAX_BITS - y.bitLength(); + + if (m + n != MAX_BITS) { + throw new RuntimeException("Unexpected leading zero sum"); + } + + BigInteger z = x.multiply(y); + } + + // Largest overflow detected by extra calculations. + @Test(expectedExceptions=ArithmeticException.class,enabled=false) + public void multiplyIndefiniteOverflowFailure() { + BigInteger x = ONE.shiftLeft((int)(MAX_BITS/2)).subtract(ONE); + long m = MAX_BITS - x.bitLength(); + + BigInteger y = ONE.shiftLeft((int)(MAX_BITS/2)).subtract(ONE); + long n = MAX_BITS - y.bitLength(); + + if (m + n != MAX_BITS) { + throw new RuntimeException("Unexpected leading zero sum"); + } + + BigInteger z = x.multiply(y); + } + + // Smallest overflow detected by examining data lengths alone. + // BEGIN Android-changed: Test fails on Android. + // java.lang.OutOfMemoryError: Failed to allocate a 134217744 byte allocation ... + @Test(expectedExceptions=ArithmeticException.class,enabled=false) + // END Android-changed: Test fails on Android. + public void multiplyDefiniteOverflow() { + // multiply by 4 as MAX_INTS_HALF refers to ints + byte[] xmag = new byte[4*MAX_INTS_HALF]; + xmag[0] = (byte)0xff; + BigInteger x = new BigInteger(1, xmag); + + byte[] ymag = new byte[4*MAX_INTS_HALF + 1]; + ymag[0] = (byte)0xff; + BigInteger y = new BigInteger(1, ymag); + + BigInteger z = x.multiply(y); + } + + // --- exponentiation --- + + @Test(expectedExceptions=ArithmeticException.class) + public void powOverflow() { + BigInteger.TEN.pow(Integer.MAX_VALUE); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void powOverflow1() { + int shift = 20; + int exponent = 1 << shift; + BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent)); + BigInteger y = x.pow(exponent); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void powOverflow2() { + int shift = 20; + int exponent = 1 << shift; + BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent)).add(ONE); + BigInteger y = x.pow(exponent); + } + + @Test(expectedExceptions=ArithmeticException.class,enabled=false) + public void powOverflow3() { + int shift = 20; + int exponent = 1 << shift; + BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent)).subtract(ONE); + BigInteger y = x.pow(exponent); + } + + @Test(enabled=false) + public void powOverflow4() { + int shift = 20; + int exponent = 1 << shift; + BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent - 1)).add(ONE); + BigInteger y = x.pow(exponent); + } +} diff --git a/ojluni/src/test/java/math/BigInteger/ModInvTime.java b/ojluni/src/test/java/math/BigInteger/ModInvTime.java new file mode 100644 index 00000000000..95cb0f7caa0 --- /dev/null +++ b/ojluni/src/test/java/math/BigInteger/ModInvTime.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020, 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 8225603 + * @summary Tests whether modInverse() completes in a reasonable time + * @run main/othervm ModInvTime + */ +package test.java.math.BigInteger; + +import java.math.BigInteger; + +public class ModInvTime { + public static void main(String[] args) throws InterruptedException { + BigInteger prime = new BigInteger("39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643"); + BigInteger s = new BigInteger("9552729729729327851382626410162104591956625415831952158766936536163093322096473638446154604799898109762512409920799"); + System.out.format("int length: %d, modulus length: %d%n", + s.bitLength(), prime.bitLength()); + + System.out.println("Computing modular inverse ..."); + BigInteger mi = s.modInverse(prime); + System.out.format("Modular inverse: %s%n", mi); + check(s, prime, mi); + + BigInteger ns = s.negate(); + BigInteger nmi = ns.modInverse(prime); + System.out.format("Modular inverse of negation: %s%n", nmi); + check(ns, prime, nmi); + } + + public static void check(BigInteger val, BigInteger mod, BigInteger inv) { + BigInteger r = inv.multiply(val).remainder(mod); + if (r.signum() == -1) + r = r.add(mod); + if (!r.equals(BigInteger.ONE)) + throw new RuntimeException("Numerically incorrect modular inverse"); + } +} diff --git a/ojluni/src/test/java/math/BigInteger/ModPow.java b/ojluni/src/test/java/math/BigInteger/ModPow.java index b31c0f6e61c..41cc337c41e 100644 --- a/ojluni/src/test/java/math/BigInteger/ModPow.java +++ b/ojluni/src/test/java/math/BigInteger/ModPow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -22,13 +22,18 @@ */ /* @test - * @bug 4181191 - * @summary test BigInteger modPow method + * @bug 4181191 8215759 + * @summary test BigInteger modPow method (use -Dseed=X to set PRNG seed) + * @library /test/lib + * @build jdk.test.lib.RandomFactory + * @run main ModPow + * @key randomness */ package test.java.math.BigInteger; import java.math.BigInteger; import java.util.Random; +import jdk.test.lib.RandomFactory; import org.testng.Assert; import org.testng.annotations.Test; @@ -41,7 +46,9 @@ public class ModPow { Random rnd = new Random(1234); for (int i=0; i<2000; i++) { - BigInteger m = new BigInteger(800, rnd); + // Clamp random modulus to a positive value or modPow() will + // throw an ArithmeticException. + BigInteger m = new BigInteger(800, rnd).max(BigInteger.ONE); BigInteger base = new BigInteger(16, rnd); if (rnd.nextInt() % 2 == 0) base = base.negate(); diff --git a/ojluni/src/test/java/math/BigInteger/ModPow65537.java b/ojluni/src/test/java/math/BigInteger/ModPow65537.java new file mode 100644 index 00000000000..c616bbcd8e1 --- /dev/null +++ b/ojluni/src/test/java/math/BigInteger/ModPow65537.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2003, 2017, 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 + * @library /test/lib + * @build jdk.test.lib.RandomFactory + * @run main ModPow65537 + * @bug 4891312 8074460 8078672 + * @summary verify that modPow() not broken by the special case for 65537 (use -Dseed=X to set PRNG seed) + * @author Andreas Sterbenz + * @key randomness + */ + +package test.java.math.BigInteger; + +import java.math.BigInteger; + +import java.security.*; +import java.security.spec.*; +import java.util.Random; +import jdk.test.lib.RandomFactory; + +public class ModPow65537 { + + public static void main(String[] args) throws Exception { + // BEGIN Android-removed: Test fails on Android. + // java.security.NoSuchProviderException: no such provider: SunRsaSign. + /* + // SunRsaSign uses BigInteger internally + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "SunRsaSign"); + kpg.initialize(new RSAKeyGenParameterSpec(512, BigInteger.valueOf(65537))); + KeyPair kp = kpg.generateKeyPair(); + testSigning(kp); + + kpg.initialize(new RSAKeyGenParameterSpec(512, BigInteger.valueOf(65539))); + kp = kpg.generateKeyPair(); + testSigning(kp); + + kpg.initialize(new RSAKeyGenParameterSpec(512, BigInteger.valueOf(3))); + kp = kpg.generateKeyPair(); + testSigning(kp); + + // basic known answer test + BigInteger base = new + BigInteger("19058071224156864789844466979330892664777520457048234786139035643344145635582"); + BigInteger mod = new + BigInteger("75554098474976067521257305210610421240510163914613117319380559667371251381587"); + BigInteger exp1 = BigInteger.valueOf(65537); + BigInteger exp2 = BigInteger.valueOf(75537); + BigInteger exp3 = new BigInteger("13456870775607312149"); + + BigInteger res1 = new + BigInteger("5770048609366563851320890693196148833634112303472168971638730461010114147506"); + BigInteger res2 = new + BigInteger("63446979364051087123350579021875958137036620431381329472348116892915461751531"); + BigInteger res3 = new + BigInteger("39016891919893878823999350081191675846357272199067075794096200770872982089502"); + + if (base.modPow(exp1, mod).equals(res1) == false) { + throw new Exception("Error using " + exp1); + } + if (base.modPow(exp2, mod).equals(res2) == false) { + throw new Exception("Error using " + exp2); + } + if (base.modPow(exp3, mod).equals(res3) == false) { + throw new Exception("Error using " + exp3); + } + + System.out.println("Passed"); + */ + // END Android-removed: Test fails on Android. + } + + // BEGIN Android-removed: Test fails on Android. + // java.security.NoSuchProviderException: no such provider: SunRsaSign. + /* + private static void testSigning(KeyPair kp) throws Exception { + System.out.println(kp.getPublic()); + byte[] data = new byte[1024]; + Random random = RandomFactory.getRandom(); + random.nextBytes(data); + + Signature sig = Signature.getInstance("SHA1withRSA", "SunRsaSign"); + sig.initSign(kp.getPrivate()); + sig.update(data); + byte[] sigBytes = sig.sign(); + + sig.initVerify(kp.getPublic()); + sig.update(data); + if (sig.verify(sigBytes) == false) { + throw new Exception("signature verification failed"); + } + System.out.println("OK"); + } + */ +} diff --git a/ojluni/src/test/java/math/BigInteger/ModPowPowersof2.java b/ojluni/src/test/java/math/BigInteger/ModPowPowersof2.java new file mode 100644 index 00000000000..11a0ea619ac --- /dev/null +++ b/ojluni/src/test/java/math/BigInteger/ModPowPowersof2.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1998, 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 4098742 + @summary Test biginteger modpow method + @author Michael McCloskey + @run main/othervm ModPowPowersof2 +*/ + +package test.java.math.BigInteger; + +import java.math.BigInteger; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.File; +import java.io.IOException; + +/** + * This class tests to see if using modPow on a power + * of two crashes the vm + * + */ +public class ModPowPowersof2 { + + public static void main(String args[]) throws Exception { + // BEGIN Android-removed: Test fails on Android. + // java.io.IOException: Cannot run program "<path-to-art>/bin/java": error=2, No such file or directory + /* + // Construct a command that runs the test in other vm + String[] command = new String[4]; + int n = 0; + + command[n++] = System.getProperty("java.home") + File.separator + + "bin" + File.separator + "java"; + if (System.getProperty("java.class.path") != null) { + command[n++] = "-classpath"; + command[n++] = System.getProperty("java.class.path"); + } + + command[n++] = "ModPowPowersof2$ModTester"; + + // Exec another vm to run test in + Process p = null; + p = Runtime.getRuntime().exec(command); + + // Read the result to determine if test failed + BufferedReader in = new BufferedReader(new InputStreamReader( + p.getInputStream())); + String s; + s = in.readLine(); + if (s == null) + throw new RuntimeException("ModPow causes vm crash"); + */ + // Android-removed Test fails on Android. + } + + // BEGIN Android-removed: Test fails on Android. + // java.io.IOException: Cannot run program "<path-to-art>/bin/java": error=2, No such file or directory + /* + public static class ModTester { + public static void main(String [] args) { + BigInteger two = BigInteger.valueOf(2); + BigInteger four = BigInteger.valueOf(4); + + two.modPow(two, BigInteger.valueOf(4)); + two.modPow(two, BigInteger.valueOf(8)); + two.modPow(four, BigInteger.valueOf(8)); + + System.out.println("success"); + } + } + */ + // Android-removed Test fails on Android. + +} diff --git a/ojluni/src/test/java/math/BigInteger/PrimeTest.java b/ojluni/src/test/java/math/BigInteger/PrimeTest.java index e0e4c886205..7a4cb048025 100644 --- a/ojluni/src/test/java/math/BigInteger/PrimeTest.java +++ b/ojluni/src/test/java/math/BigInteger/PrimeTest.java @@ -4,9 +4,7 @@ * * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. + * 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 diff --git a/ojluni/src/test/java/math/BigInteger/SerializationTests.java b/ojluni/src/test/java/math/BigInteger/SerializationTests.java new file mode 100644 index 00000000000..7faaca3c482 --- /dev/null +++ b/ojluni/src/test/java/math/BigInteger/SerializationTests.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2005, 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 + * 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 8282252 + * @summary Verify BigInteger objects are serialized properly. + */ + +package test.java.math.BigInteger; + +import java.math.*; +import java.io.*; +import java.util.Arrays; +import java.util.List; + +public class SerializationTests { + + public static void main(String... args) throws Exception { + checkBigIntegerSerialRoundTrip(); + checkBigIntegerSubSerialRoundTrip(); + } + + private static void checkSerialForm(BigInteger bi) throws Exception { + checkSerialForm0(bi); + checkSerialForm0(bi.negate()); + } + + private static void checkSerialForm0(BigInteger bi) throws Exception { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try(ObjectOutputStream oos = new ObjectOutputStream(bos)) { + oos.writeObject(bi); + oos.flush(); + } + + ObjectInputStream ois = new + ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); + BigInteger tmp = (BigInteger)ois.readObject(); + + if (!bi.equals(tmp) || + bi.hashCode() != tmp.hashCode() || + bi.getClass() != tmp.getClass() || + // For extra measure, directly test equality of components + bi.signum() != tmp.signum() || + !Arrays.equals(bi.toByteArray(), (tmp.toByteArray())) ) { + System.err.print(" original : " + bi); + System.err.println(" (hash: 0x" + Integer.toHexString(bi.hashCode()) + ")"); + System.err.print("serialized : " + tmp); + System.err.println(" (hash: 0x" + Integer.toHexString(tmp.hashCode()) + ")"); + throw new RuntimeException("Bad serial roundtrip"); + } + } + + private static void checkBigIntegerSerialRoundTrip() throws Exception { + var values = + List.of(BigInteger.ZERO, + BigInteger.ONE, + BigInteger.TWO, + BigInteger.TEN, + BigInteger.valueOf(100), + BigInteger.valueOf(Integer.MAX_VALUE), + BigInteger.valueOf(Long.MAX_VALUE-1), + new BigInteger("9223372036854775808")); // Long.MAX_VALUE + 1 + + for(BigInteger value : values) { + checkSerialForm(value); + } + } + + // Subclass with specialized toString output + private static class BigIntegerSub extends BigInteger { + public BigIntegerSub(BigInteger bi) { + super(bi.toByteArray()); + } + + @Override + public String toString() { + return Arrays.toString(toByteArray()); + } + } + + // Subclass defining a serialVersionUID + private static class BigIntegerSubSVUID extends BigInteger { + @java.io.Serial + private static long serialVesionUID = 0x0123_4567_89ab_cdefL; + + public BigIntegerSubSVUID(BigInteger bi) { + super(bi.toByteArray()); + } + + @Override + public String toString() { + return Arrays.toString(toByteArray()); + } + } + + // Subclass defining writeReplace + private static class BigIntegerSubWR extends BigInteger { + public BigIntegerSubWR(BigInteger bi) { + super(bi.toByteArray()); + } + + // Just return this; could use a serial proxy instead + @java.io.Serial + private Object writeReplace() throws ObjectStreamException { + return this; + } + } + + + private static void checkBigIntegerSubSerialRoundTrip() throws Exception { + var values = List.of(BigInteger.ZERO, + BigInteger.ONE, + BigInteger.TEN, + new BigInteger("9223372036854775808")); // Long.MAX_VALUE + 1 + + for(var value : values) { + checkSerialForm(new BigIntegerSub(value)); + checkSerialForm(new BigIntegerSubSVUID(value)); + checkSerialForm(new BigIntegerSubWR(value)); + } + } +} diff --git a/ojluni/src/test/java/nio/file/Path/PathOps.java b/ojluni/src/test/java/nio/file/Path/PathOps.java index 6c262231547..b2daa7787e6 100644 --- a/ojluni/src/test/java/nio/file/Path/PathOps.java +++ b/ojluni/src/test/java/nio/file/Path/PathOps.java @@ -27,6 +27,7 @@ */ package test.java.nio.file.Path; +import java.net.URI; import java.nio.file.FileSystems; import java.nio.file.InvalidPathException; import java.nio.file.Path; @@ -47,6 +48,14 @@ public class PathOps { } } + private PathOps(URI uri) { + try { + path = Path.of(uri); + } catch (Exception x) { + exc = x; + } + } + void checkPath() { if (path == null) { throw new InternalError("path is null"); @@ -480,6 +489,27 @@ public class PathOps { .name("bar"); } + // BEGIN Android-added: Tests for of(). + static PathOps testOf(String first) { + try { + return new PathOps(new URI (first)); + } catch (Exception e) { + return null; + } + } + + @Test + public static void doOfTests() { + Path cwd = Paths.get("").toAbsolutePath(); + + // construction + testOf("file:///foo/") + .string("/foo"); + testOf("file:///foo/bar/gus/") + .string("/foo/bar/gus"); + } + // END Android-added: Tests for of(). + @Test public static void npes() { try { diff --git a/ojluni/src/test/java/text/AttributedCharacterIterator/Attribute/ReadResolve.java b/ojluni/src/test/java/text/AttributedCharacterIterator/Attribute/ReadResolve.java new file mode 100644 index 00000000000..022d33a30db --- /dev/null +++ b/ojluni/src/test/java/text/AttributedCharacterIterator/Attribute/ReadResolve.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1998, 2016, 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 4136620 4144590 + @summary Make sure that Attribute & subclasses are serialized and deserialized correctly + @modules java.desktop + */ + +package test.java.text.AttributedCharacterIterator.Attribute; + +import java.text.AttributedCharacterIterator.Attribute; +import java.awt.font.TextAttribute; +import java.io.*; + +public class ReadResolve { + + public static void main(String[] args) throws Exception { + testSerializationCycle(Attribute.LANGUAGE); + testSerializationCycle(TextAttribute.INPUT_METHOD_HIGHLIGHT); + + boolean gotException = false; + Attribute result = null; + try { + result = doSerializationCycle(FakeAttribute.LANGUAGE); + } catch (Throwable e) { + gotException = true; + } + if (!gotException) { + throw new RuntimeException("Attribute should throw an exception when given a fake \"language\" attribute. Deserialized object: " + result); + } + } + + static Attribute doSerializationCycle(Attribute attribute) throws Exception { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(attribute); + oos.flush(); + + byte[] data = baos.toByteArray(); + + ByteArrayInputStream bais = new ByteArrayInputStream(data); + ObjectInputStream ois = new ObjectInputStream(bais); + Attribute result = (Attribute) ois.readObject(); + + return result; + } + + static void testSerializationCycle(Attribute attribute) throws Exception { + Attribute result = doSerializationCycle(attribute); + if (result != attribute) { + throw new RuntimeException("attribute changed identity during serialization/deserialization"); + } + } + + private static class FakeAttribute extends Attribute { + + // This LANGUAGE attribute should never be confused with the + // Attribute.LANGUAGE attribute. However, we don't override + // readResolve here, so that deserialization goes + // to Attribute. Attribute has to catch this problem and reject + // the fake attribute. + static final FakeAttribute LANGUAGE = new FakeAttribute("language"); + + FakeAttribute(String name) { + super(name); + } + } +} diff --git a/ojluni/src/test/java/text/AttributedString/AttributedStringTest.java b/ojluni/src/test/java/text/AttributedString/AttributedStringTest.java new file mode 100644 index 00000000000..034fa6ebcbb --- /dev/null +++ b/ojluni/src/test/java/text/AttributedString/AttributedStringTest.java @@ -0,0 +1,260 @@ +/* + * Copyright (c) 1998, 2016, 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 4139771 + * @summary test all aspects of AttributedString class + */ + +package test.java.text.AttributedString; + +import java.text.Annotation; +import java.text.AttributedCharacterIterator; +import java.text.AttributedCharacterIterator.Attribute; +import java.text.AttributedString; +import java.text.CharacterIterator; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + + +public class AttributedStringTest { + + private static final String text = "Hello, world!"; + private static final Annotation hi = new Annotation("hi"); + private static final int[] array5_13 = {5, 13}; + private static final int[] array3_9_13 = {3, 9, 13}; + private static final int[] array5_9_13 = {5, 9, 13}; + private static final int[] array3_5_9_13 = {3, 5, 9, 13}; + private static final Attribute[] arrayLanguage = {Attribute.LANGUAGE}; + private static final Attribute[] arrayLanguageReading = {Attribute.LANGUAGE, Attribute.READING}; + private static final Set setLanguageReading = new HashSet(); + static { + setLanguageReading.add(Attribute.LANGUAGE); + setLanguageReading.add(Attribute.READING); + } + + + public static final void main(String argv[]) throws Exception { + + + AttributedString string; + AttributedCharacterIterator iterator; + + // create a string with text, but no attributes + string = new AttributedString(text); + iterator = string.getIterator(); + + // make sure the text is there and attributes aren't + checkIteratorText(iterator, text); + if (!iterator.getAllAttributeKeys().isEmpty()) { + throwException(iterator, "iterator provides attributes where none are defined"); + } + + // add an attribute to a subrange + string.addAttribute(Attribute.LANGUAGE, Locale.ENGLISH, 3, 9); + iterator = string.getIterator(); + + // make sure the attribute is defined, and it's on the correct subrange + checkIteratorAttributeKeys(iterator, arrayLanguage); + checkIteratorSubranges(iterator, array3_9_13); + checkIteratorAttribute(iterator, 0, Attribute.LANGUAGE, null); + checkIteratorAttribute(iterator, 3, Attribute.LANGUAGE, Locale.ENGLISH); + checkIteratorAttribute(iterator, 9, Attribute.LANGUAGE, null); + + // add an attribute to a subrange + string.addAttribute(Attribute.READING, hi, 0, 5); + iterator = string.getIterator(); + + // make sure the attribute is defined, and it's on the correct subrange + checkIteratorAttributeKeys(iterator, arrayLanguageReading); + checkIteratorSubranges(iterator, array3_5_9_13); + checkIteratorAttribute(iterator, 0, Attribute.READING, hi); + checkIteratorAttribute(iterator, 3, Attribute.READING, hi); + checkIteratorAttribute(iterator, 5, Attribute.READING, null); + checkIteratorAttribute(iterator, 9, Attribute.READING, null); + + // make sure the first attribute wasn't adversely affected + // in particular, we shouldn't see separate subranges (3,5) and (5,9). + checkIteratorSubranges(iterator, Attribute.LANGUAGE, array3_9_13); + checkIteratorAttribute(iterator, 0, Attribute.LANGUAGE, null); + checkIteratorAttribute(iterator, 3, Attribute.LANGUAGE, Locale.ENGLISH); + checkIteratorAttribute(iterator, 5, Attribute.LANGUAGE, Locale.ENGLISH); + checkIteratorAttribute(iterator, 9, Attribute.LANGUAGE, null); + + // for the entire set of attributes, we expect four subranges + checkIteratorSubranges(iterator, setLanguageReading, array3_5_9_13); + + // redefine the language attribute so that both language and reading are continuous from 0 to 5 + string.addAttribute(Attribute.LANGUAGE, Locale.US, 0, 5); + iterator = string.getIterator(); + + // make sure attributes got changed and merged correctly + checkIteratorAttributeKeys(iterator, arrayLanguageReading); + checkIteratorSubranges(iterator, array3_5_9_13); + checkIteratorSubranges(iterator, Attribute.LANGUAGE, array5_9_13); + checkIteratorSubranges(iterator, Attribute.READING, array5_13); + checkIteratorSubranges(iterator, setLanguageReading, array5_9_13); + checkIteratorAttribute(iterator, 0, Attribute.LANGUAGE, Locale.US); + checkIteratorAttribute(iterator, 3, Attribute.LANGUAGE, Locale.US); + checkIteratorAttribute(iterator, 5, Attribute.LANGUAGE, Locale.ENGLISH); + checkIteratorAttribute(iterator, 9, Attribute.LANGUAGE, null); + + // make sure an annotation is only returned if its range is contained in the iterator's range + iterator = string.getIterator(null, 3, 5); + checkIteratorAttribute(iterator, 3, Attribute.READING, null); + checkIteratorAttribute(iterator, 5, Attribute.READING, null); + iterator = string.getIterator(null, 0, 4); + checkIteratorAttribute(iterator, 0, Attribute.READING, null); + checkIteratorAttribute(iterator, 3, Attribute.READING, null); + iterator = string.getIterator(null, 0, 5); + checkIteratorAttribute(iterator, 0, Attribute.READING, hi); + checkIteratorAttribute(iterator, 4, Attribute.READING, hi); + checkIteratorAttribute(iterator, 5, Attribute.READING, null); + + } + + private static final void checkIteratorText(AttributedCharacterIterator iterator, String expectedText) throws Exception { + if (iterator.getEndIndex() - iterator.getBeginIndex() != expectedText.length()) { + throwException(iterator, "text length doesn't match between original text and iterator"); + } + + char c = iterator.first(); + for (int i = 0; i < expectedText.length(); i++) { + if (c != expectedText.charAt(i)) { + throwException(iterator, "text content doesn't match between original text and iterator"); + } + c = iterator.next(); + } + if (c != CharacterIterator.DONE) { + throwException(iterator, "iterator text doesn't end with DONE"); + } + } + + private static final void checkIteratorAttributeKeys(AttributedCharacterIterator iterator, Attribute[] expectedKeys) throws Exception { + Set iteratorKeys = iterator.getAllAttributeKeys(); + if (iteratorKeys.size() != expectedKeys.length) { + throwException(iterator, "number of keys returned by iterator doesn't match expectation"); + } + for (int i = 0; i < expectedKeys.length; i++) { + if (!iteratorKeys.contains(expectedKeys[i])) { + throwException(iterator, "expected key wasn't found in iterator's key set"); + } + } + } + + private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, int[] expectedLimits) throws Exception { + int previous = 0; + char c = iterator.first(); + for (int i = 0; i < expectedLimits.length; i++) { + if (iterator.getRunStart() != previous || iterator.getRunLimit() != expectedLimits[i]) { + throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart() + ", " + iterator.getRunLimit()); + } + previous = expectedLimits[i]; + c = iterator.setIndex(previous); + } + if (c != CharacterIterator.DONE) { + throwException(iterator, "iterator's run sequence doesn't end with DONE"); + } + } + + private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, Attribute key, int[] expectedLimits) throws Exception { + int previous = 0; + char c = iterator.first(); + for (int i = 0; i < expectedLimits.length; i++) { + if (iterator.getRunStart(key) != previous || iterator.getRunLimit(key) != expectedLimits[i]) { + throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart(key) + ", " + iterator.getRunLimit(key) + " for key " + key); + } + previous = expectedLimits[i]; + c = iterator.setIndex(previous); + } + if (c != CharacterIterator.DONE) { + throwException(iterator, "iterator's run sequence doesn't end with DONE"); + } + } + + private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, Set keys, int[] expectedLimits) throws Exception { + int previous = 0; + char c = iterator.first(); + for (int i = 0; i < expectedLimits.length; i++) { + if (iterator.getRunStart(keys) != previous || iterator.getRunLimit(keys) != expectedLimits[i]) { + throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart(keys) + ", " + iterator.getRunLimit(keys) + " for keys " + keys); + } + previous = expectedLimits[i]; + c = iterator.setIndex(previous); + } + if (c != CharacterIterator.DONE) { + throwException(iterator, "iterator's run sequence doesn't end with DONE"); + } + } + + private static final void checkIteratorAttribute(AttributedCharacterIterator iterator, int index, Attribute key, Object expectedValue) throws Exception { + iterator.setIndex(index); + Object value = iterator.getAttribute(key); + if (!((expectedValue == null && value == null) || (expectedValue != null && expectedValue.equals(value)))) { + throwException(iterator, "iterator returns wrong attribute value - " + value + " instead of " + expectedValue); + } + value = iterator.getAttributes().get(key); + if (!((expectedValue == null && value == null) || (expectedValue != null && expectedValue.equals(value)))) { + throwException(iterator, "iterator's map returns wrong attribute value - " + value + " instead of " + expectedValue); + } + } + + private static final void throwException(AttributedCharacterIterator iterator, String details) throws Exception { + dumpIterator(iterator); + throw new Exception(details); + } + + private static final void dumpIterator(AttributedCharacterIterator iterator) { + Set attributeKeys = iterator.getAllAttributeKeys(); + System.out.print("All attributes: "); + Iterator keyIterator = attributeKeys.iterator(); + while (keyIterator.hasNext()) { + Attribute key = (Attribute) keyIterator.next(); + System.out.print(key); + } + for(char c = iterator.first(); c != CharacterIterator.DONE; c = iterator.next()) { + if (iterator.getIndex() == iterator.getBeginIndex() || + iterator.getIndex() == iterator.getRunStart()) { + System.out.println(); + Map attributes = iterator.getAttributes(); + Set entries = attributes.entrySet(); + Iterator attributeIterator = entries.iterator(); + while (attributeIterator.hasNext()) { + Map.Entry entry = (Map.Entry) attributeIterator.next(); + System.out.print("<" + entry.getKey() + ": " + + entry.getValue() + ">"); + } + } + System.out.print(" "); + System.out.print(c); + } + System.out.println(); + System.out.println("done"); + System.out.println(); + } + +} diff --git a/ojluni/src/test/java/text/AttributedString/TestAttributedStringCtor.java b/ojluni/src/test/java/text/AttributedString/TestAttributedStringCtor.java new file mode 100644 index 00000000000..fdc4cc72886 --- /dev/null +++ b/ojluni/src/test/java/text/AttributedString/TestAttributedStringCtor.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1998, 2016, 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 4146853 + * @summary Make sure we can construct an AttributedString from + * an AttributedCharacterIterator covering only a subrange + * @modules java.desktop + */ + +package test.java.text.AttributedString; + +import java.awt.font.TextAttribute; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java.util.Hashtable; + +public class TestAttributedStringCtor { + + public static void main(String[] args) { + + // Create a new AttributedString with one attribute. + Hashtable attributes = new Hashtable(); + attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD); + AttributedString origString = new AttributedString("Hello world.", attributes); + + // Create an iterator over part of the AttributedString. + AttributedCharacterIterator iter = origString.getIterator(null, 4, 6); + + // Attempt to create a new AttributedString from the iterator. + // This will throw IllegalArgumentException. + AttributedString newString = new AttributedString(iter); + + // Without the exception this would get executed. + System.out.println("DONE"); + } +} diff --git a/ojluni/src/test/java/text/AttributedString/getRunStartLimitTest.java b/ojluni/src/test/java/text/AttributedString/getRunStartLimitTest.java new file mode 100644 index 00000000000..62d4e781d53 --- /dev/null +++ b/ojluni/src/test/java/text/AttributedString/getRunStartLimitTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 1998, 2016, 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 4151160 + * @summary Make sure to return correct run start and limit values + * when the iterator has been created with begin and end index values. + * @modules java.desktop + */ + +package test.java.text.AttributedString; + +import java.awt.font.TextAttribute; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java.text.Annotation; + +public class getRunStartLimitTest { + + public static void main(String[] args) throws Exception { + + String text = "Hello world"; + AttributedString as = new AttributedString(text); + + // add non-Annotation attributes + as.addAttribute(TextAttribute.WEIGHT, + TextAttribute.WEIGHT_LIGHT, + 0, + 3); + as.addAttribute(TextAttribute.WEIGHT, + TextAttribute.WEIGHT_BOLD, + 3, + 5); + as.addAttribute(TextAttribute.WEIGHT, + TextAttribute.WEIGHT_EXTRABOLD, + 5, + text.length()); + + // add Annotation attributes + as.addAttribute(TextAttribute.WIDTH, + new Annotation(TextAttribute.WIDTH_EXTENDED), + 0, + 3); + as.addAttribute(TextAttribute.WIDTH, + new Annotation(TextAttribute.WIDTH_CONDENSED), + 3, + 4); + + AttributedCharacterIterator aci = as.getIterator(null, 2, 4); + + aci.first(); + int runStart = aci.getRunStart(); + if (runStart != 2) { + throw new Exception("1st run start is wrong. ("+runStart+" should be 2.)"); + } + + int runLimit = aci.getRunLimit(); + if (runLimit != 3) { + throw new Exception("1st run limit is wrong. ("+runLimit+" should be 3.)"); + } + + Object value = aci.getAttribute(TextAttribute.WEIGHT); + if (value != TextAttribute.WEIGHT_LIGHT) { + throw new Exception("1st run attribute is wrong. (" + +value+" should be "+TextAttribute.WEIGHT_LIGHT+".)"); + } + + value = aci.getAttribute(TextAttribute.WIDTH); + if (value != null) { + throw new Exception("1st run annotation is wrong. (" + +value+" should be null.)"); + } + + aci.setIndex(runLimit); + runStart = aci.getRunStart(); + if (runStart != 3) { + throw new Exception("2nd run start is wrong. ("+runStart+" should be 3.)"); + } + + runLimit = aci.getRunLimit(); + if (runLimit != 4) { + throw new Exception("2nd run limit is wrong. ("+runLimit+" should be 4.)"); + } + value = aci.getAttribute(TextAttribute.WEIGHT); + if (value != TextAttribute.WEIGHT_BOLD) { + throw new Exception("2nd run attribute is wrong. (" + +value+" should be "+TextAttribute.WEIGHT_BOLD+".)"); + } + + value = aci.getAttribute(TextAttribute.WIDTH); + if (!(value instanceof Annotation) + || (((Annotation)value).getValue() != TextAttribute.WIDTH_CONDENSED)) { + throw new Exception("2nd run annotation is wrong. (" + value + " should be " + + new Annotation(TextAttribute.WIDTH_CONDENSED)+".)"); + } + } +} diff --git a/ojluni/src/test/java/text/BreakIterator/Bug4533872.java b/ojluni/src/test/java/text/BreakIterator/Bug4533872.java new file mode 100644 index 00000000000..c9bbe4520df --- /dev/null +++ b/ojluni/src/test/java/text/BreakIterator/Bug4533872.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2003, 2016, 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 4533872 4640853 + * @library /java/text/testlib + * @summary Unit tests for supplementary character support (JSR-204) and Unicode 4.0 support + */ + +package test.java.text.BreakIterator; + +import java.text.BreakIterator; +import java.util.Locale; + +import test.java.text.testlib.IntlTest; + +public class Bug4533872 extends IntlTest { + + public static void main(String[] args) throws Exception { + new Bug4533872().run(args); + } + + static final String[] given = { + /* Lu Nd Lu Ll */ + "XYZ12345 ABCDE abcde", + /* Nd Lo Nd Lu Po Lu Ll */ + "123\uD800\uDC00345 ABC\uFF61XYZ abc", + /* Nd Lo Nd Lu Po Lu Ll */ + "123\uD800\uDC00345 ABC\uD800\uDD00XYZ abc", + /* Lu Ll Cs Ll Cs Lu Lo Lu */ + "ABCabc\uDC00xyz\uD800ABC\uD800\uDC00XYZ", + }; + + // Golden data for TestNext(), TestBoundar() and TestPrintEach*ward() + static final String[][] expected = { + {"XYZ12345", " ", "ABCDE", " ", "abcde"}, + {"123\uD800\uDC00345", " ", "ABC", "\uFF61", "XYZ", " ", "abc"}, + {"123\uD800\uDC00345", " ", "ABC", "\uD800\uDD00", "XYZ", " ", "abc"}, + {"ABCabc", "\uDC00", "xyz", "\uD800", "ABC\uD800\uDC00XYZ"}, + }; + + BreakIterator iter; + int start, end, current; + + /* + * Test for next(int n) + */ + void TestNext() { + iter = BreakIterator.getWordInstance(Locale.US); + + for (int i = 0; i < given.length; i++) { + iter.setText(given[i]); + start = iter.first(); + int j = expected[i].length - 1; + start = iter.next(j); + end = iter.next(); + + if (!expected[i][j].equals(given[i].substring(start, end))) { + errln("Word break failure: printEachForward() expected:<" + + expected[i][j] + ">, got:<" + + given[i].substring(start, end) + + "> start=" + start + " end=" + end); + } + } + } + + /* + * Test for isBoundary(int n) + */ + void TestIsBoundary() { + iter = BreakIterator.getWordInstance(Locale.US); + + for (int i = 0; i < given.length; i++) { + iter.setText(given[i]); + + start = iter.first(); + end = iter.next(); + + while (end < given[i].length()) { + if (!iter.isBoundary(end)) { + errln("Word break failure: isBoundary() This should be a boundary. Index=" + + end + " for " + given[i]); + } + end = iter.next(); + } + } + } + + + /* + * The followig test cases were made based on examples in BreakIterator's + * API Doc. + */ + + /* + * Test mainly for next() and current() + */ + void TestPrintEachForward() { + iter = BreakIterator.getWordInstance(Locale.US); + + for (int i = 0; i < given.length; i++) { + iter.setText(given[i]); + start = iter.first(); + + // Check current()'s return value - should be same as first()'s. + current = iter.current(); + if (start != current) { + errln("Word break failure: printEachForward() Unexpected current value: current()=" + + current + ", expected(=first())=" + start); + } + + int j = 0; + for (end = iter.next(); + end != BreakIterator.DONE; + start = end, end = iter.next(), j++) { + + // Check current()'s return value - should be same as next()'s. + current = iter.current(); + if (end != current) { + errln("Word break failure: printEachForward() Unexpected current value: current()=" + + current + ", expected(=next())=" + end); + } + + if (!expected[i][j].equals(given[i].substring(start, end))) { + errln("Word break failure: printEachForward() expected:<" + + expected[i][j] + ">, got:<" + + given[i].substring(start, end) + + "> start=" + start + " end=" + end); + } + } + } + } + + /* + * Test mainly for previous() and current() + */ + void TestPrintEachBackward() { + iter = BreakIterator.getWordInstance(Locale.US); + + for (int i = 0; i < given.length; i++) { + iter.setText(given[i]); + end = iter.last(); + + // Check current()'s return value - should be same as last()'s. + current = iter.current(); + if (end != current) { + errln("Word break failure: printEachBackward() Unexpected current value: current()=" + + current + ", expected(=last())=" + end); + } + + int j; + for (start = iter.previous(), j = expected[i].length-1; + start != BreakIterator.DONE; + end = start, start = iter.previous(), j--) { + + // Check current()'s return value - should be same as previous()'s. + current = iter.current(); + if (start != current) { + errln("Word break failure: printEachBackward() Unexpected current value: current()=" + + current + ", expected(=previous())=" + start); + } + + if (!expected[i][j].equals(given[i].substring(start, end))) { + errln("Word break failure: printEachBackward() expected:<" + + expected[i][j] + ">, got:<" + + given[i].substring(start, end) + + "> start=" + start + " end=" + end); + } + } + } + } + + /* + * Test mainly for following() and previous() + */ + void TestPrintAt_1() { + iter = BreakIterator.getWordInstance(Locale.US); + + int[][] index = { + {2, 8, 10, 15, 17}, + {1, 8, 10, 12, 15, 17, 20}, + {3, 8, 10, 13, 16, 18, 20}, + {4, 6, 9, 10, 16}, + }; + + for (int i = 0; i < given.length; i++) { + iter.setText(given[i]); + for (int j = index[i].length-1; j >= 0; j--) { + end = iter.following(index[i][j]); + start = iter.previous(); + + if (!expected[i][j].equals(given[i].substring(start, end))) { + errln("Word break failure: printAt_1() expected:<" + + expected[i][j] + ">, got:<" + + given[i].substring(start, end) + + "> start=" + start + " end=" + end); + } + } + } + } + + /* + * Test mainly for preceding() and next() + */ + void TestPrintAt_2() { + iter = BreakIterator.getWordInstance(Locale.US); + + int[][] index = { + {2, 9, 10, 15, 17}, + {1, 9, 10, 13, 16, 18, 20}, + {4, 9, 10, 13, 16, 18, 20}, + {6, 7, 10, 11, 15}, + }; + + for (int i = 0; i < given.length; i++) { + iter.setText(given[i]); + + // Check preceding(0)'s return value - should equals BreakIterator.DONE. + if (iter.preceding(0) != BreakIterator.DONE) { + errln("Word break failure: printAt_2() expected:-1(BreakIterator.DONE), got:" + + iter.preceding(0)); + } + + for (int j = 0; j < index[i].length; j++) { + start = iter.preceding(index[i][j]); + end = iter.next(); + + if (!expected[i][j].equals(given[i].substring(start, end))) { + errln("Word break failure: printAt_2() expected:<" + + expected[i][j] + ">, got:<" + + given[i].substring(start, end) + + "> start=" + start + " end=" + end); + } + } + + // Check next()'s return value - should equals BreakIterator.DONE. + end = iter.last(); + start = iter.next(); + if (start != BreakIterator.DONE) { + errln("Word break failure: printAt_2() expected:-1(BreakIterator.DONE), got:" + start); + } + } + } +} diff --git a/ojluni/src/test/java/text/BreakIterator/Bug4740757.java b/ojluni/src/test/java/text/BreakIterator/Bug4740757.java new file mode 100644 index 00000000000..7b20289ad13 --- /dev/null +++ b/ojluni/src/test/java/text/BreakIterator/Bug4740757.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2011, 2016, 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 4740757 + * @summary Confirm line-breaking behavior of Hangul + */ + +package test.java.text.BreakIterator; + +import java.text.*; +import java.util.*; + +public class Bug4740757 { + + private static boolean err = false; + + public static void main(String[] args) { + Locale defaultLocale = Locale.getDefault(); + if (defaultLocale.getLanguage().equals("th")) { + Locale.setDefault(Locale.KOREA); + test4740757(); + Locale.setDefault(defaultLocale); + } else { + test4740757(); + } + + if (err) { + throw new RuntimeException("Incorrect Line-breaking"); + } + } + + private static void test4740757() { + String source = "\uc548\ub155\ud558\uc138\uc694? \uc88b\uc740 \uc544\uce68, \uc5ec\ubcf4\uc138\uc694! \uc548\ub155. End."; + String expected = "\uc548/\ub155/\ud558/\uc138/\uc694? /\uc88b/\uc740 /\uc544/\uce68, /\uc5ec/\ubcf4/\uc138/\uc694! /\uc548/\ub155. /End./"; + + BreakIterator bi = BreakIterator.getLineInstance(Locale.KOREAN); + bi.setText(source); + int start = bi.first(); + int end = bi.next(); + StringBuilder sb = new StringBuilder(); + + for (; end != BreakIterator.DONE; start = end, end = bi.next()) { + sb.append(source.substring(start,end)); + sb.append('/'); + } + + if (!expected.equals(sb.toString())) { + System.err.println("Failed: Hangul line-breaking failed." + + "\n\tExpected: " + expected + + "\n\tGot: " + sb + + "\nin " + Locale.getDefault() + " locale."); + err = true; + } + } + +} diff --git a/ojluni/src/test/java/text/BreakIterator/Bug4912404.java b/ojluni/src/test/java/text/BreakIterator/Bug4912404.java new file mode 100644 index 00000000000..2ad9573b3c7 --- /dev/null +++ b/ojluni/src/test/java/text/BreakIterator/Bug4912404.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2003, 2016, 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 4912404 + * @summary Confirm that BreakIterator.equals(null) return false. + */ + +package test.java.text.BreakIterator; + +import java.text.BreakIterator; + +public class Bug4912404 { + + public static void main(String[] args) { + BreakIterator b = BreakIterator.getWordInstance(); + b.setText("abc"); + if (b.equals(null)) { + throw new RuntimeException("BreakIterator.equals(null) should return false."); + } + } +} diff --git a/ojluni/src/test/java/text/BreakIterator/Bug4932583.java b/ojluni/src/test/java/text/BreakIterator/Bug4932583.java new file mode 100644 index 00000000000..1b52b604e91 --- /dev/null +++ b/ojluni/src/test/java/text/BreakIterator/Bug4932583.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2003, 2016, 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 + * @run main/timeout=60 Bug4932583 + * @bug 4932583 + * @summary Confirm that BreakIterator doesn't get caught in an infinite loop. + */ + +package test.java.text.BreakIterator; + +import java.text.*; +import java.util.*; +import java.io.*; + +public class Bug4932583 { + public static void main(String[] args) { + BreakIterator iterator = BreakIterator.getCharacterInstance(); + iterator.setText("\uDB40\uDFFF"); + int boundary = iterator.next(); + } +} diff --git a/ojluni/src/test/java/text/BreakIterator/Bug7104012.java b/ojluni/src/test/java/text/BreakIterator/Bug7104012.java new file mode 100644 index 00000000000..acfc8b0ec13 --- /dev/null +++ b/ojluni/src/test/java/text/BreakIterator/Bug7104012.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2012, 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 7104012 + * @summary Confirm that AIOBE is not thrown. + */ + +package test.java.text.BreakIterator; + +import java.text.*; +import java.util.*; + +public class Bug7104012 { + + public static void main(String[] args) { + boolean err = false; + + List<String> data = new ArrayList<>(); + data.add("\udb40"); + data.add(" \udb40"); + data.add("\udc53"); + data.add(" \udc53"); + data.add(" \udb40\udc53"); + data.add("\udb40\udc53"); + data.add("ABC \udb40\udc53 123"); + data.add("\udb40\udc53 ABC \udb40\udc53"); + + for (Locale locale : Locale.getAvailableLocales()) { + List<BreakIterator> breakIterators = new ArrayList<>(); + breakIterators.add(BreakIterator.getCharacterInstance(locale)); + breakIterators.add(BreakIterator.getLineInstance(locale)); + breakIterators.add(BreakIterator.getSentenceInstance(locale)); + breakIterators.add(BreakIterator.getWordInstance(locale)); + + for (BreakIterator bi : breakIterators) { + for (String str : data) { + try { + bi.setText(str); + bi.first(); + while (bi.next() != BreakIterator.DONE) { } + bi.last(); + while (bi.previous() != BreakIterator.DONE) { } + } + catch (ArrayIndexOutOfBoundsException ex) { + System.out.println(" " + data.indexOf(str) + + ": BreakIterator(" + locale + + ") threw AIOBE."); + err = true; + } + } + } + } + + if (err) { + throw new RuntimeException("Unexpected exeption."); + } + } + +} diff --git a/ojluni/src/test/java/text/BreakIterator/Bug8032446.java b/ojluni/src/test/java/text/BreakIterator/Bug8032446.java new file mode 100644 index 00000000000..731242e50bb --- /dev/null +++ b/ojluni/src/test/java/text/BreakIterator/Bug8032446.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, 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 8032446 + * @summary Confirm that BreakIterator works as expected with new characters in Unicode 7. + */ + +package test.java.text.BreakIterator; + +import java.text.*; +import java.util.*; + +public class Bug8032446 { + + public static void main(String[] args) { + boolean err = false; + + StringBuilder sb = new StringBuilder(); + for (int i = 0x10860; i <= 0x10876; i++) { // Palmyrene Letters + sb.append(Character.toChars(i)); + } + sb.append(" "); + for (int i = 0x10879; i <= 0x1087D; i++) { // Palmyrene Numbers + sb.append(Character.toChars(i)); + } + String s = sb.toString(); + + BreakIterator bi = BreakIterator.getWordInstance(Locale.ROOT); + bi.setText(s); + bi.first(); + + if (bi.next() != s.indexOf(' ')) { + throw new RuntimeException("Unexpected word breaking."); + } + } + +} diff --git a/ojluni/src/test/java/text/BreakIterator/ExceptionTest.java b/ojluni/src/test/java/text/BreakIterator/ExceptionTest.java new file mode 100644 index 00000000000..24318717ae5 --- /dev/null +++ b/ojluni/src/test/java/text/BreakIterator/ExceptionTest.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2007, 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 6521742 + * @summary test exceptions + */ + +package test.java.text.BreakIterator; + +import java.text.*; +import java.util.*; +import static java.text.BreakIterator.DONE; + +public class ExceptionTest { + private static final String text = + "An ordered collection (also known as a sequence). " + + "The user of this interface has precise control over " + + "where in the list each element is inserted. " + + "The user can access elements by their integer index (position in the list), " + + "and search for elements in the list."; + + public static void main(String[] args) { + BreakIterator bi = BreakIterator.getWordInstance(); + bi.setText(text); + MirroredBreakIterator mirror = new MirroredBreakIterator(bi); + final int first = bi.first(); + if (first != 0) { + throw new RuntimeException("first != 0: " + first); + } + final int last = bi.last(); + bi = BreakIterator.getWordInstance(); + bi.setText(text); + int length = text.length(); + + /* + * following(int) + */ + for (int i = 0; i <= length; i++) { + if (i == length) { + check(bi.following(i), DONE); + } + check(bi.following(i), mirror.following(i)); + check(bi.current(), mirror.current()); + } + for (int i = -length; i < 0; i++) { + checkFollowingException(bi, i); + checkFollowingException(mirror, i); + check(bi.current(), mirror.current()); + } + for (int i = 1; i < length; i++) { + checkFollowingException(bi, length + i); + checkFollowingException(mirror, length + i); + check(bi.current(), mirror.current()); + } + + /* + * preceding(int) + */ + for (int i = length; i >= 0; i--) { + if (i == 0) { + check(bi.preceding(i), DONE); + } + check(bi.preceding(i), mirror.preceding(i)); + check(bi.current(), mirror.current()); + } + for (int i = -length; i < 0; i++) { + checkPrecedingException(bi, i); + checkPrecedingException(mirror, i); + check(bi.current(), mirror.current()); + } + for (int i = 1; i < length; i++) { + checkPrecedingException(bi, length + i); + checkPrecedingException(mirror, length + i); + check(bi.current(), mirror.current()); + } + + /* + * isBoundary(int) + */ + for (int i = 0; i <= length; i++) { + check(bi.isBoundary(i), mirror.isBoundary(i)); + check(bi.current(), mirror.current()); + } + for (int i = -length; i < 0; i++) { + checkIsBoundaryException(bi, i); + checkIsBoundaryException(mirror, i); + } + for (int i = 1; i < length; i++) { + checkIsBoundaryException(bi, length + i); + checkIsBoundaryException(mirror, length + i); + } + } + + private static void check(int i1, int i2) { + if (i1 != i2) { + throw new RuntimeException(i1 + " != " + i2); + } + } + + private static void check(boolean b1, boolean b2) { + if (b1 != b2) { + throw new RuntimeException(b1 + " != " + b2); + } + } + + private static void checkFollowingException(BreakIterator bi, int offset) { + try { + bi.following(offset); + } catch (IllegalArgumentException e) { + return; // OK + } + throw new RuntimeException(bi + ": following() doesn't throw an IAE with offset " + + offset); + } + + private static void checkPrecedingException(BreakIterator bi, int offset) { + try { + bi.preceding(offset); + } catch (IllegalArgumentException e) { + return; // OK + } + throw new RuntimeException(bi + ": preceding() doesn't throw an IAE with offset " + + offset); + } + + private static void checkIsBoundaryException(BreakIterator bi, int offset) { + try { + bi.isBoundary(offset); + } catch (IllegalArgumentException e) { + return; // OK + } + throw new RuntimeException(bi + ": isBoundary() doesn't throw an IAE with offset " + + offset); + } +} diff --git a/ojluni/src/test/java/text/BreakIterator/MirroredBreakIterator.java b/ojluni/src/test/java/text/BreakIterator/MirroredBreakIterator.java new file mode 100644 index 00000000000..79ccc091fc8 --- /dev/null +++ b/ojluni/src/test/java/text/BreakIterator/MirroredBreakIterator.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2007, 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. + */ + +package test.java.text.BreakIterator; + +import java.text.BreakIterator; +import java.text.CharacterIterator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +public class MirroredBreakIterator extends BreakIterator { + private final List<Integer> boundaries; + private int charIndex; + private int boundaryIndex; + + MirroredBreakIterator(BreakIterator bi) { + List<Integer> b = new ArrayList<Integer>(); + int i = bi.first(); + charIndex = i; + for (; i != DONE; i = bi.next()) { + b.add(i); + } + boundaries = Collections.unmodifiableList(b); + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (Exception e) { + throw new RuntimeException("clone failed", e); + } + } + + @Override + public int first() { + return changeIndices(0); + } + + @Override + public int last() { + return changeIndices(boundaries.size() - 1); + } + + @Override + public int next(int n) { + if (n == 0) { + return current(); + } + int newBoundary = boundaryIndex + n; + if (newBoundary < 0) { + first(); + return DONE; + } + if (newBoundary > lastBoundary()) { + last(); + return DONE; + } + return changeIndices(newBoundary); + } + + @Override + public int next() { + if (boundaryIndex == lastBoundary()) { + return DONE; + } + return changeIndices(boundaryIndex + 1); + } + + @Override + public int previous() { + if (boundaryIndex == 0) { + return DONE; + } + return changeIndices(boundaryIndex - 1); + } + + @Override + public int following(int offset) { + validateOffset(offset); + for (int b = 0; b <= lastBoundary(); b++) { + int i = boundaries.get(b); + if (i > offset) { + return changeIndices(i, b); + } + } + return DONE; + } + + @Override + public int preceding(int offset) { + validateOffset(offset); + for (int b = lastBoundary(); b >= 0; b--) { + int i = boundaries.get(b); + if (i < offset) { + return changeIndices(i, b); + } + } + return DONE; + } + + @Override + public boolean isBoundary(int offset) { + // Call the default impelementation in BreakIterator + return super.isBoundary(offset); + } + + @Override + public int current() { + return charIndex; + } + + @Override + public CharacterIterator getText() { + throw new UnsupportedOperationException(); + } + + @Override + public void setText(CharacterIterator newText) { + throw new UnsupportedOperationException(); + } + + private int lastBoundary() { + return boundaries.size() - 1; + } + + private int changeIndices(int newCharIndex, int newBoundary) { + boundaryIndex = newBoundary; + return charIndex = newCharIndex; + } + + private int changeIndices(int newBoundary) { + try { + return changeIndices(boundaries.get(newBoundary), newBoundary); + } catch (IndexOutOfBoundsException e) { + throw new IllegalArgumentException(e); + } + } + + private void validateOffset(int offset) { + if (offset < boundaries.get(0) || offset > boundaries.get(lastBoundary())) { + throw new IllegalArgumentException(); + } + } +} diff --git a/ojluni/src/test/java/text/CharacterIterator/CharacterIteratorTest.java b/ojluni/src/test/java/text/CharacterIterator/CharacterIteratorTest.java new file mode 100644 index 00000000000..9ad95dcc1fc --- /dev/null +++ b/ojluni/src/test/java/text/CharacterIterator/CharacterIteratorTest.java @@ -0,0 +1,290 @@ +/* + * Copyright (c) 1997, 2016, 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 + * @library /java/text/testlib + * @summary test for Character Iterator + */ + +/* + * + * + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved + * + * Portions copyright (c) 2007 Sun Microsystems, Inc. + * All Rights Reserved. + * + * The original version of this source code and documentation + * is copyrighted and owned by Taligent, Inc., a wholly-owned + * subsidiary of IBM. These materials are provided under terms + * of a License Agreement between Taligent and Sun. This technology + * is protected by multiple US and International patents. + * + * This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for NON-COMMERCIAL purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. Please refer to the file "copyright.html" + * for further important copyright and licensing information. + * + * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF + * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + */ + +package test.java.text.CharacterIterator; + +import java.text.*; + +import test.java.text.testlib.IntlTest; + +public class CharacterIteratorTest extends IntlTest { + public static void main(String[] args) throws Exception { + new CharacterIteratorTest().run(args); + } + + public CharacterIteratorTest() { + } + + public void TestConstructionAndEquality() { + String testText = "Now is the time for all good men to come to the aid of their country."; + String testText2 = "Don't bother using this string."; + + CharacterIterator test1 = new StringCharacterIterator(testText); + CharacterIterator test2 = new StringCharacterIterator(testText, 5); + CharacterIterator test3 = new StringCharacterIterator(testText, 2, 20, 5); + CharacterIterator test4 = new StringCharacterIterator(testText2); + CharacterIterator test5 = (CharacterIterator)test1.clone(); + + if (test1.equals(test2) || test1.equals(test3) || test1.equals(test4)) + errln("Construation or equals() failed: Two unequal iterators tested equal"); + + if (!test1.equals(test5)) + errln("clone() or equals() failed: Two clones tested unequal"); + + if (test1.hashCode() == test2.hashCode() || test1.hashCode() == test3.hashCode() + || test1.hashCode() == test4.hashCode()) + errln("hash() failed: different objects have same hash code"); + + if (test1.hashCode() != test5.hashCode()) + errln("hash() failed: identical objects have different hash codes"); + + test1.setIndex(5); + if (!test1.equals(test2) || test1.equals(test5)) + errln("setIndex() failed"); + } + + public void TestIteration() { + String text = "Now is the time for all good men to come to the aid of their country."; + + CharacterIterator iter = new StringCharacterIterator(text, 5); + + if (iter.current() != text.charAt(5)) + errln("Iterator didn't start out in the right place."); + + char c = iter.first(); + int i = 0; + + if (iter.getBeginIndex() != 0 || iter.getEndIndex() != text.length()) + errln("getBeginIndex() or getEndIndex() failed"); + + logln("Testing forward iteration..."); + do { + if (c == CharacterIterator.DONE && i != text.length()) + errln("Iterator reached end prematurely"); + else if (c != text.charAt(i)) + errln("Character mismatch at position " + i + ", iterator has " + c + + ", string has " + text.charAt(c)); + + if (iter.current() != c) + errln("current() isn't working right"); + if (iter.getIndex() != i) + errln("getIndex() isn't working right"); + + if (c != CharacterIterator.DONE) { + c = iter.next(); + i++; + } + } while (c != CharacterIterator.DONE); + + c = iter.last(); + i = text.length() - 1; + + logln("Testing backward iteration..."); + do { + if (c == CharacterIterator.DONE && i >= 0) + errln("Iterator reached end prematurely"); + else if (c != text.charAt(i)) + errln("Character mismatch at position " + i + ", iterator has " + c + + ", string has " + text.charAt(c)); + + if (iter.current() != c) + errln("current() isn't working right"); + if (iter.getIndex() != i) + errln("getIndex() isn't working right"); + + if (c != CharacterIterator.DONE) { + c = iter.previous(); + i--; + } + } while (c != CharacterIterator.DONE); + + iter = new StringCharacterIterator(text, 5, 15, 10); + if (iter.getBeginIndex() != 5 || iter.getEndIndex() != 15) + errln("creation of a restricted-range iterator failed"); + + if (iter.getIndex() != 10 || iter.current() != text.charAt(10)) + errln("starting the iterator in the middle didn't work"); + + c = iter.first(); + i = 5; + + logln("Testing forward iteration over a range..."); + do { + if (c == CharacterIterator.DONE && i != 15) + errln("Iterator reached end prematurely"); + else if (c != text.charAt(i)) + errln("Character mismatch at position " + i + ", iterator has " + c + + ", string has " + text.charAt(c)); + + if (iter.current() != c) + errln("current() isn't working right"); + if (iter.getIndex() != i) + errln("getIndex() isn't working right"); + + if (c != CharacterIterator.DONE) { + c = iter.next(); + i++; + } + } while (c != CharacterIterator.DONE); + + c = iter.last(); + i = 14; + + logln("Testing backward iteration over a range..."); + do { + if (c == CharacterIterator.DONE && i >= 5) + errln("Iterator reached end prematurely"); + else if (c != text.charAt(i)) + errln("Character mismatch at position " + i + ", iterator has " + c + + ", string has " + text.charAt(c)); + + if (iter.current() != c) + errln("current() isn't working right"); + if (iter.getIndex() != i) + errln("getIndex() isn't working right"); + + if (c != CharacterIterator.DONE) { + c = iter.previous(); + i--; + } + } while (c != CharacterIterator.DONE); + } + + /** + * @bug 4082050 4078261 4078255 + */ + public void TestPathologicalCases() { + String text = "This is only a test."; + +/* +This test is commented out until API-change approval for bug #4082050 goes through. + // test for bug #4082050 (don't get an error if begin == end, even though all + // operations on the iterator will cause exceptions) + // [I actually fixed this so that you CAN create an iterator with begin == end, + // but all operations on it return DONE.] + CharacterIterator iter = new StringCharacterIterator(text, 5, 5, 5); + if (iter.first() != CharacterIterator.DONE + || iter.next() != CharacterIterator.DONE + || iter.last() != CharacterIterator.DONE + || iter.previous() != CharacterIterator.DONE + || iter.current() != CharacterIterator.DONE + || iter.getIndex() != 5) + errln("Got something other than DONE when performing operations on an empty StringCharacterIterator"); +*/ +CharacterIterator iter = null; + + // if we try to construct a StringCharacterIterator with an endIndex that's off + // the end of the String under iterator, we're supposed to get an + // IllegalArgumentException + boolean gotException = false; + try { + iter = new StringCharacterIterator(text, 5, 100, 5); + } + catch (IllegalArgumentException e) { + gotException = true; + } + if (!gotException) + errln("StringCharacterIterator didn't throw an exception when given an invalid substring range."); + + // test for bug #4078255 (getting wrong value from next() when we're at the end + // of the string) + iter = new StringCharacterIterator(text); + int expectedIndex = iter.getEndIndex(); + int actualIndex; + + iter.last(); + actualIndex = iter.getIndex(); + if (actualIndex != expectedIndex - 1) + errln("last() failed: expected " + (expectedIndex - 1) + ", got " + actualIndex); + + iter.next(); + actualIndex = iter.getIndex(); + if (actualIndex != expectedIndex) + errln("next() after last() failed: expected " + expectedIndex + ", got " + actualIndex); + + iter.next(); + actualIndex = iter.getIndex(); + if (actualIndex != expectedIndex) + errln("second next() after last() failed: expected " + expectedIndex + ", got " + actualIndex); + } + + /* + * @bug 4123771 4051073 + * #4123771 is actually a duplicate of bug #4051073, which was fixed some time ago, but + * no one ever added a regression test for it. + */ + public void TestBug4123771() { + String text = "Some string for testing"; + StringCharacterIterator iter = new StringCharacterIterator(text); + int index = iter.getEndIndex(); + try { + char c = iter.setIndex(index); + } + catch (Exception e) { + System.out.println("method setIndex(int position) throws unexpected exception " + e); + System.out.println(" position: " + index); + System.out.println(" getEndIndex(): " + iter.getEndIndex()); + System.out.println(" text.length(): " + text.length()); + errln(""); // re-throw the exception through our test framework + } + } +} diff --git a/ojluni/src/test/java/text/Collator/Bug5047314.java b/ojluni/src/test/java/text/Collator/Bug5047314.java new file mode 100644 index 00000000000..ddd2d043dc5 --- /dev/null +++ b/ojluni/src/test/java/text/Collator/Bug5047314.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2009, 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 5047314 + * @summary verify that compare() and getCollationKey() don't go into an infinite loop for unfinished Thai/Lao text. + * @run main/timeout=60 Bug5047314 + */ +package test.java.text.Collator; + +import java.text.Collator; +import java.util.Locale; + +public class Bug5047314 { + + private static Collator colLao = Collator.getInstance(new Locale("lo")); + private static Collator colThai = Collator.getInstance(new Locale("th")); + + private static String[] textLao = { + "\u0ec0", "\u0ec1", "\u0ec2", "\u0ec3", "\u0ec4" + }; + private static String[] textThai = { + "\u0e40", "\u0e41", "\u0e42", "\u0e43", "\u0e44" + }; + + public static void main(String[] args) { + testLao1(); + testLao2(); + testThai1(); + testThai2(); + } + + private static void testLao1() { + System.out.print("Test(Lao 1) .... "); + for (int i = 0; i < textLao.length; i++) { + colLao.compare(textLao[i], textLao[i]); + } + System.out.println("Passed."); + } + + private static void testLao2() { + System.out.print("Test(Lao 2) .... "); + for (int i = 0; i < textLao.length; i++) { + colLao.compare(textLao[i], textLao[i]); + } + System.out.println("Passed."); + } + + private static void testThai1() { + System.out.print("Test(Thai 1) .... "); + for (int i = 0; i < textThai.length; i++) { + colThai.compare(textThai[i], textThai[i]); + } + System.out.println("Passed."); + } + + private static void testThai2() { + System.out.print("Test(Thai 2) .... "); + for (int i = 0; i < textThai.length; i++) { + colThai.getCollationKey(textThai[i]); + } + System.out.println("Passed."); + } + +} diff --git a/ojluni/src/test/java/text/Collator/Bug7200119.java b/ojluni/src/test/java/text/Collator/Bug7200119.java new file mode 100644 index 00000000000..d2117376be0 --- /dev/null +++ b/ojluni/src/test/java/text/Collator/Bug7200119.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012, 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 7200119 + * @summary verify that getAvailableLocales() contains Locale.US + */ +package test.java.text.Collator; + +import java.text.*; +import java.util.*; + +public class Bug7200119 { + public static void main(String[] args) { + List<Locale> avail = Arrays.asList(Collator.getAvailableLocales()); + + if (!avail.contains(Locale.US)) { + throw new RuntimeException("Failed."); + } + } +} diff --git a/ojluni/src/test/java/text/Collator/CollatorTest.java b/ojluni/src/test/java/text/Collator/CollatorTest.java new file mode 100644 index 00000000000..a183d8f1874 --- /dev/null +++ b/ojluni/src/test/java/text/Collator/CollatorTest.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1998, 2016, 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. + */ + +package test.java.text.Collator; + +import java.lang.reflect.*; +import java.util.Hashtable; +import java.util.Enumeration; +import java.util.Vector; +import java.io.*; +import java.text.*; + +import test.java.text.testlib.IntlTest; + +/** + * CollatorTest is a base class for tests that can be run conveniently from + * the command line as well as under the Java test harness. + * <p> + * Sub-classes implement a set of methods named Test<something>. Each + * of these methods performs some test. Test methods should indicate + * errors by calling either err or errln. This will increment the + * errorCount field and may optionally print a message to the log. + * Debugging information may also be added to the log via the log + * and logln methods. These methods will add their arguments to the + * log only if the test is being run in verbose mode. + */ +public abstract class CollatorTest extends IntlTest { + + //------------------------------------------------------------------------ + // These methods are utilities specific to the Collation tests.. + //------------------------------------------------------------------------ + + protected void assertEqual(CollationElementIterator i1, CollationElementIterator i2) { + int c1, c2, count = 0; + do { + c1 = i1.next(); + c2 = i2.next(); + if (c1 != c2) { + errln(" " + count + ": " + c1 + " != " + c2); + break; + } + count++; + } while (c1 != CollationElementIterator.NULLORDER); + } + + // Replace nonprintable characters with unicode escapes + static protected String prettify(String str) { + StringBuffer result = new StringBuffer(); + + String zero = "0000"; + + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + if (ch < 0x09 || (ch > 0x0A && ch < 0x20)|| (ch > 0x7E && ch < 0xA0) || ch > 0x100) { + String hex = Integer.toString((int)ch,16); + + result.append("\\u" + zero.substring(0, 4 - hex.length()) + hex); + } else { + result.append(ch); + } + } + return result.toString(); + } + + // Produce a printable representation of a CollationKey + static protected String prettify(CollationKey key) { + StringBuffer result = new StringBuffer(); + byte[] bytes = key.toByteArray(); + + for (int i = 0; i < bytes.length; i += 2) { + int val = (bytes[i] << 8) + bytes[i+1]; + result.append(Integer.toString(val, 16) + " "); + } + return result.toString(); + } + + //------------------------------------------------------------------------ + // Everything below here is boilerplate code that makes it possible + // to add a new test by simply adding a function to an existing class + //------------------------------------------------------------------------ + + protected void doTest(Collator col, int strength, + String[] source, String[] target, int[] result) { + if (source.length != target.length) { + errln("Data size mismatch: source = " + + source.length + ", target = " + target.length); + + return; // Return if "-nothrow" is specified. + } + if (source.length != result.length) { + errln("Data size mismatch: source & target = " + + source.length + ", result = " + result.length); + + return; // Return if "-nothrow" is specified. + } + + col.setStrength(strength); + for (int i = 0; i < source.length ; i++) { + doTest(col, source[i], target[i], result[i]); + } + } + + protected void doTest(Collator col, + String source, String target, int result) { + char relation = '='; + if (result <= -1) { + relation = '<'; + } else if (result >= 1) { + relation = '>'; + } + + int compareResult = col.compare(source, target); + CollationKey sortKey1 = col.getCollationKey(source); + CollationKey sortKey2 = col.getCollationKey(target); + int keyResult = sortKey1.compareTo(sortKey2); + if (compareResult != keyResult) { + errln("Compare and Collation Key results are different! Source = " + + source + " Target = " + target); + } + if (keyResult != result) { + errln("Collation Test failed! Source = " + source + " Target = " + + target + " result should be " + relation); + } + } +} diff --git a/ojluni/src/test/java/text/Collator/MonkeyTest.java b/ojluni/src/test/java/text/Collator/MonkeyTest.java new file mode 100644 index 00000000000..7a4b98d1809 --- /dev/null +++ b/ojluni/src/test/java/text/Collator/MonkeyTest.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1997, 2016, 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 + * @library /java/text/testlib + * @summary test Collation, Monkey style + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +package test.java.text.Collator; + +import java.io.IOException; +import java.util.Random; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.Locale; +import java.text.Collator; +import java.text.RuleBasedCollator; +import java.text.CollationKey; + +public class MonkeyTest extends CollatorTest +{ + public static void main(String[] args) throws Exception { + new MonkeyTest().run(args); + } + + public void report(String s, String t, int result, int revResult) + { + if (result == -1) + { + if (revResult != 1) + errln(" --> Test Failed"); + } + else if (result == 1) + { + if (revResult != -1) + errln(" --> Test Failed"); + } + else if (result == 0) + { + if (revResult != 0) + errln(" --> Test Failed"); + } + } + + public void TestCollationKey() + { + String source = "-abcdefghijklmnopqrstuvwxyz#&^$@"; + Random r = new Random(3); + int s = checkValue(r.nextInt() % source.length()); + int t = checkValue(r.nextInt() % source.length()); + int slen = checkValue((r.nextInt() - source.length()) % source.length()); + int tlen = checkValue((r.nextInt() - source.length()) % source.length()); + String subs = source.substring((s > slen ? slen : s), (s >= slen ? s : slen)); + String subt = source.substring((t > tlen ? tlen : t), (t >= tlen ? t : tlen)); + myCollator.setStrength(Collator.TERTIARY); + CollationKey CollationKey1 = myCollator.getCollationKey(subs); + CollationKey CollationKey2 = myCollator.getCollationKey(subt); + int result = CollationKey1.compareTo(CollationKey2); // Tertiary + int revResult = CollationKey2.compareTo(CollationKey1); // Tertiary + report(("CollationKey(" + subs + ")"), ("CollationKey(" + subt + ")"), result, revResult); + myCollator.setStrength(Collator.SECONDARY); + CollationKey1 = myCollator.getCollationKey(subs); + CollationKey2 = myCollator.getCollationKey(subt); + result = CollationKey1.compareTo(CollationKey2); // Secondary + revResult = CollationKey2.compareTo(CollationKey1); // Secondary + report(("CollationKey(" + subs + ")") , ("CollationKey(" + subt + ")"), result, revResult); + myCollator.setStrength(Collator.PRIMARY); + CollationKey1 = myCollator.getCollationKey(subs); + CollationKey2 = myCollator.getCollationKey(subt); + result = CollationKey1.compareTo(CollationKey2); // Primary + revResult = CollationKey2.compareTo(CollationKey1); // Primary + report(("CollationKey(" + subs + ")"), ("CollationKey(" + subt + ")"), result, revResult); + String addOne = subs + "\uE000"; + CollationKey1 = myCollator.getCollationKey(subs); + CollationKey2 = myCollator.getCollationKey(addOne); + result = CollationKey1.compareTo(CollationKey2); + if (result != -1) + errln("CollationKey(" + subs + ")" + ".LT." + "CollationKey(" + addOne + ") Failed."); + result = CollationKey2.compareTo(CollationKey1); + if (result != 1) + errln("CollationKey(" + addOne + ")" + ".GT." + "CollationKey(" + subs + ") Failed."); + } + private static int checkValue(int value) + { + value *= (value > 0) ? 1 : -1; + return value; + } + public void TestCompare() + { + String source = "-abcdefghijklmnopqrstuvwxyz#&^$@"; + Random r = new Random(3); + int s = checkValue(r.nextInt() % source.length()); + int t = checkValue(r.nextInt() % source.length()); + int slen = checkValue((r.nextInt() - source.length()) % source.length()); + int tlen = checkValue((r.nextInt() - source.length()) % source.length()); + String subs = source.substring((s > slen ? slen : s), (s >= slen ? s : slen)); + String subt = source.substring((t > tlen ? tlen : t), (t >= tlen ? t : tlen)); + myCollator.setStrength(Collator.TERTIARY); + int result = myCollator.compare(subs, subt); // Tertiary + int revResult = myCollator.compare(subt, subs); // Tertiary + report(subs, subt, result, revResult); + myCollator.setStrength(Collator.SECONDARY); + result = myCollator.compare(subs, subt); // Secondary + revResult = myCollator.compare(subt, subs); // Secondary + report(subs, subt, result, revResult); + myCollator.setStrength(Collator.PRIMARY); + result = myCollator.compare(subs, subt); // Primary + revResult = myCollator.compare(subt, subs); // Primary + report(subs, subt, result, revResult); + String addOne = subs + "\uE000"; + result = myCollator.compare(subs, addOne); + if (result != -1) + errln("Test : " + subs + " .LT. " + addOne + " Failed."); + result = myCollator.compare(addOne, subs); + if (result != 1) + errln("Test : " + addOne + " .GE. " + subs + " Failed."); + } + private static Collator myCollator = Collator.getInstance(); +} diff --git a/ojluni/src/test/java/text/Format/ChoiceFormat/Bug4387255.java b/ojluni/src/test/java/text/Format/ChoiceFormat/Bug4387255.java new file mode 100644 index 00000000000..233d7b7616d --- /dev/null +++ b/ojluni/src/test/java/text/Format/ChoiceFormat/Bug4387255.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1997, 2016, 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 4387255 + * @summary Verifies that ChoiceFormat can handle large numbers of choices + */ + +package test.java.text.Format.ChoiceFormat; + +import java.text.ChoiceFormat; + +public class Bug4387255 { + + private static final double[] doubles = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35}; + + private static final String[] strings = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", + "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", + "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", + "U", "V", "W", "X", "Y", "Z"}; + + private static final String pattern = + "0#0|1#1|2#2|3#3|4#4|5#5|6#6|7#7|8#8|9#9" + + "|10#A|11#B|12#C|13#D|14#E|15#F|16#G|17#H|18#I|19#J" + + "|20#K|21#L|22#M|23#N|24#O|25#P|26#Q|27#R|28#S|29#T" + + "|30#U|31#V|32#W|33#X|34#Y|35#Z"; + + public static void main(String[] args) throws Exception { + ChoiceFormat choiceFormat1 = new ChoiceFormat(doubles, strings); + ChoiceFormat choiceFormat2 = new ChoiceFormat(pattern); + if (!choiceFormat1.equals(choiceFormat2)) { + System.out.println("choiceFormat1: " + choiceFormat1.toPattern()); + System.out.println("choiceFormat2: " + choiceFormat2.toPattern()); + throw new RuntimeException(); + } + + for (int i = 0; i < doubles.length; i++) { + String result = choiceFormat2.format(doubles[i]); + if (!result.equals(strings[i])) { + throw new RuntimeException("Wrong format result - expected " + + strings[i] + ", got " + result); + } + } + } +} diff --git a/ojluni/src/test/java/text/Format/ChoiceFormat/Bug8001209.java b/ojluni/src/test/java/text/Format/ChoiceFormat/Bug8001209.java new file mode 100644 index 00000000000..cb8a2879581 --- /dev/null +++ b/ojluni/src/test/java/text/Format/ChoiceFormat/Bug8001209.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2012, 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 8001209 + * @summary Confirm that the values set by setChoices() are not mutable. + */ +package test.java.text.Format.ChoiceFormat; + +import java.text.*; + +public class Bug8001209 { + + public static void main(String[] args) throws Exception { + boolean err = false; + + // Borrow an example in API doc + double[] limits = {1,2,3,4,5,6,7}; + String[] dayOfWeekNames = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; + ChoiceFormat form = new ChoiceFormat(limits, dayOfWeekNames); + ParsePosition status = new ParsePosition(0); + + StringBuilder before = new StringBuilder(); + for (double i = 1.0; i <= 7.0; ++i) { + status.setIndex(0); + String s = form.format(i); + before.append(" "); + before.append(s); + before.append(form.parse(form.format(i),status)); + } + String original = before.toString(); + + double[] newLimits = form.getLimits(); + String[] newFormats = (String[])form.getFormats(); + newFormats[6] = "Doyoubi"; + StringBuilder after = new StringBuilder(); + for (double i = 1.0; i <= 7.0; ++i) { + status.setIndex(0); + String s = form.format(i); + after.append(" "); + after.append(s); + after.append(form.parse(form.format(i),status)); + } + if (!original.equals(after.toString())) { + err = true; + System.err.println(" Expected:" + before + + "\n Got: " + after); + } + + dayOfWeekNames[6] = "Saturday"; + after = new StringBuilder(); + for (double i = 1.0; i <= 7.0; ++i) { + status.setIndex(0); + String s = form.format(i); + after.append(" "); + after.append(s); + after.append(form.parse(form.format(i),status)); + } + if (!original.equals(after.toString())) { + err = true; + System.err.println(" Expected:" + before + + "\n Got: " + after); + } + + if (err) { + throw new RuntimeException("Failed."); + } else { + System.out.println("Passed."); + } + } +} diff --git a/ojluni/src/test/java/text/Format/DateFormat/SimpleDateFormatPatternTest.java b/ojluni/src/test/java/text/Format/DateFormat/SimpleDateFormatPatternTest.java new file mode 100644 index 00000000000..8acac13d3f5 --- /dev/null +++ b/ojluni/src/test/java/text/Format/DateFormat/SimpleDateFormatPatternTest.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2019, 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 4326988 6990146 8231213 + * @summary test SimpleDateFormat, check its pattern in the constructor + * @run testng/othervm SimpleDateFormatPatternTest + */ +package test.java.text.Format.DateFormat; + +import java.lang.IllegalArgumentException; +import java.text.DateFormat; +import java.text.DateFormatSymbols; +import java.text.SimpleDateFormat; +import java.util.Locale; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class SimpleDateFormatPatternTest { + private static String[] validPat = { + "yyyy-MM-dd h.mm.ss.a z", + "yyyy'M'd' ahh'mm'ss' z", + "dd MMMM yyyy hh:mm:ss", + "d MMM yy HH:mm:ss", + "dd/MM/yyyy HH:mm:ss", + "d' / 'MMMM' / 'yyyy HH:mm:ss z", + "d.M.yyyy H:mm:ss", + "d' de 'MMMM' de 'yyyy H'h'm'min's's' z", + "dd. MMMM yyyy HH:mm:ss z", + "d-M-yyyy H:mm:ss", + "EEEE''d MMMM G yyyy, H' 'm' 'ss' '", + "dd.MMM.yyyy HH:mm:ss", + "yy-MM-dd h:mm:ss.a", + "d' de 'MMMM' de 'yyyy hh:mm:ss a z", + "EEEE d MMMM yyyy H' h 'mm' min 'ss' s 'z", + "d MMMM yyyy H:mm:ss", + "d/MM/yyyy hh:mm:ss a", + "EEEE, d, MMMM yyyy HH:mm:ss z", + "EEEE, d. MMMM yyyy HH.mm.' h' z", + "EEEE, d' / 'MMMM' / 'yyyy HH:mm:ss z", + "d/MM/yyyy HH:mm:ss", + "d MMMM yyyy H:mm:ss z", + "MMMM d, yyyy h:mm:ss a z", + "yyyy. MMMM d. H:mm:ss z", + "d' de 'MMMM' de 'yyyy H:mm:ss z", + "EEEE, MMMM d, yyyy h:mm:ss a z", + "d/M/yyyy H:mm:ss", + "d-MMM-yy HH:mm:ss", + "EEEE d' de 'MMMM' de 'yyyy hh:mm:ss a z", + "yyyy'M'd' ahh'mm'ss'", + "yyyy'MM'dd' EEEE ahh'mm'ss'", + "EEEE, d MMMM yyyy HH:mm:ss z", + + //6990146: 'Y' for year; 'X' for time zone; 'u' for day number of the week + "d/M/YYYY H:mm:ss", + "d-MMM-YY HH:mm:ss", + "EEEE d' de 'MMMM' de 'YYYY hh:mm:ss a X", + "YYYY M d ahh:mm:ss", + "YYYY MM dd EEEE u ahh/mm/ss", + "EEEE, u, d MMMM YYYY HH:mm:ss X", + "YYYY M d Z ahh mm ss", + "YYYY-MM-dd EEEE u ahh-mm-ss", + + //*added for sr-Latn* + "EEEE, dd. MMMM y. HH.mm.ss zzzz", + "dd. MMMM y. HH.mm.ss z", + "dd.MM.y. HH.mm.ss", + "d.M.yy. HH.mm" + }; + + private static String[] invalidPat = { + "yyyy'M'd' ahh:mm:ss", + "EEEe d MM MM yyyy HH' h 'mm zzzZ", + "d MMMM\\ yyyy, H' 'm' 'g", + "EEEE d' @# MMMMde 'yyys HHH'mm z", + "yyyy'MMe 2 #dd' EEEEahh'mm'ss' z,z", + "yyyy.M.d H;mm.ses", + "EEEe, d MMMM yyyy h:mm:ss a z", + "EEEE, MMMM d, 'y y y y h:mm:ss 'o''clock' a z", + "dd MMMM yyyy 0HHcl:mm:ss z", + "d.M_M_y.yy1yy HextH:mm|45:", + "d,D MMMTTTTTTTTTKM yy|+yy HH:m m:ss z", + "d-MDtM M-yy H:mm:ss", + "yyyy/M///m/nM/d Dd H:m$m:s s", + "EEEE, dd. MMMM yyyy HH:m'''m' Uhr 'z", + //6990146 + "EEEE d' de 'MMMM' de 'YYYY hh:mm:ss a x", + "EEEE, U, d MMMM YYYY HH:mm:ss Z" + }; + + private static Locale[] locales = DateFormat.getAvailableLocales(); + private static Object[][] dfAllLocalesObj = createAllLocales(); + private static Object[][] invalidPatObj = createPatternObj(invalidPat); + private static Object[][] validPatObj = createPatternObj(validPat); + + private static Object[][] createAllLocales() { + Object[][] objArray = new Object[locales.length][]; + for (int i = 0; i < locales.length; i++) { + objArray[i] = new Object[1]; + objArray[i][0] = locales[i]; + } + return objArray; + } + + private static Object[][] createPatternObj(String[] pattern){ + Object[][] objArray = new Object[locales.length * pattern.length][]; + int k = 0; + for (int i = 0; i < locales.length; i++) { + for (int j = 0; j < pattern.length; j++) { + objArray[k] = new Object[2]; + objArray[k][0] = pattern[j]; + objArray[k][1] = locales[i]; + k = k + 1; + } + } + return objArray; + } + + @DataProvider(name = "dfAllLocalesObj") + Object[][] dfAllLocalesObj() { + return dfAllLocalesObj; + } + + @DataProvider(name = "invalidPatternObj") + Object[][] invalidPatternObj() { + return invalidPatObj; + } + + @DataProvider(name = "validPatternObj") + Object[][] validPatternObj() { + return validPatObj; + } + + //check Constructors for invalid pattern + @Test(dataProvider = "invalidPatternObj", + expectedExceptions = IllegalArgumentException.class) + public void testIllegalArgumentException1(String pattern, Locale loc) + throws IllegalArgumentException { + Locale.setDefault(loc); + new SimpleDateFormat(pattern); + } + + @Test(dataProvider = "invalidPatternObj", + expectedExceptions = IllegalArgumentException.class) + public void testIllegalArgumentException2(String pattern, Locale loc) + throws IllegalArgumentException { + Locale.setDefault(loc); + new SimpleDateFormat(pattern, new DateFormatSymbols()); + } + + @Test(dataProvider = "invalidPatternObj", + expectedExceptions = IllegalArgumentException.class) + public void testIllegalArgumentException3 (String pattern, Locale loc) + throws IllegalArgumentException { + Locale.setDefault(loc); + new SimpleDateFormat(pattern, Locale.getDefault()); + } + + @Test(dataProvider = "invalidPatternObj", + expectedExceptions = IllegalArgumentException.class) + public void testIllegalArgumentException4(String pattern, Locale loc) + throws IllegalArgumentException { + Locale.setDefault(loc); + new SimpleDateFormat().applyPattern(pattern); + } + + //check Constructors for null pattern + @Test(dataProvider = "dfAllLocalesObj", + expectedExceptions = NullPointerException.class) + public void testNullPointerException1(Locale loc) + throws NullPointerException { + Locale.setDefault(loc); + new SimpleDateFormat(null); + } + + @Test(dataProvider = "dfAllLocalesObj", + expectedExceptions = NullPointerException.class) + public void testNullPointerException2(Locale loc) + throws NullPointerException { + Locale.setDefault(loc); + new SimpleDateFormat(null, new DateFormatSymbols()); + } + + @Test(dataProvider = "dfAllLocalesObj", + expectedExceptions = NullPointerException.class) + public void testNullPointerException3(Locale loc) + throws NullPointerException { + Locale.setDefault(loc); + new SimpleDateFormat(null, Locale.getDefault()); + } + + @Test(dataProvider = "dfAllLocalesObj", + expectedExceptions = NullPointerException.class) + public void testNullPointerException4(Locale loc) + throws NullPointerException { + Locale.setDefault(loc); + new SimpleDateFormat().applyPattern(null); + } + + @Test(dataProvider = "validPatternObj") + //check Constructors for valid pattern + public void testValidPattern(String pattern, Locale loc) { + Locale.setDefault(loc); + new SimpleDateFormat(pattern); + new SimpleDateFormat(pattern, new DateFormatSymbols()); + new SimpleDateFormat(pattern, Locale.getDefault()); + new SimpleDateFormat().applyPattern(pattern); + } +} diff --git a/ojluni/src/test/java/text/Format/DecimalFormat/Bug8165466.java b/ojluni/src/test/java/text/Format/DecimalFormat/Bug8165466.java new file mode 100644 index 00000000000..073b88cc62c --- /dev/null +++ b/ojluni/src/test/java/text/Format/DecimalFormat/Bug8165466.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2016, 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 8165466 + * @summary Checks the subsequent function calls of the DecimalFormat.format() + * method in which the minimumFractionDigit is set to 0 and one of + * the format() call include formatting of the number with zero + * fraction value e.g. 0.00, 9.00 + */ + +package test.java.text.Format.DecimalFormat; + +import java.text.DecimalFormat; +import java.util.Locale; + +public class Bug8165466 { + + public static void main(String[] args) { + DecimalFormat nf = (DecimalFormat) DecimalFormat + .getPercentInstance(Locale.US); + nf.setMaximumFractionDigits(3); + nf.setMinimumFractionDigits(0); + nf.setMultiplier(1); + + double d = 0.005678; + String result = nf.format(d); + if (!result.equals("0.006%")) { + throw new RuntimeException("[Failed while formatting the double" + + " value: " + d + " Expected: 0.006%, Found: " + result + + "]"); + } + + d = 0.00; + result = nf.format(d); + if (!result.equals("0%")) { + throw new RuntimeException("[Failed while formatting the double" + + " value: " + d + " Expected: 0%, Found: " + result + + "]"); + } + + d = 0.005678; + result = nf.format(d); + if (!result.equals("0.006%")) { + throw new RuntimeException("[Failed while formatting the double" + + " value: " + d + " Expected: 0.006%, Found: " + result + + "]"); + } + + //checking with the non zero value + d = 0.005678; + result = nf.format(d); + if (!result.equals("0.006%")) { + throw new RuntimeException("[Failed while formatting the double" + + " value: " + d + " Expected: 0.006%, Found: " + result + + "]"); + } + + d = 9.00; + result = nf.format(d); + if (!result.equals("9%")) { + throw new RuntimeException("[Failed while formatting the double" + + " value: " + d + " Expected: 9%, Found: " + result + + "]"); + } + + d = 0.005678; + result = nf.format(d); + if (!result.equals("0.006%")) { + throw new RuntimeException("[Failed while formatting the double" + + " value: " + d + " Expected: 0.006%, Found: " + result + + "]"); + } + } + +} + diff --git a/ojluni/src/test/java/text/Format/DecimalFormat/GoldenFormattedValues.java b/ojluni/src/test/java/text/Format/DecimalFormat/GoldenFormattedValues.java new file mode 100644 index 00000000000..5690819cfbe --- /dev/null +++ b/ojluni/src/test/java/text/Format/DecimalFormat/GoldenFormattedValues.java @@ -0,0 +1,870 @@ +/* + * Copyright (c) 2012, 2015, 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. + */ + +package test.java.text.Format.DecimalFormat; + +/* This is a machine generated file - Please DO NOT EDIT ! + * Change RoundingAndPropertyTest instead, + * and run with "-gengold" argument to regenerate (without copyright header). + */ + +/* This file contains the set of result Strings expected from calling inside + * RoundingAndPropertyTest the method NumberFormat.format() upon the set of + * double values provided in GoldenDoubleValues.java. It contains three arrays, + * each containing arrays of unicode values representing the expected string + * result when calling format() on the corresponding (i.e. same index) double + * value found in GoldenDoubleValues arrays : + * - DecimalDigitsLocalizedFormattedValues corresponds to DecimalLocalizationValues, + * when using FullLocalizationTestLocale to format. + * - DecimalGoldenFormattedValues corresponds to DecimalGoldenValues, when used + * in the decimal pattern case together with TestLocale. + * - CurrencyGoldenFormattedValues corresponds to CurrencyGoldenValues. when used + * in the currency pattern case together with TestLocale. + * Please see documentation in RoundingAndPropertyTest.java for more details. + * + * This file generated by running RoundingAndPropertyTest with "-gengold" argument. + */ + +class GoldenFormattedValues { + + // The formatted values below were generated from golden values + // listed in GoldenDoubleValues.java, using the following jvm version : + // Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 1.9.0-internal-fastdebug + // locale for golden double values : en_US + // locale for testing digit localization : hi_IN + + // The array of int[] unicode values storing the expected results + // when experiencing full localization of digits on DecimalLocalizationValues. + static int[][] DecimalDigitsLocalizedFormattedValues = { + { 49, 46, 49, 50, 51 }, + { 49, 50, 46, 49, 50, 51 }, + { 49, 50, 51, 46, 49, 50, 51 }, + { 49, 44, 50, 51, 52, 46, 49, 50, 51 }, + { 49, 50, 44, 51, 52, 53, 46, 49, 50, 51 }, + { 49, 50, 51, 44, 52, 53, 54, 46, 49, 50, 51 }, + { 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 49, 50, 51 }, + { 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 49, 50, 51 }, + { 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 49, 50, 51 }, + { 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 49, 50, 51 }, + { 49, 44, 50, 51, 52 }, + { 49, 44, 50, 51, 52, 46, 57 }, + { 49, 44, 50, 51, 52, 46, 57, 57 }, + { 49, 44, 50, 51, 52, 46, 57, 57, 57 }, + }; + + // The array of int[] unicode values storing the expected results + // when calling Decimal.format(double) on the decimal GoldenDoubleValues. + static int[][] DecimalGoldenFormattedValues = { + { 48 }, + { 45, 48 }, + { 48 }, + { 48 }, + { 45, 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 54, 46, 50, 51, 51 }, + { 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 54, 46, 50, 51, 52 }, + { 45, 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 56 }, + { 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 56 }, + { 45, 49, 44, 57, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 }, + { 50, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 78, 97, 78 }, + { 8734 }, + { 45, 8734 }, + { 49, 55, 57, 44, 55, 54, 57, 44, 51, 49, 51, 44, 52, 56, 54, 44, 50, 51, 49, 44, 53, 55, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 45, 57, 44, 56, 55, 54, 44, 53, 52, 51, 44, 50, 49, 48, 46, 57, 56, 56 }, + { 57, 44, 56, 55, 54, 44, 53, 52, 51, 44, 50, 49, 48, 46, 57, 56, 56 }, + { 45, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 44, 48, 49, 50, 44, 51, 52, 53, 44, 54, 55, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 44, 48, 49, 50, 44, 51, 52, 53, 44, 54, 55, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 49, 46, 49, 50, 51 }, + { 49, 50, 46, 49, 50, 51 }, + { 49, 50, 51, 46, 49, 50, 51 }, + { 49, 44, 50, 51, 52, 46, 49, 50, 51 }, + { 49, 50, 44, 51, 52, 53, 46, 49, 50, 51 }, + { 49, 50, 51, 44, 52, 53, 54, 46, 49, 50, 51 }, + { 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 49, 50, 51 }, + { 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 49, 50, 51 }, + { 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 49, 50, 51 }, + { 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 49, 50, 51 }, + { 45, 49, 46, 49, 50, 51 }, + { 45, 49, 50, 46, 49, 50, 51 }, + { 45, 49, 50, 51, 46, 49, 50, 51 }, + { 45, 49, 44, 50, 51, 52, 46, 49, 50, 51 }, + { 45, 49, 50, 44, 51, 52, 53, 46, 49, 50, 51 }, + { 45, 49, 50, 51, 44, 52, 53, 54, 46, 49, 50, 51 }, + { 45, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 49, 50, 51 }, + { 45, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 49, 50, 51 }, + { 45, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 49, 50, 51 }, + { 45, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 49, 50, 51 }, + { 48, 46, 49 }, + { 48, 46, 49, 50 }, + { 48, 46, 49, 50, 51 }, + { 48, 46, 49, 50, 51 }, + { 49, 48, 46, 49 }, + { 49, 48, 46, 49, 50 }, + { 49, 48, 46, 49, 50, 51 }, + { 49, 48, 46, 49, 50, 51 }, + { 49, 48, 48, 46, 49 }, + { 49, 48, 48, 46, 49, 50 }, + { 49, 48, 48, 46, 49, 50, 51 }, + { 49, 48, 48, 46, 49, 50, 51 }, + { 49, 44, 48, 48, 48, 46, 49 }, + { 49, 44, 48, 48, 48, 46, 49, 50 }, + { 49, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 49, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 49, 48, 44, 48, 48, 48, 46, 49 }, + { 49, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 49, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 49, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 49, 48, 48, 44, 48, 48, 48, 46, 49 }, + { 49, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 49, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 49, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 }, + { 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 }, + { 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 }, + { 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 }, + { 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 45, 48, 46, 49 }, + { 45, 48, 46, 49, 50 }, + { 45, 48, 46, 49, 50, 51 }, + { 45, 48, 46, 49, 50, 51 }, + { 45, 49, 48, 46, 49 }, + { 45, 49, 48, 46, 49, 50 }, + { 45, 49, 48, 46, 49, 50, 51 }, + { 45, 49, 48, 46, 49, 50, 51 }, + { 45, 49, 48, 48, 46, 49 }, + { 45, 49, 48, 48, 46, 49, 50 }, + { 45, 49, 48, 48, 46, 49, 50, 51 }, + { 45, 49, 48, 48, 46, 49, 50, 51 }, + { 45, 49, 44, 48, 48, 48, 46, 49 }, + { 45, 49, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 49, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 45, 49, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 45, 49, 48, 44, 48, 48, 48, 46, 49 }, + { 45, 49, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 49, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 45, 49, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 45, 49, 48, 48, 44, 48, 48, 48, 46, 49 }, + { 45, 49, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 49, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 45, 49, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 }, + { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 45, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 }, + { 45, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 45, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 45, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 }, + { 45, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 45, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 }, + { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 }, + { 49, 46, 57, 57, 57 }, + { 49, 50, 46, 57, 57, 57 }, + { 49, 50, 51, 46, 57, 57, 57 }, + { 49, 44, 50, 51, 52, 46, 57, 57, 57 }, + { 49, 50, 44, 51, 52, 53, 46, 57, 57, 57 }, + { 49, 50, 51, 44, 52, 53, 54, 46, 57, 57, 57 }, + { 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 57, 57, 57 }, + { 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 57, 57, 57 }, + { 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 57, 57, 57 }, + { 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 57, 57, 57 }, + { 50 }, + { 49, 51 }, + { 49, 50, 52 }, + { 49, 44, 50, 51, 53 }, + { 49, 50, 44, 51, 52, 54 }, + { 49, 50, 51, 44, 52, 53, 55 }, + { 49, 44, 50, 51, 52, 44, 53, 54, 56 }, + { 49, 50, 44, 51, 52, 53, 44, 54, 55, 57 }, + { 49, 50, 51, 44, 52, 53, 54, 44, 55, 57, 48 }, + { 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 49 }, + { 45, 49, 46, 57, 57, 57 }, + { 45, 49, 50, 46, 57, 57, 57 }, + { 45, 49, 50, 51, 46, 57, 57, 57 }, + { 45, 49, 44, 50, 51, 52, 46, 57, 57, 57 }, + { 45, 49, 50, 44, 51, 52, 53, 46, 57, 57, 57 }, + { 45, 49, 50, 51, 44, 52, 53, 54, 46, 57, 57, 57 }, + { 45, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 57, 57, 57 }, + { 45, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 57, 57, 57 }, + { 45, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 57, 57, 57 }, + { 45, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 57, 57, 57 }, + { 45, 50 }, + { 45, 49, 51 }, + { 45, 49, 50, 52 }, + { 45, 49, 44, 50, 51, 53 }, + { 45, 49, 50, 44, 51, 52, 54 }, + { 45, 49, 50, 51, 44, 52, 53, 55 }, + { 45, 49, 44, 50, 51, 52, 44, 53, 54, 56 }, + { 45, 49, 50, 44, 51, 52, 53, 44, 54, 55, 57 }, + { 45, 49, 50, 51, 44, 52, 53, 54, 44, 55, 57, 48 }, + { 45, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 49 }, + { 49, 49, 48 }, + { 49, 44, 49, 48, 48 }, + { 49, 49, 44, 48, 48, 48 }, + { 49, 49, 48, 44, 48, 48, 48 }, + { 49, 44, 49, 48, 48, 44, 48, 48, 48 }, + { 49, 49, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 49, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 49, 44, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 45, 49, 49, 48 }, + { 45, 49, 44, 49, 48, 48 }, + { 45, 49, 49, 44, 48, 48, 48 }, + { 45, 49, 49, 48, 44, 48, 48, 48 }, + { 45, 49, 44, 49, 48, 48, 44, 48, 48, 48 }, + { 45, 49, 49, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 45, 49, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 45, 49, 44, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 50 }, + { 50, 48 }, + { 50, 48, 48 }, + { 50, 44, 48, 48, 48 }, + { 50, 48, 44, 48, 48, 48 }, + { 50, 48, 48, 44, 48, 48, 48 }, + { 50, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 50, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 50, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 50, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 45, 50 }, + { 45, 50, 48 }, + { 45, 50, 48, 48 }, + { 45, 50, 44, 48, 48, 48 }, + { 45, 50, 48, 44, 48, 48, 48 }, + { 45, 50, 48, 48, 44, 48, 48, 48 }, + { 45, 50, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 45, 50, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 45, 50, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 45, 50, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 49, 48 }, + { 49, 48, 48 }, + { 49, 44, 48, 48, 48 }, + { 49, 48, 44, 48, 48, 48 }, + { 49, 48, 48, 44, 48, 48, 48 }, + { 49, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 49, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 57, 46, 57, 57, 57 }, + { 57, 57, 46, 57, 57, 57 }, + { 57, 57, 57, 46, 57, 57, 57 }, + { 57, 44, 57, 57, 57, 46, 57, 57, 57 }, + { 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 }, + { 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 }, + { 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 }, + { 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 }, + { 57, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 }, + { 45, 49, 48 }, + { 45, 49, 48, 48 }, + { 45, 49, 44, 48, 48, 48 }, + { 45, 49, 48, 44, 48, 48, 48 }, + { 45, 49, 48, 48, 44, 48, 48, 48 }, + { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 45, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 45, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 }, + { 45, 57, 46, 57, 57, 57 }, + { 45, 57, 57, 46, 57, 57, 57 }, + { 45, 57, 57, 57, 46, 57, 57, 57 }, + { 45, 57, 44, 57, 57, 57, 46, 57, 57, 57 }, + { 45, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 }, + { 45, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 }, + { 45, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 }, + { 45, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 }, + { 45, 57, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 }, + { 49 }, + { 49, 50 }, + { 49, 50, 51 }, + { 49, 44, 50, 51, 52 }, + { 49, 50, 44, 51, 52, 53 }, + { 49, 50, 51, 44, 52, 53, 54 }, + { 49, 44, 50, 51, 52, 44, 53, 54, 55 }, + { 49, 50, 44, 51, 52, 53, 44, 54, 55, 56 }, + { 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57 }, + { 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48 }, + { 45, 49 }, + { 45, 49, 50 }, + { 45, 49, 50, 51 }, + { 45, 49, 44, 50, 51, 52 }, + { 45, 49, 50, 44, 51, 52, 53 }, + { 45, 49, 50, 51, 44, 52, 53, 54 }, + { 45, 49, 44, 50, 51, 52, 44, 53, 54, 55 }, + { 45, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56 }, + { 45, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57 }, + { 45, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48 }, + { 45, 50, 44, 53, 57, 57, 46, 52 }, + { 45, 50, 44, 53, 57, 57, 46, 51, 52 }, + { 45, 50, 44, 53, 57, 57, 46, 51, 51, 52 }, + { 49 }, + { 49 }, + { 49 }, + { 49 }, + { 49 }, + { 49, 46, 48, 48, 49 }, + { 49, 46, 48, 48, 49 }, + { 49, 46, 48, 48, 49 }, + { 49, 46, 48, 48, 49 }, + { 49, 46, 48, 48, 49 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 50 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 46, 50, 50, 51 }, + { 49, 48, 48, 44, 57, 49, 51, 46, 54, 55, 49 }, + { 49, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 }, + { 50, 53, 49, 44, 56, 52, 54, 46, 51, 52, 55 }, + { 50, 53, 51, 44, 50, 52, 51, 46, 56, 56, 51 }, + { 51, 54, 53, 44, 48, 52, 53, 46, 56, 53, 51 }, + { 51, 49, 52, 44, 55, 51, 52, 46, 57, 54, 49 }, + { 53, 52, 49, 44, 49, 51, 51, 46, 57, 55, 53 }, + { 56, 53, 56, 44, 51, 55, 50, 46, 49, 50, 51 }, + { 49, 44, 48, 48, 49, 44, 48, 48, 48 }, + { 49, 44, 51, 52, 55, 44, 53, 48, 53, 46, 55, 56, 50 }, + { 51, 44, 51, 53, 56, 44, 56, 52, 52, 46, 49, 57, 55 }, + { 57, 44, 57, 57, 55, 44, 57, 55, 57, 46, 52, 48, 57 }, + { 57, 44, 57, 57, 51, 44, 55, 52, 51, 46, 49, 53, 57 }, + { 57, 44, 57, 51, 56, 44, 54, 55, 49, 46, 57, 48, 57 }, + { 51, 44, 51, 56, 53, 44, 51, 48, 50, 46, 53, 52, 55 }, + { 51, 44, 52, 48, 52, 44, 54, 52, 50, 46, 54, 54, 49 }, + { 51, 44, 52, 51, 49, 44, 50, 56, 48, 46, 48, 56, 55 }, + { 51, 44, 52, 51, 56, 44, 55, 53, 54, 46, 52, 55, 53 }, + { 51, 44, 52, 52, 54, 44, 48, 53, 51, 46, 55, 56, 55 }, + { 51, 44, 52, 53, 55, 44, 57, 49, 55, 46, 53, 49, 51 }, + { 51, 44, 52, 54, 53, 44, 51, 57, 51, 46, 57, 48, 49 }, + { 51, 44, 52, 56, 52, 44, 55, 51, 52, 46, 48, 49, 53 }, + { 51, 44, 52, 57, 50, 44, 48, 51, 49, 46, 51, 50, 55 }, + { 51, 44, 53, 48, 51, 44, 56, 57, 53, 46, 48, 53, 51 }, + { 51, 44, 53, 49, 49, 44, 51, 55, 49, 46, 52, 52, 49 }, + { 51, 44, 53, 49, 56, 44, 54, 54, 56, 46, 55, 53, 51 }, + { 51, 44, 53, 51, 48, 44, 53, 51, 50, 46, 52, 55, 57 }, + { 51, 44, 53, 51, 56, 44, 48, 48, 56, 46, 56, 54, 55 }, + { 51, 44, 53, 52, 53, 44, 51, 48, 54, 46, 49, 55, 57 }, + { 51, 44, 53, 53, 55, 44, 49, 54, 57, 46, 57, 48, 53 }, + { 51, 44, 53, 53, 55, 44, 51, 52, 56, 46, 57, 56, 49 }, + { 51, 44, 53, 54, 52, 44, 54, 52, 54, 46, 50, 57, 51 }, + { 51, 44, 53, 56, 51, 44, 57, 56, 54, 46, 52, 48, 55 }, + { 51, 44, 53, 57, 49, 44, 50, 56, 51, 46, 55, 49, 57 }, + { 51, 44, 54, 48, 51, 44, 49, 52, 55, 46, 52, 52, 53 }, + { 51, 44, 54, 49, 48, 44, 54, 50, 51, 46, 56, 51, 51 }, + { 51, 44, 54, 49, 55, 44, 57, 50, 49, 46, 49, 52, 53 }, + { 51, 44, 54, 50, 57, 44, 55, 56, 52, 46, 56, 55, 49 }, + { 51, 44, 54, 51, 55, 44, 50, 54, 49, 46, 50, 53, 57 }, + { 51, 44, 54, 53, 54, 44, 52, 50, 50, 46, 50, 57, 55 }, + { 51, 44, 54, 53, 54, 44, 54, 48, 49, 46, 51, 55, 51 }, + { 51, 44, 54, 54, 51, 44, 56, 57, 56, 46, 54, 56, 53 }, + { 51, 44, 54, 55, 53, 44, 55, 54, 50, 46, 52, 49, 49 }, + { 51, 44, 54, 56, 51, 44, 50, 51, 56, 46, 55, 57, 57 }, + { 51, 44, 54, 57, 48, 44, 53, 51, 54, 46, 49, 49, 49 }, + { 51, 44, 55, 48, 50, 44, 51, 57, 57, 46, 56, 51, 55 }, + { 51, 44, 55, 48, 57, 44, 56, 55, 54, 46, 50, 50, 53 }, + { 51, 44, 55, 49, 55, 44, 49, 55, 51, 46, 53, 51, 55 }, + { 51, 44, 55, 50, 57, 44, 48, 51, 55, 46, 50, 54, 51 }, + { 51, 44, 55, 51, 54, 44, 53, 49, 51, 46, 54, 53, 49 }, + { 51, 44, 55, 53, 53, 44, 56, 53, 51, 46, 55, 54, 53 }, + { 51, 44, 55, 54, 51, 44, 49, 53, 49, 46, 48, 55, 55 }, + { 51, 44, 55, 55, 53, 44, 48, 49, 52, 46, 56, 48, 51 }, + { 51, 44, 55, 56, 50, 44, 52, 57, 49, 46, 49, 57, 49 }, + { 51, 44, 55, 56, 57, 44, 55, 56, 56, 46, 53, 48, 51 }, + { 51, 44, 56, 48, 49, 44, 54, 53, 50, 46, 50, 50, 57 }, + { 51, 44, 56, 48, 57, 44, 49, 50, 56, 46, 54, 49, 55 }, + { 51, 44, 56, 49, 54, 44, 52, 50, 53, 46, 57, 50, 57 }, + { 51, 44, 56, 50, 56, 44, 50, 56, 57, 46, 54, 53, 53 }, + { 51, 44, 56, 50, 56, 44, 52, 54, 56, 46, 55, 51, 49 }, + { 51, 44, 56, 51, 53, 44, 55, 54, 54, 46, 48, 52, 51 }, + { 51, 44, 56, 53, 53, 44, 49, 48, 54, 46, 49, 53, 55 }, + { 51, 44, 56, 54, 50, 44, 52, 48, 51, 46, 52, 54, 57 }, + { 51, 44, 56, 55, 52, 44, 50, 54, 55, 46, 49, 57, 53 }, + { 51, 44, 56, 56, 49, 44, 55, 52, 51, 46, 53, 56, 51 }, + { 51, 44, 56, 56, 57, 44, 48, 52, 48, 46, 56, 57, 53 }, + { 51, 44, 57, 48, 48, 44, 57, 48, 52, 46, 54, 50, 49 }, + { 51, 44, 57, 48, 56, 44, 51, 56, 49, 46, 48, 48, 57 }, + { 51, 44, 57, 50, 55, 44, 53, 52, 50, 46, 48, 52, 55 }, + { 51, 44, 57, 50, 55, 44, 55, 50, 49, 46, 49, 50, 51 }, + { 51, 44, 57, 51, 53, 44, 48, 49, 56, 46, 52, 51, 53 }, + { 51, 44, 57, 52, 54, 44, 56, 56, 50, 46, 49, 54, 49 }, + { 51, 44, 57, 53, 52, 44, 51, 53, 56, 46, 53, 52, 57 }, + { 51, 44, 57, 54, 49, 44, 54, 53, 53, 46, 56, 54, 49 }, + { 51, 44, 57, 55, 51, 44, 53, 49, 57, 46, 53, 56, 55 }, + { 51, 44, 57, 56, 48, 44, 57, 57, 53, 46, 57, 55, 53 }, + { 51, 44, 57, 56, 56, 44, 50, 57, 51, 46, 50, 56, 55 }, + { 52, 44, 48, 48, 48, 44, 49, 53, 55, 46, 48, 49, 51 }, + { 52, 44, 48, 48, 55, 44, 54, 51, 51, 46, 52, 48, 49 }, + { 52, 44, 48, 50, 54, 44, 57, 55, 51, 46, 53, 49, 53 }, + { 52, 44, 48, 51, 52, 44, 50, 55, 48, 46, 56, 50, 55 }, + { 52, 44, 48, 52, 54, 44, 49, 51, 52, 46, 53, 53, 51 }, + { 52, 44, 48, 53, 51, 44, 54, 49, 48, 46, 57, 52, 49 }, + { 52, 44, 48, 54, 48, 44, 57, 48, 56, 46, 50, 53, 51 }, + { 52, 44, 48, 55, 50, 44, 55, 55, 49, 46, 57, 55, 57 }, + { 52, 44, 48, 56, 48, 44, 50, 52, 56, 46, 51, 54, 55 }, + { 52, 44, 48, 56, 55, 44, 53, 52, 53, 46, 54, 55, 57 }, + { 52, 44, 48, 57, 57, 44, 52, 48, 57, 46, 52, 48, 53 }, + { 52, 44, 48, 57, 57, 44, 53, 56, 56, 46, 52, 56, 49 }, + { 52, 44, 49, 48, 54, 44, 56, 56, 53, 46, 55, 57, 51 }, + { 52, 44, 49, 50, 54, 44, 50, 50, 53, 46, 57, 48, 55 }, + { 52, 44, 49, 51, 51, 44, 53, 50, 51, 46, 50, 49, 57 }, + { 52, 44, 49, 52, 53, 44, 51, 56, 54, 46, 57, 52, 53 }, + { 52, 44, 49, 53, 50, 44, 56, 54, 51, 46, 51, 51, 51 }, + { 52, 44, 49, 54, 48, 44, 49, 54, 48, 46, 54, 52, 53 }, + { 52, 44, 49, 55, 50, 44, 48, 50, 52, 46, 51, 55, 49 }, + { 52, 44, 49, 55, 57, 44, 53, 48, 48, 46, 55, 53, 57 }, + { 52, 44, 49, 57, 56, 44, 54, 54, 49, 46, 55, 57, 55 }, + { 52, 44, 50, 48, 51, 44, 52, 48, 55, 46, 50, 56, 55 }, + { 52, 44, 50, 49, 48, 44, 55, 48, 52, 46, 53, 57, 57 }, + { 52, 44, 50, 49, 51, 44, 52, 51, 53, 46, 52, 57, 55 }, + }; + + // The array of int[] unicode values storing the expected results + // when calling Decimal.format(double) on the currency GoldenDoubleValues. + static int[][] CurrencyGoldenFormattedValues = { + { 36, 48, 46, 48, 48 }, + { 45, 36, 48, 46, 48, 48 }, + { 36, 48, 46, 48, 48 }, + { 36, 48, 46, 48, 48 }, + { 45, 36, 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 54, 46, 50, 51 }, + { 36, 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 54, 46, 50, 51 }, + { 45, 36, 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 56, 46, 48, 48 }, + { 36, 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 56, 46, 48, 48 }, + { 45, 36, 49, 44, 57, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57 }, + { 36, 50, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 78, 97, 78 }, + { 36, 8734 }, + { 45, 36, 8734 }, + { 36, 49, 55, 57, 44, 55, 54, 57, 44, 51, 49, 51, 44, 52, 56, 54, 44, 50, 51, 49, 44, 53, 55, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 57, 44, 56, 55, 54, 44, 53, 52, 51, 44, 50, 49, 48, 46, 57, 57 }, + { 36, 57, 44, 56, 55, 54, 44, 53, 52, 51, 44, 50, 49, 48, 46, 57, 57 }, + { 45, 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 44, 48, 49, 50, 44, 51, 52, 53, 44, 54, 55, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 44, 48, 49, 50, 44, 51, 52, 53, 44, 54, 55, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 49, 46, 49, 50 }, + { 36, 49, 50, 46, 49, 50 }, + { 36, 49, 50, 51, 46, 49, 50 }, + { 36, 49, 44, 50, 51, 52, 46, 49, 50 }, + { 36, 49, 50, 44, 51, 52, 53, 46, 49, 50 }, + { 36, 49, 50, 51, 44, 52, 53, 54, 46, 49, 50 }, + { 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 49, 50 }, + { 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 49, 50 }, + { 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 49, 50 }, + { 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 49, 50 }, + { 45, 36, 49, 46, 49, 50 }, + { 45, 36, 49, 50, 46, 49, 50 }, + { 45, 36, 49, 50, 51, 46, 49, 50 }, + { 45, 36, 49, 44, 50, 51, 52, 46, 49, 50 }, + { 45, 36, 49, 50, 44, 51, 52, 53, 46, 49, 50 }, + { 45, 36, 49, 50, 51, 44, 52, 53, 54, 46, 49, 50 }, + { 45, 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 49, 50 }, + { 45, 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 49, 50 }, + { 45, 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 49, 50 }, + { 45, 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 49, 50 }, + { 36, 48, 46, 49, 48 }, + { 36, 48, 46, 49, 50 }, + { 36, 48, 46, 49, 50 }, + { 36, 49, 48, 46, 49, 48 }, + { 36, 49, 48, 46, 49, 50 }, + { 36, 49, 48, 46, 49, 50 }, + { 36, 49, 48, 48, 46, 49, 48 }, + { 36, 49, 48, 48, 46, 49, 50 }, + { 36, 49, 48, 48, 46, 49, 50 }, + { 36, 49, 44, 48, 48, 48, 46, 49, 48 }, + { 36, 49, 44, 48, 48, 48, 46, 49, 50 }, + { 36, 49, 44, 48, 48, 48, 46, 49, 50 }, + { 36, 49, 48, 44, 48, 48, 48, 46, 49, 48 }, + { 36, 49, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 36, 49, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 36, 49, 48, 48, 44, 48, 48, 48, 46, 49, 48 }, + { 36, 49, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 36, 49, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48 }, + { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48 }, + { 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48 }, + { 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48 }, + { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 36, 48, 46, 49, 48 }, + { 45, 36, 48, 46, 49, 50 }, + { 45, 36, 48, 46, 49, 50 }, + { 45, 36, 49, 48, 46, 49, 48 }, + { 45, 36, 49, 48, 46, 49, 50 }, + { 45, 36, 49, 48, 46, 49, 50 }, + { 45, 36, 49, 48, 48, 46, 49, 48 }, + { 45, 36, 49, 48, 48, 46, 49, 50 }, + { 45, 36, 49, 48, 48, 46, 49, 50 }, + { 45, 36, 49, 44, 48, 48, 48, 46, 49, 48 }, + { 45, 36, 49, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 36, 49, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 36, 49, 48, 44, 48, 48, 48, 46, 49, 48 }, + { 45, 36, 49, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 36, 49, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 36, 49, 48, 48, 44, 48, 48, 48, 46, 49, 48 }, + { 45, 36, 49, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 36, 49, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48 }, + { 45, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48 }, + { 45, 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48 }, + { 45, 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48 }, + { 45, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 45, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 }, + { 36, 49, 46, 57, 57 }, + { 36, 49, 50, 46, 57, 57 }, + { 36, 49, 50, 51, 46, 57, 57 }, + { 36, 49, 44, 50, 51, 52, 46, 57, 57 }, + { 36, 49, 50, 44, 51, 52, 53, 46, 57, 57 }, + { 36, 49, 50, 51, 44, 52, 53, 54, 46, 57, 57 }, + { 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 57, 57 }, + { 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 57, 57 }, + { 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 57, 57 }, + { 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 57, 57 }, + { 36, 50, 46, 48, 48 }, + { 36, 49, 51, 46, 48, 48 }, + { 36, 49, 50, 52, 46, 48, 48 }, + { 36, 49, 44, 50, 51, 53, 46, 48, 48 }, + { 36, 49, 50, 44, 51, 52, 54, 46, 48, 48 }, + { 36, 49, 50, 51, 44, 52, 53, 55, 46, 48, 48 }, + { 36, 49, 44, 50, 51, 52, 44, 53, 54, 56, 46, 48, 48 }, + { 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 57, 46, 48, 48 }, + { 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 57, 48, 46, 48, 48 }, + { 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 49, 46, 48, 48 }, + { 45, 36, 49, 46, 57, 57 }, + { 45, 36, 49, 50, 46, 57, 57 }, + { 45, 36, 49, 50, 51, 46, 57, 57 }, + { 45, 36, 49, 44, 50, 51, 52, 46, 57, 57 }, + { 45, 36, 49, 50, 44, 51, 52, 53, 46, 57, 57 }, + { 45, 36, 49, 50, 51, 44, 52, 53, 54, 46, 57, 57 }, + { 45, 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 57, 57 }, + { 45, 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 57, 57 }, + { 45, 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 57, 57 }, + { 45, 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 57, 57 }, + { 45, 36, 50, 46, 48, 48 }, + { 45, 36, 49, 51, 46, 48, 48 }, + { 45, 36, 49, 50, 52, 46, 48, 48 }, + { 45, 36, 49, 44, 50, 51, 53, 46, 48, 48 }, + { 45, 36, 49, 50, 44, 51, 52, 54, 46, 48, 48 }, + { 45, 36, 49, 50, 51, 44, 52, 53, 55, 46, 48, 48 }, + { 45, 36, 49, 44, 50, 51, 52, 44, 53, 54, 56, 46, 48, 48 }, + { 45, 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 57, 46, 48, 48 }, + { 45, 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 57, 48, 46, 48, 48 }, + { 45, 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 49, 46, 48, 48 }, + { 36, 49, 49, 48, 46, 48, 48 }, + { 36, 49, 44, 49, 48, 48, 46, 48, 48 }, + { 36, 49, 49, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 49, 49, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 49, 44, 49, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 49, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 49, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 49, 44, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 49, 49, 48, 46, 48, 48 }, + { 45, 36, 49, 44, 49, 48, 48, 46, 48, 48 }, + { 45, 36, 49, 49, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 49, 49, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 49, 44, 49, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 49, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 49, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 49, 44, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 50, 46, 48, 48 }, + { 36, 50, 48, 46, 48, 48 }, + { 36, 50, 48, 48, 46, 48, 48 }, + { 36, 50, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 50, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 50, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 50, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 50, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 50, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 50, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 50, 46, 48, 48 }, + { 45, 36, 50, 48, 46, 48, 48 }, + { 45, 36, 50, 48, 48, 46, 48, 48 }, + { 45, 36, 50, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 50, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 50, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 50, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 50, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 50, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 50, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 49, 48, 46, 48, 48 }, + { 36, 49, 48, 48, 46, 48, 48 }, + { 36, 49, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 49, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 49, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 36, 57, 46, 57, 57 }, + { 36, 57, 57, 46, 57, 57 }, + { 36, 57, 57, 57, 46, 57, 57 }, + { 36, 57, 44, 57, 57, 57, 46, 57, 57 }, + { 36, 57, 57, 44, 57, 57, 57, 46, 57, 57 }, + { 36, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57 }, + { 36, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57 }, + { 36, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57 }, + { 36, 57, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57 }, + { 45, 36, 49, 48, 46, 48, 48 }, + { 45, 36, 49, 48, 48, 46, 48, 48 }, + { 45, 36, 49, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 49, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 49, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 }, + { 45, 36, 57, 46, 57, 57 }, + { 45, 36, 57, 57, 46, 57, 57 }, + { 45, 36, 57, 57, 57, 46, 57, 57 }, + { 45, 36, 57, 44, 57, 57, 57, 46, 57, 57 }, + { 45, 36, 57, 57, 44, 57, 57, 57, 46, 57, 57 }, + { 45, 36, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57 }, + { 45, 36, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57 }, + { 45, 36, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57 }, + { 45, 36, 57, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57 }, + { 36, 49, 46, 48, 48 }, + { 36, 49, 50, 46, 48, 48 }, + { 36, 49, 50, 51, 46, 48, 48 }, + { 36, 49, 44, 50, 51, 52, 46, 48, 48 }, + { 36, 49, 50, 44, 51, 52, 53, 46, 48, 48 }, + { 36, 49, 50, 51, 44, 52, 53, 54, 46, 48, 48 }, + { 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 48, 48 }, + { 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 48, 48 }, + { 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 48, 48 }, + { 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 48, 48 }, + { 45, 36, 49, 46, 48, 48 }, + { 45, 36, 49, 50, 46, 48, 48 }, + { 45, 36, 49, 50, 51, 46, 48, 48 }, + { 45, 36, 49, 44, 50, 51, 52, 46, 48, 48 }, + { 45, 36, 49, 50, 44, 51, 52, 53, 46, 48, 48 }, + { 45, 36, 49, 50, 51, 44, 52, 53, 54, 46, 48, 48 }, + { 45, 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 48, 48 }, + { 45, 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 48, 48 }, + { 45, 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 48, 48 }, + { 45, 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 48, 48 }, + { 45, 36, 50, 44, 53, 57, 57, 46, 52, 48 }, + { 45, 36, 50, 44, 53, 57, 57, 46, 51, 52 }, + { 45, 36, 50, 44, 53, 57, 57, 46, 51, 51 }, + { 36, 49, 46, 48, 48 }, + { 36, 49, 46, 48, 48 }, + { 36, 49, 46, 48, 48 }, + { 36, 49, 46, 48, 48 }, + { 36, 49, 46, 48, 48 }, + { 36, 49, 46, 48, 49 }, + { 36, 49, 46, 48, 49 }, + { 36, 49, 46, 48, 49 }, + { 36, 49, 46, 48, 49 }, + { 36, 49, 46, 48, 49 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 50 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 46, 50, 51 }, + { 36, 49, 44, 48, 48, 57, 44, 49, 51, 54, 46, 55, 49 }, + { 36, 50, 44, 53, 49, 56, 44, 52, 54, 51, 46, 52, 54 }, + { 36, 50, 44, 53, 51, 50, 44, 52, 51, 56, 46, 56, 51 }, + { 36, 51, 44, 54, 53, 48, 44, 52, 53, 56, 46, 53, 51 }, + { 36, 51, 44, 49, 52, 55, 44, 51, 52, 57, 46, 54, 50 }, + { 36, 53, 44, 52, 49, 49, 44, 51, 51, 57, 46, 55, 53 }, + { 36, 56, 44, 53, 56, 51, 44, 55, 50, 49, 46, 50, 50 }, + { 36, 49, 51, 44, 52, 55, 53, 44, 48, 53, 55, 46, 56, 50 }, + { 36, 51, 51, 44, 53, 56, 56, 44, 52, 52, 49, 46, 57, 56 }, + { 36, 57, 57, 44, 57, 55, 57, 44, 55, 57, 52, 46, 48, 56 }, + { 36, 57, 57, 44, 57, 51, 55, 44, 52, 51, 49, 46, 53, 56 }, + { 36, 57, 57, 44, 51, 56, 54, 44, 55, 49, 57, 46, 48, 56 }, + { 36, 51, 51, 44, 56, 53, 51, 44, 48, 50, 53, 46, 52, 55 }, + { 36, 51, 52, 44, 48, 52, 54, 44, 52, 50, 54, 46, 54, 48 }, + { 36, 51, 52, 44, 51, 49, 50, 44, 56, 48, 48, 46, 56, 55 }, + { 36, 51, 52, 44, 51, 56, 55, 44, 53, 54, 52, 46, 55, 53 }, + { 36, 51, 52, 44, 52, 54, 48, 44, 53, 51, 55, 46, 56, 55 }, + { 36, 51, 52, 44, 53, 55, 57, 44, 49, 55, 53, 46, 49, 50 }, + { 36, 51, 52, 44, 54, 53, 51, 44, 57, 51, 57, 46, 48, 50 }, + { 36, 51, 52, 44, 56, 52, 55, 44, 51, 52, 48, 46, 49, 53 }, + { 36, 51, 52, 44, 57, 50, 48, 44, 51, 49, 51, 46, 50, 55 }, + { 36, 51, 53, 44, 48, 51, 56, 44, 57, 53, 48, 46, 53, 50 }, + { 36, 51, 53, 44, 49, 49, 51, 44, 55, 49, 52, 46, 52, 49 }, + { 36, 51, 53, 44, 49, 56, 54, 44, 54, 56, 55, 46, 53, 51 }, + { 36, 51, 53, 44, 51, 48, 53, 44, 51, 50, 52, 46, 55, 56 }, + { 36, 51, 53, 44, 51, 56, 48, 44, 48, 56, 56, 46, 54, 55 }, + { 36, 51, 53, 44, 52, 53, 51, 44, 48, 54, 49, 46, 55, 57 }, + { 36, 51, 53, 44, 53, 55, 49, 44, 54, 57, 57, 46, 48, 53 }, + { 36, 51, 53, 44, 53, 55, 51, 44, 52, 56, 57, 46, 56, 49 }, + { 36, 51, 53, 44, 54, 52, 54, 44, 52, 54, 50, 46, 57, 51 }, + { 36, 51, 53, 44, 56, 51, 57, 44, 56, 54, 52, 46, 48, 55 }, + { 36, 51, 53, 44, 57, 49, 50, 44, 56, 51, 55, 46, 50, 48 }, + { 36, 51, 54, 44, 48, 51, 49, 44, 52, 55, 52, 46, 52, 53 }, + { 36, 51, 54, 44, 49, 48, 54, 44, 50, 51, 56, 46, 51, 51 }, + { 36, 51, 54, 44, 49, 55, 57, 44, 50, 49, 49, 46, 52, 53 }, + { 36, 51, 54, 44, 50, 57, 55, 44, 56, 52, 56, 46, 55, 48 }, + { 36, 51, 54, 44, 51, 55, 50, 44, 54, 49, 50, 46, 53, 57 }, + { 36, 51, 54, 44, 53, 54, 52, 44, 50, 50, 50, 46, 57, 55 }, + { 36, 51, 54, 44, 53, 54, 54, 44, 48, 49, 51, 46, 55, 51 }, + { 36, 51, 54, 44, 54, 51, 56, 44, 57, 56, 54, 46, 56, 53 }, + { 36, 51, 54, 44, 55, 53, 55, 44, 54, 50, 52, 46, 49, 48 }, + { 36, 51, 54, 44, 56, 51, 50, 44, 51, 56, 55, 46, 57, 57 }, + { 36, 51, 54, 44, 57, 48, 53, 44, 51, 54, 49, 46, 49, 49 }, + { 36, 51, 55, 44, 48, 50, 51, 44, 57, 57, 56, 46, 51, 55 }, + { 36, 51, 55, 44, 48, 57, 56, 44, 55, 54, 50, 46, 50, 53 }, + { 36, 51, 55, 44, 49, 55, 49, 44, 55, 51, 53, 46, 51, 55 }, + { 36, 51, 55, 44, 50, 57, 48, 44, 51, 55, 50, 46, 54, 50 }, + { 36, 51, 55, 44, 51, 54, 53, 44, 49, 51, 54, 46, 53, 50 }, + { 36, 51, 55, 44, 53, 53, 56, 44, 53, 51, 55, 46, 54, 53 }, + { 36, 51, 55, 44, 54, 51, 49, 44, 53, 49, 48, 46, 55, 55 }, + { 36, 51, 55, 44, 55, 53, 48, 44, 49, 52, 56, 46, 48, 50 }, + { 36, 51, 55, 44, 56, 50, 52, 44, 57, 49, 49, 46, 57, 49 }, + { 36, 51, 55, 44, 56, 57, 55, 44, 56, 56, 53, 46, 48, 51 }, + { 36, 51, 56, 44, 48, 49, 54, 44, 53, 50, 50, 46, 50, 56 }, + { 36, 51, 56, 44, 48, 57, 49, 44, 50, 56, 54, 46, 49, 55 }, + { 36, 51, 56, 44, 49, 54, 52, 44, 50, 53, 57, 46, 50, 57 }, + { 36, 51, 56, 44, 50, 56, 50, 44, 56, 57, 54, 46, 53, 53 }, + { 36, 51, 56, 44, 50, 56, 52, 44, 54, 56, 55, 46, 51, 49 }, + { 36, 51, 56, 44, 51, 53, 55, 44, 54, 54, 48, 46, 52, 51 }, + { 36, 51, 56, 44, 53, 53, 49, 44, 48, 54, 49, 46, 53, 55 }, + { 36, 51, 56, 44, 54, 50, 52, 44, 48, 51, 52, 46, 55, 48 }, + { 36, 51, 56, 44, 55, 52, 50, 44, 54, 55, 49, 46, 57, 53 }, + { 36, 51, 56, 44, 56, 49, 55, 44, 52, 51, 53, 46, 56, 51 }, + { 36, 51, 56, 44, 56, 57, 48, 44, 52, 48, 56, 46, 57, 53 }, + { 36, 51, 57, 44, 48, 48, 57, 44, 48, 52, 54, 46, 50, 48 }, + { 36, 51, 57, 44, 48, 56, 51, 44, 56, 49, 48, 46, 48, 57 }, + { 36, 51, 57, 44, 50, 55, 53, 44, 52, 50, 48, 46, 52, 55 }, + { 36, 51, 57, 44, 50, 55, 55, 44, 50, 49, 49, 46, 50, 51 }, + { 36, 51, 57, 44, 51, 53, 48, 44, 49, 56, 52, 46, 51, 53 }, + { 36, 51, 57, 44, 52, 54, 56, 44, 56, 50, 49, 46, 54, 48 }, + { 36, 51, 57, 44, 53, 52, 51, 44, 53, 56, 53, 46, 52, 57 }, + { 36, 51, 57, 44, 54, 49, 54, 44, 53, 53, 56, 46, 54, 49 }, + { 36, 51, 57, 44, 55, 51, 53, 44, 49, 57, 53, 46, 56, 55 }, + { 36, 51, 57, 44, 56, 48, 57, 44, 57, 53, 57, 46, 55, 53 }, + { 36, 51, 57, 44, 56, 56, 50, 44, 57, 51, 50, 46, 56, 55 }, + { 36, 52, 48, 44, 48, 48, 49, 44, 53, 55, 48, 46, 49, 50 }, + { 36, 52, 48, 44, 48, 55, 54, 44, 51, 51, 52, 46, 48, 50 }, + { 36, 52, 48, 44, 50, 54, 57, 44, 55, 51, 53, 46, 49, 53 }, + { 36, 52, 48, 44, 51, 52, 50, 44, 55, 48, 56, 46, 50, 55 }, + { 36, 52, 48, 44, 52, 54, 49, 44, 51, 52, 53, 46, 53, 50 }, + { 36, 52, 48, 44, 53, 51, 54, 44, 49, 48, 57, 46, 52, 49 }, + { 36, 52, 48, 44, 54, 48, 57, 44, 48, 56, 50, 46, 53, 51 }, + { 36, 52, 48, 44, 55, 50, 55, 44, 55, 49, 57, 46, 55, 56 }, + { 36, 52, 48, 44, 56, 48, 50, 44, 52, 56, 51, 46, 54, 55 }, + { 36, 52, 48, 44, 56, 55, 53, 44, 52, 53, 54, 46, 55, 57 }, + { 36, 52, 48, 44, 57, 57, 52, 44, 48, 57, 52, 46, 48, 53 }, + { 36, 52, 48, 44, 57, 57, 53, 44, 56, 56, 52, 46, 56, 49 }, + { 36, 52, 49, 44, 48, 54, 56, 44, 56, 53, 55, 46, 57, 51 }, + { 36, 52, 49, 44, 50, 54, 50, 44, 50, 53, 57, 46, 48, 55 }, + { 36, 52, 49, 44, 51, 51, 53, 44, 50, 51, 50, 46, 50, 48 }, + { 36, 52, 49, 44, 52, 53, 51, 44, 56, 54, 57, 46, 52, 53 }, + { 36, 52, 49, 44, 53, 50, 56, 44, 54, 51, 51, 46, 51, 51 }, + { 36, 52, 49, 44, 54, 48, 49, 44, 54, 48, 54, 46, 52, 53 }, + { 36, 52, 49, 44, 55, 50, 48, 44, 50, 52, 51, 46, 55, 48 }, + { 36, 52, 49, 44, 55, 57, 53, 44, 48, 48, 55, 46, 53, 57 }, + { 36, 52, 49, 44, 57, 56, 54, 44, 54, 49, 55, 46, 57, 55 }, + { 36, 52, 50, 44, 48, 51, 52, 44, 48, 55, 50, 46, 56, 55 }, + { 36, 52, 50, 44, 49, 48, 55, 44, 48, 52, 53, 46, 57, 56 }, + { 36, 52, 50, 44, 49, 51, 52, 44, 51, 53, 52, 46, 57, 56 }, + }; + +} diff --git a/ojluni/src/test/java/text/Format/DecimalFormat/SetGroupingSizeTest.java b/ojluni/src/test/java/text/Format/DecimalFormat/SetGroupingSizeTest.java new file mode 100644 index 00000000000..a28c00bc276 --- /dev/null +++ b/ojluni/src/test/java/text/Format/DecimalFormat/SetGroupingSizeTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2019, 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 8212749 + * @summary test whether input value check for + * DecimalFormat.setGroupingSize(int) works correctly. + * @run testng/othervm SetGroupingSizeTest + */ + +package test.java.text.Format.DecimalFormat; + +import java.text.DecimalFormat; + +import static org.testng.Assert.assertEquals; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +@Test +public class SetGroupingSizeTest { + + @DataProvider + public static Object[][] validGroupingSizes() { + return new Object[][] { + { 0 }, + { Byte.MAX_VALUE }, + }; + } + + @DataProvider + public static Object[][] invalidGroupingSizes() { + return new Object[][] { + { Byte.MIN_VALUE - 1 }, + { Byte.MIN_VALUE }, + { -1 }, + { Byte.MAX_VALUE + 1 }, + { Integer.MIN_VALUE }, + { Integer.MAX_VALUE }, + }; + } + + @Test(dataProvider = "validGroupingSizes") + public void test_validGroupingSize(int newVal) { + DecimalFormat df = new DecimalFormat(); + df.setGroupingSize(newVal); + assertEquals(df.getGroupingSize(), newVal); + } + + @Test(dataProvider = "invalidGroupingSizes", + expectedExceptions = IllegalArgumentException.class) + public void test_invalidGroupingSize(int newVal) { + DecimalFormat df = new DecimalFormat(); + df.setGroupingSize(newVal); + } +} diff --git a/ojluni/src/test/java/text/Format/MessageFormat/Bug6481179.java b/ojluni/src/test/java/text/Format/MessageFormat/Bug6481179.java new file mode 100644 index 00000000000..aab78f1b88b --- /dev/null +++ b/ojluni/src/test/java/text/Format/MessageFormat/Bug6481179.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2011, 2016, 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 + * @summary Confirm that a bug in an error message has been fixed. + * @bug 6481179 + */ + +package test.java.text.Format.MessageFormat; + +import java.text.MessageFormat; +import java.text.ParseException; + +public class Bug6481179 { + + public static void main(String[] args) { + boolean err = false; + + try { + MessageFormat.format("Testdata {1,invalid_format_type}", + new Object[] { "val0", "val1" }); + + System.err.println("Error: IllegalArgumentException should be thrown."); + err = true; + } + catch (IllegalArgumentException e) { + String expected = "unknown format type: invalid_format_type"; + String got = e.getMessage(); + + if (!expected.equals(got)) { + System.err.println("Error: Unexpected error message: " + got); + err = true; + } + } + catch (Exception e) { + System.err.println("Error: Unexpected exception was thrown: " + e); + err = true; + } + + if (err) { + throw new RuntimeException("Failed."); + } + } + +} diff --git a/ojluni/src/test/java/text/Format/MessageFormat/Bug7003643.java b/ojluni/src/test/java/text/Format/MessageFormat/Bug7003643.java new file mode 100644 index 00000000000..57abba42d64 --- /dev/null +++ b/ojluni/src/test/java/text/Format/MessageFormat/Bug7003643.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2010, 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 7003643 + * @summary Make sure MessageFormat.toPattern produces correct quoting. (SPI part is tested in PluggableLocale tests.) + * @key randomness + */ + +package test.java.text.Format.MessageFormat; + +import java.text.*; +import java.util.*; + +public class Bug7003643 { + private static final int N = 5; + + private static final String[] elements = { + "'{'", "'{", "{", "''", "}", "a", "'", + }; + + public static void main(String[] args) { + Random rand = new Random(); + int count = 0; + int max = (int) (Math.pow((double)elements.length, (double)N)/0.52); + while (count < max) { + // Create a random pattern. If the produced pattern is + // valid, then proceed with the round-trip testing. + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < N; i++) { + sb.append(elements[rand.nextInt(elements.length)]); + } + String pattern = sb.toString(); + MessageFormat mf = null; + try { + mf = new MessageFormat(pattern); + } catch (IllegalArgumentException e) { + // bad pattern data + } + if (mf == null) { + continue; + } + count++; + String res1 = MessageFormat.format(pattern, 123); + String toPattern = mf.toPattern(); + String res2 = MessageFormat.format(toPattern, 123); + if (!res1.equals(res2)) { + String s = String.format("Failed%n pattern=\"%s\" => result=\"%s\"%n" + + " toPattern()=\"%s\" => result=\"%s\"%n", + pattern, res1, toPattern, res2); + throw new RuntimeException(s); + } + } + } +} diff --git a/ojluni/src/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java b/ojluni/src/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java new file mode 100644 index 00000000000..3084266da23 --- /dev/null +++ b/ojluni/src/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2016, 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 4105380 + * @summary basic tests for new methods getFormatsByArgumentIndex, setFormatByArgumentIndex, setFormatsByArgumentIndex + */ + +package test.java.text.Format.MessageFormat; + +import java.text.ChoiceFormat; +import java.text.Format; +import java.text.MessageFormat; +import java.text.NumberFormat; + +public class MessageFormatsByArgumentIndex { + + private static String choicePattern = "0.0#are no files|1.0#is one file|1.0<are {0,number,integer} files"; + + public static void main(String[] args) { + Format[] subformats; + + MessageFormat format = new MessageFormat("{3, choice," + choicePattern + "}, {2}, {0}"); + + subformats = format.getFormatsByArgumentIndex(); + checkSubformatLength(subformats, 4); + checkSubformat(subformats, 0, null); + checkSubformat(subformats, 1, null); + checkSubformat(subformats, 2, null); + checkSubformat(subformats, 3, new ChoiceFormat(choicePattern)); + + subformats = format.getFormats(); + checkSubformatLength(subformats, 3); + checkSubformat(subformats, 0, new ChoiceFormat(choicePattern)); + checkSubformat(subformats, 1, null); + checkSubformat(subformats, 2, null); + + format.setFormatByArgumentIndex(0, NumberFormat.getInstance()); + + checkPattern(format.toPattern(), "{3,choice," + choicePattern + "}, {2}, {0,number}"); + + subformats = format.getFormatsByArgumentIndex(); + checkSubformatLength(subformats, 4); + checkSubformat(subformats, 0, NumberFormat.getInstance()); + checkSubformat(subformats, 1, null); + checkSubformat(subformats, 2, null); + checkSubformat(subformats, 3, new ChoiceFormat(choicePattern)); + + subformats = format.getFormats(); + checkSubformatLength(subformats, 3); + checkSubformat(subformats, 0, new ChoiceFormat(choicePattern)); + checkSubformat(subformats, 1, null); + checkSubformat(subformats, 2, NumberFormat.getInstance()); + + format.setFormatsByArgumentIndex(subformats); + + checkPattern(format.toPattern(), "{3,choice," + choicePattern + "}, {2,number}, {0,choice," + choicePattern + "}"); + + subformats = format.getFormatsByArgumentIndex(); + checkSubformatLength(subformats, 4); + checkSubformat(subformats, 0, new ChoiceFormat(choicePattern)); + checkSubformat(subformats, 1, null); + checkSubformat(subformats, 2, NumberFormat.getInstance()); + checkSubformat(subformats, 3, new ChoiceFormat(choicePattern)); + + subformats = format.getFormats(); + checkSubformatLength(subformats, 3); + checkSubformat(subformats, 0, new ChoiceFormat(choicePattern)); + checkSubformat(subformats, 1, NumberFormat.getInstance()); + checkSubformat(subformats, 2, new ChoiceFormat(choicePattern)); + + } + + private static void checkPattern(String actual, String expected) { + if (!expected.equals(actual)) { + throw new RuntimeException("unexpected pattern:\n expected: " + expected + "\n actual: " + actual); + } + } + + private static void checkSubformatLength(Format[] subformats, int expected) { + if (subformats.length != expected) { + throw new RuntimeException("unexpected subformat length:\n expected: " + expected + "\n actual: " + subformats.length); + } + } + + private static void checkSubformat(Format[] subformats, int index, Format expected) { + Format subformat = subformats[index]; + if (subformat == expected) { + return; + } + if ((subformat != null) && subformat.equals(expected)) { + return; + } + throw new RuntimeException("found unexpected subformat for argument " + index + ":\n expected: " + expected + "\n actual: " + subformat); + } +} diff --git a/ojluni/src/test/java/text/Format/MessageFormat/MessageRegression.java b/ojluni/src/test/java/text/Format/MessageFormat/MessageRegression.java new file mode 100644 index 00000000000..cd019152dc3 --- /dev/null +++ b/ojluni/src/test/java/text/Format/MessageFormat/MessageRegression.java @@ -0,0 +1,690 @@ +/* + * Copyright (c) 1997, 2017, 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 4031438 4058973 4074764 4094906 4104976 4105380 4106659 4106660 4106661 + * 4111739 4112104 4113018 4114739 4114743 4116444 4118592 4118594 4120552 + * 4142938 4169959 4232154 4293229 8187551 + * @summary Regression tests for MessageFormat and associated classes + * @library /java/text/testlib + * @run main MessageRegression + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +package test.java.text.Format.MessageFormat; + +import java.text.*; +import java.util.*; +import java.io.IOException; +import java.io.FileOutputStream; +import java.io.FileInputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectInputStream; +import java.io.Serializable; + +import test.java.text.testlib.IntlTest; +import test.java.text.testlib.TestUtils; + +public class MessageRegression extends IntlTest { + + public static void main(String[] args) throws Exception { + new MessageRegression().run(args); + } + + /* @bug 4074764 + * Null exception when formatting pattern with MessageFormat + * with no parameters. + */ + public void Test4074764() { + String[] pattern = {"Message without param", + "Message with param:{0}", + "Longer Message with param {0}"}; + //difference between the two param strings are that + //in the first one, the param position is within the + //length of the string without param while it is not so + //in the other case. + + MessageFormat messageFormatter = new MessageFormat(""); + + try { + //Apply pattern with param and print the result + messageFormatter.applyPattern(pattern[1]); + Object[] params = {new String("BUG"), new Date()}; + String tempBuffer = messageFormatter.format(params); + if (!tempBuffer.equals("Message with param:BUG")) + errln("MessageFormat with one param test failed."); + logln("Formatted with one extra param : " + tempBuffer); + + //Apply pattern without param and print the result + messageFormatter.applyPattern(pattern[0]); + tempBuffer = messageFormatter.format(null); + if (!tempBuffer.equals("Message without param")) + errln("MessageFormat with no param test failed."); + logln("Formatted with no params : " + tempBuffer); + + tempBuffer = messageFormatter.format(params); + if (!tempBuffer.equals("Message without param")) + errln("Formatted with arguments > subsitution failed. result = " + tempBuffer.toString()); + logln("Formatted with extra params : " + tempBuffer); + //This statement gives an exception while formatting... + //If we use pattern[1] for the message with param, + //we get an NullPointerException in MessageFormat.java(617) + //If we use pattern[2] for the message with param, + //we get an StringArrayIndexOutOfBoundsException in MessageFormat.java(614) + //Both are due to maxOffset not being reset to -1 + //in applyPattern() when the pattern does not + //contain any param. + } catch (Exception foo) { + errln("Exception when formatting with no params."); + } + } + + /* @bug 4058973 + * MessageFormat.toPattern has weird rounding behavior. + */ + public void Test4058973() { + + MessageFormat fmt = new MessageFormat("{0,choice,0#no files|1#one file|1< {0,number,integer} files}"); + String pat = fmt.toPattern(); + if (!pat.equals("{0,choice,0.0#no files|1.0#one file|1.0< {0,number,integer} files}")) { + errln("MessageFormat.toPattern failed"); + } + } + /* @bug 4031438 + * More robust message formats. + */ + public void Test4031438() { + Locale locale = Locale.getDefault(); + if (!TestUtils.usesAsciiDigits(locale)) { + logln("Skipping this test because locale is " + locale); + return; + } + + String pattern1 = "Impossible {1} has occurred -- status code is {0} and message is {2}."; + String pattern2 = "Double '' Quotes {0} test and quoted '{1}' test plus 'other {2} stuff'."; + + MessageFormat messageFormatter = new MessageFormat(""); + + try { + logln("Apply with pattern : " + pattern1); + messageFormatter.applyPattern(pattern1); + Object[] params = {7}; + String tempBuffer = messageFormatter.format(params); + if (!tempBuffer.equals("Impossible {1} has occurred -- status code is 7 and message is {2}.")) + errln("Tests arguments < substitution failed. Formatted text=" + + "<" + tempBuffer + ">"); + logln("Formatted with 7 : " + tempBuffer); + ParsePosition status = new ParsePosition(0); + Object[] objs = messageFormatter.parse(tempBuffer, status); + if (objs[params.length] != null) + errln("Parse failed with more than expected arguments"); + for (int i = 0; i < objs.length; i++) { + if (objs[i] != null && !objs[i].toString().equals(params[i].toString())) { + errln("Parse failed on object " + objs[i] + " at index : " + i); + } + } + tempBuffer = messageFormatter.format(null); + if (!tempBuffer.equals("Impossible {1} has occurred -- status code is {0} and message is {2}.")) + errln("Tests with no arguments failed"); + logln("Formatted with null : " + tempBuffer); + logln("Apply with pattern : " + pattern2); + messageFormatter.applyPattern(pattern2); + tempBuffer = messageFormatter.format(params); + if (!tempBuffer.equals("Double ' Quotes 7 test and quoted {1} test plus other {2} stuff.")) + errln("quote format test (w/ params) failed."); + logln("Formatted with params : " + tempBuffer); + tempBuffer = messageFormatter.format(null); + if (!tempBuffer.equals("Double ' Quotes {0} test and quoted {1} test plus other {2} stuff.")) + errln("quote format test (w/ null) failed."); + logln("Formatted with null : " + tempBuffer); + logln("toPattern : " + messageFormatter.toPattern()); + } catch (Exception foo) { + errln("Exception when formatting in bug 4031438. "+foo.getMessage()); + } + } + public void Test4052223() + { + ParsePosition pos = new ParsePosition(0); + if (pos.getErrorIndex() != -1) { + errln("ParsePosition.getErrorIndex initialization failed."); + } + MessageFormat fmt = new MessageFormat("There are {0} apples growing on the {1} tree."); + String str = new String("There is one apple growing on the peach tree."); + Object[] objs = fmt.parse(str, pos); + logln("unparsable string , should fail at " + pos.getErrorIndex()); + if (pos.getErrorIndex() == -1) + errln("Bug 4052223 failed : parsing string " + str); + pos.setErrorIndex(4); + if (pos.getErrorIndex() != 4) + errln("setErrorIndex failed, got " + pos.getErrorIndex() + " instead of 4"); + ChoiceFormat f = new ChoiceFormat( + "-1#are negative|0#are no or fraction|1#is one|1.0<is 1+|2#are two|2<are more than 2."); + pos.setIndex(0); pos.setErrorIndex(-1); + Number obj = f.parse("are negative", pos); + if (pos.getErrorIndex() != -1 && obj.doubleValue() == -1.0) + errln("Parse with \"are negative\" failed, at " + pos.getErrorIndex()); + pos.setIndex(0); pos.setErrorIndex(-1); + obj = f.parse("are no or fraction ", pos); + if (pos.getErrorIndex() != -1 && obj.doubleValue() == 0.0) + errln("Parse with \"are no or fraction\" failed, at " + pos.getErrorIndex()); + pos.setIndex(0); pos.setErrorIndex(-1); + obj = f.parse("go postal", pos); + if (pos.getErrorIndex() == -1 && !Double.isNaN(obj.doubleValue())) + errln("Parse with \"go postal\" failed, at " + pos.getErrorIndex()); + } + /* @bug 4104976 + * ChoiceFormat.equals(null) throws NullPointerException + */ + public void Test4104976() + { + double[] limits = {1, 20}; + String[] formats = {"xyz", "abc"}; + ChoiceFormat cf = new ChoiceFormat(limits, formats); + try { + log("Compares to null is always false, returned : "); + logln(cf.equals(null) ? "TRUE" : "FALSE"); + } catch (Exception foo) { + errln("ChoiceFormat.equals(null) throws exception."); + } + } + /* @bug 4106659 + * ChoiceFormat.ctor(double[], String[]) doesn't check + * whether lengths of input arrays are equal. + */ + public void Test4106659() + { + double[] limits = {1, 2, 3}; + String[] formats = {"one", "two"}; + ChoiceFormat cf = null; + try { + cf = new ChoiceFormat(limits, formats); + } catch (Exception foo) { + logln("ChoiceFormat constructor should check for the array lengths"); + cf = null; + } + if (cf != null) errln(cf.format(5)); + } + + /* @bug 4106660 + * ChoiceFormat.ctor(double[], String[]) allows unordered double array. + * This is not a bug, added javadoc to emphasize the use of limit + * array must be in ascending order. + */ + public void Test4106660() + { + double[] limits = {3, 1, 2}; + String[] formats = {"Three", "One", "Two"}; + ChoiceFormat cf = new ChoiceFormat(limits, formats); + double d = 5.0; + String str = cf.format(d); + if (!str.equals("Two")) + errln("format(" + d + ") = " + cf.format(d)); + } + + /* @bug 4111739 + * MessageFormat is incorrectly serialized/deserialized. + */ + public void Test4111739() + { + MessageFormat format1 = null; + MessageFormat format2 = null; + ObjectOutputStream ostream = null; + ByteArrayOutputStream baos = null; + ObjectInputStream istream = null; + + try { + baos = new ByteArrayOutputStream(); + ostream = new ObjectOutputStream(baos); + } catch(IOException e) { + errln("Unexpected exception : " + e.getMessage()); + return; + } + + try { + format1 = new MessageFormat("pattern{0}"); + ostream.writeObject(format1); + ostream.flush(); + + byte bytes[] = baos.toByteArray(); + + istream = new ObjectInputStream(new ByteArrayInputStream(bytes)); + format2 = (MessageFormat)istream.readObject(); + } catch(Exception e) { + errln("Unexpected exception : " + e.getMessage()); + } + + if (!format1.equals(format2)) { + errln("MessageFormats before and after serialization are not" + + " equal\nformat1 = " + format1 + "(" + format1.toPattern() + ")\nformat2 = " + + format2 + "(" + format2.toPattern() + ")"); + } else { + logln("Serialization for MessageFormat is OK."); + } + } + /* @bug 4114743 + * MessageFormat.applyPattern allows illegal patterns. + */ + public void Test4114743() + { + String originalPattern = "initial pattern"; + MessageFormat mf = new MessageFormat(originalPattern); + try { + String illegalPattern = "ab { '}' de"; + mf.applyPattern(illegalPattern); + errln("illegal pattern: \"" + illegalPattern + "\""); + } catch (IllegalArgumentException foo) { + if (!originalPattern.equals(mf.toPattern())) + errln("pattern after: \"" + mf.toPattern() + "\""); + } + } + + /* @bug 4116444 + * MessageFormat.parse has different behavior in case of null. + */ + public void Test4116444() + { + String[] patterns = {"", "one", "{0,date,short}"}; + MessageFormat mf = new MessageFormat(""); + + for (int i = 0; i < patterns.length; i++) { + String pattern = patterns[i]; + mf.applyPattern(pattern); + try { + Object[] array = mf.parse(null, new ParsePosition(0)); + logln("pattern: \"" + pattern + "\""); + log(" parsedObjects: "); + if (array != null) { + log("{"); + for (int j = 0; j < array.length; j++) { + if (array[j] != null) + err("\"" + array[j].toString() + "\""); + else + log("null"); + if (j < array.length - 1) log(","); + } + log("}") ; + } else { + log("null"); + } + logln(""); + } catch (Exception e) { + errln("pattern: \"" + pattern + "\""); + errln(" Exception: " + e.getMessage()); + } + } + + } + /* @bug 4114739 (FIX and add javadoc) + * MessageFormat.format has undocumented behavior about empty format objects. + */ + public void Test4114739() + { + + MessageFormat mf = new MessageFormat("<{0}>"); + Object[] objs1 = null; + Object[] objs2 = {}; + Object[] objs3 = {null}; + try { + logln("pattern: \"" + mf.toPattern() + "\""); + log("format(null) : "); + logln("\"" + mf.format(objs1) + "\""); + log("format({}) : "); + logln("\"" + mf.format(objs2) + "\""); + log("format({null}) :"); + logln("\"" + mf.format(objs3) + "\""); + } catch (Exception e) { + errln("Exception thrown for null argument tests."); + } + } + + /* @bug 4113018 + * MessageFormat.applyPattern works wrong with illegal patterns. + */ + public void Test4113018() + { + String originalPattern = "initial pattern"; + MessageFormat mf = new MessageFormat(originalPattern); + String illegalPattern = "format: {0, xxxYYY}"; + logln("pattern before: \"" + mf.toPattern() + "\""); + logln("illegal pattern: \"" + illegalPattern + "\""); + try { + mf.applyPattern(illegalPattern); + errln("Should have thrown IllegalArgumentException for pattern : " + illegalPattern); + } catch (IllegalArgumentException e) { + if (!originalPattern.equals(mf.toPattern())) + errln("pattern after: \"" + mf.toPattern() + "\""); + } + } + /* @bug 4106661 + * ChoiceFormat is silent about the pattern usage in javadoc. + */ + public void Test4106661() + { + ChoiceFormat fmt = new ChoiceFormat( + "-1#are negative| 0#are no or fraction | 1#is one |1.0<is 1+ |2#are two |2<are more than 2."); + logln("Formatter Pattern : " + fmt.toPattern()); + + logln("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY)); + logln("Format with -1.0 : " + fmt.format(-1.0)); + logln("Format with 0 : " + fmt.format(0)); + logln("Format with 0.9 : " + fmt.format(0.9)); + logln("Format with 1.0 : " + fmt.format(1)); + logln("Format with 1.5 : " + fmt.format(1.5)); + logln("Format with 2 : " + fmt.format(2)); + logln("Format with 2.1 : " + fmt.format(2.1)); + logln("Format with NaN : " + fmt.format(Double.NaN)); + logln("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY)); + } + /* @bug 4094906 + * ChoiceFormat should accept \u221E as eq. to INF. + */ + public void Test4094906() + { + ChoiceFormat fmt = new ChoiceFormat( + "-\u221E<are negative|0<are no or fraction|1#is one|1.0<is 1+|\u221E<are many."); + if (!fmt.toPattern().startsWith("-\u221E<are negative|0.0<are no or fraction|1.0#is one|1.0<is 1+|\u221E<are many.")) + errln("Formatter Pattern : " + fmt.toPattern()); + logln("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY)); + logln("Format with -1.0 : " + fmt.format(-1.0)); + logln("Format with 0 : " + fmt.format(0)); + logln("Format with 0.9 : " + fmt.format(0.9)); + logln("Format with 1.0 : " + fmt.format(1)); + logln("Format with 1.5 : " + fmt.format(1.5)); + logln("Format with 2 : " + fmt.format(2)); + logln("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY)); + } + + /* @bug 4118592 + * MessageFormat.parse fails with ChoiceFormat. + */ + public void Test4118592() + { + MessageFormat mf = new MessageFormat(""); + String pattern = "{0,choice,1#YES|2#NO}"; + String prefix = ""; + for (int i = 0; i < 5; i++) { + String formatted = prefix + "YES"; + mf.applyPattern(prefix + pattern); + prefix += "x"; + Object[] objs = mf.parse(formatted, new ParsePosition(0)); + logln(i + ". pattern :\"" + mf.toPattern() + "\""); + log(" \"" + formatted + "\" parsed as "); + if (objs == null) logln(" null"); + else logln(" " + objs[0]); + } + } + /* @bug 4118594 + * MessageFormat.parse fails for some patterns. + */ + public void Test4118594() + { + MessageFormat mf = new MessageFormat("{0}, {0}, {0}"); + String forParsing = "x, y, z"; + Object[] objs = mf.parse(forParsing, new ParsePosition(0)); + logln("pattern: \"" + mf.toPattern() + "\""); + logln("text for parsing: \"" + forParsing + "\""); + if (!objs[0].toString().equals("z")) + errln("argument0: \"" + objs[0] + "\""); + mf.setLocale(Locale.US); + mf.applyPattern("{0,number,#.##}, {0,number,#.#}"); + Object[] oldobjs = {3.1415}; + String result = mf.format( oldobjs ); + logln("pattern: \"" + mf.toPattern() + "\""); + logln("text for parsing: \"" + result + "\""); + // result now equals "3.14, 3.1" + if (!result.equals("3.14, 3.1")) + errln("result = " + result); + Object[] newobjs = mf.parse(result, new ParsePosition(0)); + // newobjs now equals {new Double(3.1)} + if (((Double)newobjs[0]).doubleValue() != 3.1) + errln( "newobjs[0] = " + newobjs[0]); + } + /* @bug 4105380 + * When using ChoiceFormat, MessageFormat is not good for I18n. + */ + public void Test4105380() + { + String patternText1 = "The disk \"{1}\" contains {0}."; + String patternText2 = "There are {0} on the disk \"{1}\""; + MessageFormat form1 = new MessageFormat(patternText1); + MessageFormat form2 = new MessageFormat(patternText2); + double[] filelimits = {0,1,2}; + String[] filepart = {"no files","one file","{0,number} files"}; + ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart); + form1.setFormat(1, fileform); + form2.setFormat(0, fileform); + Object[] testArgs = {12373L, "MyDisk"}; + logln(form1.format(testArgs)); + logln(form2.format(testArgs)); + } + /* @bug 4120552 + * MessageFormat.parse incorrectly sets errorIndex. + */ + public void Test4120552() + { + MessageFormat mf = new MessageFormat("pattern"); + String texts[] = {"pattern", "pat", "1234"}; + logln("pattern: \"" + mf.toPattern() + "\""); + for (int i = 0; i < texts.length; i++) { + ParsePosition pp = new ParsePosition(0); + Object[] objs = mf.parse(texts[i], pp); + log(" text for parsing: \"" + texts[i] + "\""); + if (objs == null) { + logln(" (incorrectly formatted string)"); + if (pp.getErrorIndex() == -1) + errln("Incorrect error index: " + pp.getErrorIndex()); + } else { + logln(" (correctly formatted string)"); + } + } + } + + /** + * @bug 4142938 + * MessageFormat handles single quotes in pattern wrong. + * This is actually a problem in ChoiceFormat; it doesn't + * understand single quotes. + */ + public void Test4142938() { + String pat = "''Vous'' {0,choice,0#n''|1#}avez s\u00E9lectionne\u00E9 " + + "{0,choice,0#aucun|1#{0}} client{0,choice,0#s|1#|2#s} " + + "personnel{0,choice,0#s|1#|2#s}."; + MessageFormat mf = new MessageFormat(pat); + + String[] PREFIX = { + "'Vous' n'avez s\u00E9lectionne\u00E9 aucun clients personnels.", + "'Vous' avez s\u00E9lectionne\u00E9 ", + "'Vous' avez s\u00E9lectionne\u00E9 " + }; + String[] SUFFIX = { + null, + " client personnel.", + " clients personnels." + }; + + for (int i=0; i<3; i++) { + String out = mf.format(new Object[]{i}); + if (SUFFIX[i] == null) { + if (!out.equals(PREFIX[i])) + errln("" + i + ": Got \"" + out + "\"; Want \"" + PREFIX[i] + "\""); + } + else { + if (!out.startsWith(PREFIX[i]) || + !out.endsWith(SUFFIX[i])) + errln("" + i + ": Got \"" + out + "\"; Want \"" + PREFIX[i] + "\"...\"" + + SUFFIX[i] + "\""); + } + } + } + + /** + * @bug 4142938 + * Test the applyPattern and toPattern handling of single quotes + * by ChoiceFormat. (This is in here because this was a bug reported + * against MessageFormat.) The single quote is used to quote the + * pattern characters '|', '#', '<', and '\u2264'. Two quotes in a row + * is a quote literal. + */ + public void TestChoicePatternQuote() { + String[] DATA = { + // Pattern 0 value 1 value + "0#can''t|1#can", "can't", "can", + "0#'pound(#)=''#'''|1#xyz", "pound(#)='#'", "xyz", + "0#'1<2 | 1\u22641'|1#''", "1<2 | 1\u22641", "'", + }; + for (int i=0; i<DATA.length; i+=3) { + try { + ChoiceFormat cf = new ChoiceFormat(DATA[i]); + for (int j=0; j<=1; ++j) { + String out = cf.format(j); + if (!out.equals(DATA[i+1+j])) + errln("Fail: Pattern \"" + DATA[i] + "\" x "+j+" -> " + + out + "; want \"" + DATA[i+1+j] + '"'); + } + String pat = cf.toPattern(); + String pat2 = new ChoiceFormat(pat).toPattern(); + if (!pat.equals(pat2)) + errln("Fail: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"'); + else + logln("Ok: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"'); + } + catch (IllegalArgumentException e) { + errln("Fail: Pattern \"" + DATA[i] + "\" -> " + e); + } + } + } + + /** + * @bug 4112104 + * MessageFormat.equals(null) throws a NullPointerException. The JLS states + * that it should return false. + */ + public void Test4112104() { + MessageFormat format = new MessageFormat(""); + try { + // This should NOT throw an exception + if (format.equals(null)) { + // It also should return false + errln("MessageFormat.equals(null) returns false"); + } + } + catch (NullPointerException e) { + errln("MessageFormat.equals(null) throws " + e); + } + } + + /** + * @bug 4169959 + * MessageFormat does not format null objects. CANNOT REPRODUCE THIS BUG. + */ + public void Test4169959() { + // This works + logln(MessageFormat.format( "This will {0}", "work")); + + // This fails + logln(MessageFormat.format( "This will {0}", + new Object[]{ null } ) ); + } + + public void test4232154() { + boolean gotException = false; + try { + MessageFormat format = new MessageFormat("The date is {0:date}"); + } catch (Exception e) { + gotException = true; + if (!(e instanceof IllegalArgumentException)) { + throw new RuntimeException("got wrong exception type"); + } + if ("argument number too large at ".equals(e.getMessage())) { + throw new RuntimeException("got wrong exception message"); + } + } + if (!gotException) { + throw new RuntimeException("didn't get exception for invalid input"); + } + } + + public void test4293229() { + MessageFormat format = new MessageFormat("'''{'0}'' '''{0}'''"); + Object[] args = { null }; + String expected = "'{0}' '{0}'"; + String result = format.format(args); + if (!result.equals(expected)) { + throw new RuntimeException("wrong format result - expected \"" + + expected + "\", got \"" + result + "\""); + } + } + + /** + * @bug 8187551 + * test MessageFormat.setFormat() method to throw AIOOBE on invalid index. + */ + public void test8187551() { + //invalid cases ("pattern", "invalid format element index") + String[][] invalidCases = {{"The disk \"{1}\" contains {0}.", "2"}, + {"The disk \"{1}\" contains {0}.", "9"}, + {"On {1}, there are {0} and {2} folders", "3"}}; + + //invalid cases (must throw exception) + Arrays.stream(invalidCases).forEach(entry -> messageSetFormat(entry[0], + Integer.valueOf(entry[1]))); + } + + // test MessageFormat.setFormat() method for the given pattern and + // format element index + private void messageSetFormat(String pattern, int elemIndex) { + MessageFormat form = new MessageFormat(pattern); + + double[] fileLimits = {0, 1, 2}; + String[] filePart = {"no files", "one file", "{0,number} files"}; + ChoiceFormat fileForm = new ChoiceFormat(fileLimits, filePart); + + boolean AIOOBEThrown = false; + try { + form.setFormat(elemIndex, fileForm); + } catch (ArrayIndexOutOfBoundsException ex) { + AIOOBEThrown = true; + } + + if (!AIOOBEThrown) { + throw new RuntimeException("[FAILED: Must throw" + + " ArrayIndexOutOfBoundsException for" + + " invalid index " + elemIndex + " used in" + + " MessageFormat.setFormat(index, format)]"); + } + } + +} diff --git a/ojluni/src/test/java/text/Format/MessageFormat/MessageTest.java b/ojluni/src/test/java/text/Format/MessageFormat/MessageTest.java new file mode 100644 index 00000000000..6db035f9717 --- /dev/null +++ b/ojluni/src/test/java/text/Format/MessageFormat/MessageTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1997, 2016, 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 + * @library /java/text/testlib + * @summary test MessageFormat + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + + +package test.java.text.Format.MessageFormat; + +import java.util.*; +import java.io.*; +import java.text.*; + +import test.java.text.testlib.IntlTest; + +public class MessageTest extends IntlTest { + + public static void main(String[] args) throws Exception { + new MessageTest().run(args); + } + + + public void TestMSGPatternTest() { + Object[] testArgs = { + 1D, 3456D, + "Disk", new Date(10000000000L)}; + + String[] testCases = { + "Quotes '', '{', 'a' {0} '{0}'", + "Quotes '', '{', 'a' {0,number} '{0}'", + "'{'1,number,'#',##} {1,number,'#',##}", + "There are {1} files on {2} at {3}", + "On {2}, there are {1} files, with {0,number,currency}.", + "'{1,number,percent}', {1,number,percent}, ", + "'{1,date,full}', {1,date,full}, ", + "'{3,date,full}', {3,date,full}, ", + "'{1,number,#,##}' {1,number,#,##}", + }; + + for (int i = 0; i < testCases.length; ++i) { + Locale save = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + logln(""); + logln( i + " Pat in: " + testCases[i]); + MessageFormat form = new MessageFormat(testCases[i]); + logln( i + " Pat out: " + form.toPattern()); + String result = form.format(testArgs); + logln( i + " Result: " + result); + Object[] values = form.parse(result); + for (int j = 0; j < testArgs.length; ++j) { + Object testArg = testArgs[j]; + Object value = null; + if (j < values.length) { + value = values[j]; + } + if ((testArg == null && value != null) + || (testArg != null && !testArg.equals(value))) { + logln( i + " " + j + " old: " + testArg); + logln( i + " " + j + " new: " + value); + } + } + } + catch(java.text.ParseException pe ) { + throw new RuntimeException("Error: MessageFormat.parse throws ParseException"); + } + finally{ + Locale.setDefault(save); + } + } + } +} diff --git a/ojluni/src/test/java/text/Format/MessageFormat/bug4492719.java b/ojluni/src/test/java/text/Format/MessageFormat/bug4492719.java new file mode 100644 index 00000000000..929737da906 --- /dev/null +++ b/ojluni/src/test/java/text/Format/MessageFormat/bug4492719.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2001, 2016, 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 4492719 + * @library /java/text/testlib + * @summary Confirm that Message.parse() interprets time zone which uses "GMT+/-" format correctly and doesn't throw ParseException. + */ + +package test.java.text.Format.MessageFormat; + +import java.util.*; +import java.text.*; + +import test.java.text.testlib.IntlTest; + +public class bug4492719 extends IntlTest { + + public static void main(String[] args) throws Exception { + Locale savedLocale = Locale.getDefault(); + TimeZone savedTimeZone = TimeZone.getDefault(); + MessageFormat mf; + boolean err =false; + + String[] formats = { + "short", "medium", "long", "full" + }; + String[] timezones = { + "America/Los_Angeles", "GMT", "GMT+09:00", "GMT-8:00", + "GMT+123", "GMT-1234", "GMT+2", "GMT-13" + }; + String text; + + Locale.setDefault(Locale.US); + + try { + for (int i = 0; i < timezones.length; i++) { + TimeZone.setDefault(TimeZone.getTimeZone(timezones[i])); + + for (int j = 0; j < formats.length; j++) { + mf = new MessageFormat("{0,time," + formats[j] + "} - time"); + text = MessageFormat.format("{0,time," + formats[j] + "} - time", + new Object [] { new Date(123456789012L)}); + Object[] objs = mf.parse(text); + } + } + } catch (ParseException e) { + err = true; + System.err.println("Invalid ParseException occurred : " + + e.getMessage()); + System.err.println(" TimeZone=" + TimeZone.getDefault()); + } + finally { + Locale.setDefault(savedLocale); + TimeZone.setDefault(savedTimeZone); + if (err) { + throw new Exception("MessageFormat.parse(\"GMT format\") failed."); + } + } + } +} diff --git a/ojluni/src/test/java/text/Format/NumberFormat/BigDecimalFormat.java b/ojluni/src/test/java/text/Format/NumberFormat/BigDecimalFormat.java new file mode 100644 index 00000000000..c99f61e4ddb --- /dev/null +++ b/ojluni/src/test/java/text/Format/NumberFormat/BigDecimalFormat.java @@ -0,0 +1,1048 @@ +/* + * Copyright (c) 2003, 2016, 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 4018937 8008577 + * @summary Confirm that methods which are newly added to support BigDecimal and BigInteger work as expected. + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI BigDecimalFormat + */ + +package test.java.text.Format.NumberFormat; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.*; +import java.util.*; + +import test.java.text.testlib.IntlTest; + +public class BigDecimalFormat extends IntlTest { + + public static void main(String[] args) throws Exception { + new BigDecimalFormat().run(args); + } + + static final String nonsep_int = + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890"; + + static final String sep_int = + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890"; + + static final String nonsep_zero = + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000"; + + static final String sep_zero = + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000"; + + static final String fra = + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789"; + + + StringBuffer formatted = new StringBuffer(1000); + FieldPosition fp; + + /** + * Test for normal big numbers which have the fraction part + */ + void test_Format_in_NumberFormat_BigDecimal() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 0.000...789 + // To: 0.000...789 (same as From) + formatted.setLength(0); + from = "0." + nonsep_zero + "123456789"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, from, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...789 + // To: -0.000...789 (same as From) + // ~ : FieldPosition(SIGN) + fp = new FieldPosition(NumberFormat.Field.SIGN); + formatted.setLength(0); + from = "-0." + nonsep_zero + "123456789"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, from, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 0, 1); + + /* ------------------------------------------------------------------ */ + + // From: 1234...7890.012...789 + // To: 123,4...7,890.012...789 + // ~~~~~~~~~~~~~ : FieldPosition(INTEGER_FIELD) + fp = new FieldPosition(DecimalFormat.INTEGER_FIELD); + formatted.setLength(0); + from = nonsep_int + "." + fra; + to = sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 0, 479); + + /* ------------------------------------------------------------------ */ + + // From: -1234...7890.012...789 + // To: -123,4...7,890.012...789 + // ~~~~~~~~~ : FieldPosition(FRACTION_FIELD) + fp = new FieldPosition(DecimalFormat.FRACTION_FIELD); + formatted.setLength(0); + from = "-" + nonsep_int + "." + fra; + to = "-" + sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 481, 841); + + /* ------------------------------------------------------------------ */ + + // From: 1234...78900000...0000.000...789 + // To: 123,4...7,890,000,0...0,000.000...789 + formatted.setLength(0); + from = nonsep_int + nonsep_zero + "." + nonsep_zero + fra; + to = sep_int + "," + sep_zero + "." + nonsep_zero + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000.000...789 + // To: -123,4...7,890,000,0...0,000.000...789 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero + fra; + to = "-" + sep_int + "," + sep_zero + "." + nonsep_zero + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1234...78900000...0000 + // To: 123,4...7,890,000,0...0,000 + formatted.setLength(0); + from = nonsep_int + nonsep_zero; + to = sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000 + // To: -123,4...7,890,000,0...0,000 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero; + to = "-" + sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1234...78900000...0000.0...0 + // To: 1,234...7,890,000,0...0,000 + formatted.setLength(0); + from = nonsep_int + nonsep_zero + "." + nonsep_zero; + to = sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000.0...0 + // To: -1,234...7,890,000,0...0,000 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero; + to = "-" + sep_int + "," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 000...0000 + // To: 0 + formatted.setLength(0); + from = nonsep_zero; + to = "0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -000...0000 + // To: 0 + formatted.setLength(0); + from = "-" + nonsep_zero; + to = "0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 000...00001234 + // To: 1,234 + formatted.setLength(0); + from = nonsep_zero + "1234"; + to = "1,234"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -000...00001234 + // To: -1,234 + // ~ : FieldPosition(GROUPING_SEPARATOR) + fp = new FieldPosition(NumberFormat.Field.GROUPING_SEPARATOR); + formatted.setLength(0); + from = "-" + nonsep_zero + "1234"; + to = "-1,234"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 2, 3); + + /* ------------------------------------------------------------------ */ + + // From: 000...0000.0...0 + // To: 0 + formatted.setLength(0); + from = nonsep_zero + "." + nonsep_zero; + to = "0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.0"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 1); + + // From: -000...0000.0...0 + // To: 0.0 + formatted.setLength(0); + from = "-" + nonsep_zero + "." + nonsep_zero; + to = "0.0"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1234...7890.012...7890...0 + // To: 1,234...7,890.0123...789 + formatted.setLength(0); + from = nonsep_int + "." + fra + nonsep_zero; + to = sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...7890.012...7890...0 + // To: -1,234...7,890.0123...789 + formatted.setLength(0); + from = "-" + nonsep_int + "." + fra + nonsep_zero; + to = "-" + sep_int + "." + fra; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 0); + + // From: 1123...890.012...789 + // To : 1.123...8900123...789E360 + // ~~~ : FieldPosition(EXPONENT) + fp = new FieldPosition(NumberFormat.Field.EXPONENT); + formatted.setLength(0); + from = "1" + nonsep_int + "." + fra; + to = "1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 723, 726); + + /* ------------------------------------------------------------------ */ + + // From: -1123...890.012...789 + // To : -1.123...8900123...789E360 + formatted.setLength(0); + from = "-1" + nonsep_int + "." + fra; + to = "-1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 0); + + // From: 0.000...0001123...890.012...789 + // To : 1.123...8900123...789E-360 + formatted.setLength(0); + from = "0." + nonsep_zero + "1" + fra; + to = "1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...0001123...890.012...789 + // To : -1.123...8900123...789E-360 + formatted.setLength(0); + from = "-0." + nonsep_zero + "1" + fra; + to = "-1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: 1123...890.012...789000...000 + // To : 1.123...8900123...789E360 + formatted.setLength(0); + from = "1" + nonsep_int + "." + fra + nonsep_zero; + to = "1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1123...890.012...789000...000 + // To : -1.123...8900123...789E360 + // ~ : FieldPosition(EXPONENT_SYMBOL) + fp = new FieldPosition(NumberFormat.Field.EXPONENT_SYMBOL); + formatted.setLength(0); + from = "-1" + nonsep_int + "." + fra + nonsep_zero; + to = "-1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 723, 724); + + /* ------------------------------------------------------------------ */ + + // From: 0.000...0001123...890.012...789000...000 + // To : 1.123...8900123...789E-360 + // ~ : FieldPosition(EXPONENT_SIGN) + fp = new FieldPosition(NumberFormat.Field.EXPONENT_SIGN); + formatted.setLength(0); + from = "0." + nonsep_zero + "1" + fra + nonsep_zero; + to = "1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 363, 364); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...0001123...890.012...789000...000 + // To : -1.123...8900123...789E-360 + formatted.setLength(0); + from = "-0." + nonsep_zero + "1" + fra + nonsep_zero; + to = "-1." + fra + "E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: ABC1123...890.012...789 + // To : ABC1.123...890.0123...789 + formatted = new StringBuffer("ABC"); + from = "1" + nonsep_int + "." + fra; + to = "ABC1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: ABC-1123...890.012...789 + // To : ABC-1.123...890.0123...789 + // ~ : FieldPosition(DECIMAL_SEPARATOR) + fp = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR); + formatted = new StringBuffer("ABC"); + from = "-1" + nonsep_int + "." + fra; + to = "ABC-1." + nonsep_int + fra + "E360"; + nf.format(new BigDecimal(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 5, 6); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, 726, 0); + + // From: 0.000...000012...7890123456789 + // To: 0.000...000012...789012346 (Shorter than From) + formatted.setLength(0); + from = "0." + nonsep_zero + fra + fra; + to = "0." + nonsep_zero + fra + "012346"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, 723, 0); + + /* ------------------------------------------------------------------ */ + + // From: -0.000...000012...7890123456789 + // To: -0.000...000012...789012 (Shorter than From) + formatted.setLength(0); + from = "-0." + nonsep_zero + fra + fra; + to = "-0." + nonsep_zero + fra + "012"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("00000.###E0"); + setDigits(nf, 5, 5, 370, 0); + + // From: 1234567890.012...78901234567890 + // To: 12345.67890012...789012346E5 + formatted.setLength(0); + from = "1234567890." + fra + "0123456789"; + to = "12345.67890" + fra + "01235E5"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, 364, 0); + + // From: -0.000...0001012...7890123456789 + // To: -1.012...789012E-361 + formatted.setLength(0); + from = "-0." + nonsep_zero + "1" + fra + "0123456789"; + to = "-1." + fra + "0123E-361"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, 366, 0); + + // From: 1012...78901234567890 + // To: 1.012...789012346E370 + formatted.setLength(0); + from = "1" + fra + "0123456789"; + to = "1." + fra + "012346E370"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, 363, 0); + + // From: -1012...7890123456789 + // To: -1.012...789012E370 + formatted.setLength(0); + from = "-1" + fra + "0123456789"; + to = "-1." + fra + "012E370"; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 720); + + // From: 1234...78900000...0000.0...0 + // To: 1,234...7,890,000,0...0,000.0...0 + formatted.setLength(0); + from = nonsep_int + nonsep_zero + "." + nonsep_zero + nonsep_zero; + to = sep_int + "," + sep_zero + "." + nonsep_zero + nonsep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...78900000...0000.0...0 + // To: -1,234...7,890,000,0...0,000.0...0 + formatted.setLength(0); + from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero + nonsep_zero; + to = "-" + sep_int + "," + sep_zero + "." + nonsep_zero + nonsep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal big numbers which have the fraction part with multiplier + */ + void test_Format_in_NumberFormat_BigDecimal_usingMultiplier() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + ((DecimalFormat)nf).setMultiplier(250000000); + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(true); + + // From: 1000...0000.000...000 + // To: 250,0...0,000. + formatted.setLength(0); + from = "1" + nonsep_zero + "." + nonsep_zero; + to = "250,000,000," + sep_zero + "."; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(false); + + // From: -1000...0000.000...000 + // To: -250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero + "." + nonsep_zero; + to = "-250,000,000," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + ((DecimalFormat)nf).setMultiplier(-250000000); + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(true); + + // From: 1000...0000.000...000 + // To: -250,0...0,000. + formatted.setLength(0); + from = "1" + nonsep_zero + "." + nonsep_zero; + to = "-250,000,000," + sep_zero + "."; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(false); + + // From: -1000...0000.000...000 + // To: 250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero + "." + nonsep_zero; + to = "250,000,000," + sep_zero; + nf.format(new BigDecimal(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal big numbers which don't have the fraction part + */ + void test_Format_in_NumberFormat_BigInteger() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 1234...7890 + // To: 123,4...7,890 + formatted.setLength(0); + from = nonsep_int; + to = sep_int; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1234...7890 + // To: -123,4...7,890 + // ~~~~~~~~~~~~~ : FieldPosition(INTEGER_FIELD) + fp = new FieldPosition(DecimalFormat.INTEGER_FIELD); + formatted.setLength(0); + from = "-" + nonsep_int; + to = "-" + sep_int; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 1, 480); + + /* ------------------------------------------------------------------ */ + + // From: 000...0001234...7890 + // To: 123,4...7,890 + formatted.setLength(0); + from = nonsep_zero + nonsep_int; + to = sep_int; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -000...0001234...7890 + // To: -123,4...7,890 + // ~ : FieldPosition(SIGN) + fp = new FieldPosition(NumberFormat.Field.SIGN); + formatted.setLength(0); + from = "-" + nonsep_zero + nonsep_int; + to = "-" + sep_int; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 0, 1); + + /* ------------------------------------------------------------------ */ + + // From: 000...0000 + // To: 0 + formatted.setLength(0); + from = nonsep_zero; + to = "0"; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.0"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 1); + + // From: -000...0000 + // To: 0.0 + fp = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR); + formatted.setLength(0); + from = "-" + nonsep_zero; + to = "0.0"; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 1, 2); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 0); + + // From: 10123...789 + // To : 1.0123...789E360 + // ~~~ : FieldPosition(EXPONENT) + fp = new FieldPosition(NumberFormat.Field.EXPONENT); + formatted.setLength(0); + from = "1" + fra; + to = "1." + fra + "E360"; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 363, 366); + + /* ------------------------------------------------------------------ */ + + // From: -1012...789 + // To : -1.012...789E360 + formatted.setLength(0); + from = "-1" + fra; + to = "-1." + fra + "E360"; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("00000.###E0"); + setDigits(nf, 5, 5, Integer.MAX_VALUE, 720); + + // From: 12345012...789000...000 + // To : 12345.012...789000...000E720 + // ~~~ : FieldPosition(EXPONENT) + fp = new FieldPosition(NumberFormat.Field.EXPONENT); + formatted.setLength(0); + from = "12345" + fra + nonsep_zero; + to = "12345." + fra + nonsep_zero + "E720"; + nf.format(new BigInteger(from), formatted, fp); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + checkFieldPosition(from, fp, 727, 730); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("00000.###E0"); + setDigits(nf, 5, 5, Integer.MAX_VALUE, 365); + + // From: -1234567890012...789000...000 + // To : -12345.67890012...789E365 + formatted.setLength(0); + from = "-1234567890" + fra; + to = "-12345.67890" + fra + "E365"; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal big numbers which don't have the fraction part with + * multiplier + */ + void test_Format_in_NumberFormat_BigInteger_usingMultiplier() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(250000000); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 1000...0000 + // To: 250,0...0,000 + formatted.setLength(0); + from = "1" + nonsep_zero; + to = "250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1000...0000 + // To: -250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero; + to = "-250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(-250000000); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + // From: 1000...0000 + // To: -250,0...0,000 + formatted.setLength(0); + from = "1" + nonsep_zero; + to = "-250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + // From: -1000...0000 + // To: 250,0...0,000 + formatted.setLength(0); + from = "-1" + nonsep_zero; + to = "250,000,000," + sep_zero; + nf.format(new BigInteger(from), formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for normal Long numbers when maximum and minimum digits are + * specified + */ + void test_Format_in_NumberFormat_Long_checkDigits() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 0); + + // From: 1234567890 + // To: 000,0...0,000,123,456,789 + // ------------- + // 300 zeros + formatted.setLength(0); + from = "123456789"; + to = sep_zero.substring(0, 399) + ",123,456,789"; + nf.format(123456789L, formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("##0.###"); + ((DecimalFormat)nf).setMultiplier(-1); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360); + + // From: 1234567890 + // To: -0000...0000123456789.000...000 + // ------------- + // 300 zeros + formatted.setLength(0); + from = "123456789"; + to = "-" + nonsep_zero.substring(0, 300) + "123456789." + + nonsep_zero.substring(0, 340); + nf.format(123456789L, formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(Integer.MAX_VALUE); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 0); + + // From: Long.MAX_VALUE + // To: 000,0...0,000,019,807,040,619,342,712,359,383,728,129 + // --------------- + // 280 zeros + formatted.setLength(0); + from = Long.toString(Long.MAX_VALUE); + to = sep_zero.substring(0, 373) + + "19,807,040,619,342,712,359,383,728,129"; + nf.format(Long.MAX_VALUE, formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("0.###E0"); + ((DecimalFormat)nf).setMultiplier(Integer.MIN_VALUE); + setDigits(nf, 1, 1, Integer.MAX_VALUE, 360); + + // From: Long.MAX_VALUE + // To: -1.9807040628566084396238503936000...000E28 + // --------- + // 312 zeros + formatted.setLength(0); + from = Long.toString(Long.MAX_VALUE); + to = "-1.9807040628566084396238503936" + + nonsep_zero.substring(0, 312) + "E28"; + nf.format(Long.MAX_VALUE, formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("##0.###E0"); + ((DecimalFormat)nf).setMultiplier(Integer.MAX_VALUE); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360); + + // From: Long.MIN_VALUE + // To: -198070406193427123615312117760000...0000.000...000E-280 + // ----------- --------- + // 280 zeros 340 zeros + formatted.setLength(0); + from = Long.toString(Long.MIN_VALUE); + to = "-19807040619342712361531211776" + + nonsep_zero.substring(0, 280) + "." + + nonsep_zero.substring(0, 340) + "E-280"; + nf.format(Long.MIN_VALUE, formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + + /* ------------------------------------------------------------------ */ + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + ((DecimalFormat)nf).setMultiplier(Integer.MIN_VALUE); + setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360); + + // From: Long.MIN_VALUE + // To: 000,0...0,000,019,807,040,628,566,084,398,385,987,584.000...000 + // --------------- --------- + // 280 zeros 340 zeros + formatted.setLength(0); + from = Long.toString(Long.MIN_VALUE); + to = sep_zero.substring(0, 373) + + "19,807,040,628,566,084,398,385,987,584." + + nonsep_zero.substring(0, 340); + nf.format(Long.MIN_VALUE, formatted, new FieldPosition(0)); + checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier()); + } + + /** + * Test for special numbers + * Double.NaN + * Double.POSITIVE_INFINITY + * Double.NEGATIVE_INFINITY + */ + void test_Format_in_NumberFormat_SpecialNumber() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + ((DecimalFormat)nf).applyPattern("#,##0.###"); + setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0); + + double[] numbers = { + -0.0, 0.0, Double.NaN, + Double.POSITIVE_INFINITY, 5.1, 5.0, + Double.NEGATIVE_INFINITY, -5.1, -5.0, + }; + int multipliers[] = {0, 5, -5}; + String[][] expected = { + {"-0", "0", "\ufffd", "\ufffd", "0", "0", "\ufffd", "-0", "-0"}, + {"-0", "0", "\ufffd", "\u221e", "25.5", "25", "-\u221e", "-25.5", + "-25"}, + {"0", "-0", "\ufffd", "-\u221e", "-25.5", "-25", "\u221e", "25.5", + "25"}, + }; + + for (int i = 0; i < multipliers.length; i++) { + ((DecimalFormat)nf).setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + formatted.setLength(0); + from = String.valueOf(numbers[j]); + nf.format(numbers[j], formatted, new FieldPosition(0)); + checkFormat(from, formatted, expected[i][j], + ((DecimalFormat)nf).getMultiplier()); + } + } + } + + /** + * Test for Long.MIN_VALUE + * (Formatting Long.MIN_VALUE w/ multiplier=-1 used to return a wrong + * number.) + */ + void test_Format_in_NumberFormat_Other() { + String from, to; + + NumberFormat nf = NumberFormat.getInstance(Locale.US); + if (!(nf instanceof DecimalFormat)) { + throw new RuntimeException("Couldn't get DecimalFormat instance."); + } + + long[] numbers = { + Long.MIN_VALUE, + }; + int multipliers[] = {1, -1}; + String[][] expected = { + {"-9,223,372,036,854,775,808"}, // Long.MIN_VALUE + {"9,223,372,036,854,775,808"}, // Long.MIN_VALUE * (-1) + }; + + for (int i = 0; i < multipliers.length; i++) { + ((DecimalFormat)nf).setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + formatted.setLength(0); + from = String.valueOf(numbers[j]); + nf.format(numbers[j], formatted, new FieldPosition(0)); + checkFormat(from, formatted, expected[i][j], + ((DecimalFormat)nf).getMultiplier()); + } + } + } + + /** + * Test for MessageFormat + */ + void test_Format_in_MessageFormat() { + MessageFormat mf = new MessageFormat( + " {0, number}\n" + + " {0, number, integer}\n" + + " {0, number, currency}\n" + + " {0, number, percent}\n" + + " {0, number,0.###########E0}\n" + + + " {1, number}\n" + + " {1, number, integer}\n" + + " {1, number, currency}\n" + + " {1, number, percent}\n" + + " {1, number,0.#######E0}\n", + Locale.US + ); + Object[] testArgs = { + new BigInteger("9876543210987654321098765432109876543210"), + new BigDecimal("-12345678901234567890.98765432109876543210987654321"), + }; + String expected = + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210\n" + + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210\n" + + " $9,876,543,210,987,654,321,098,765,432,109,876,543,210.00\n" + + " 987,654,321,098,765,432,109,876,543,210,987,654,321,000%\n" + + " 9.87654321099E39\n" + + + " -12,345,678,901,234,567,890.988\n" + + " -12,345,678,901,234,567,891\n" + + " ($12,345,678,901,234,567,890.99)\n" + + " -1,234,567,890,123,456,789,099%\n" + + " -1.2345679E19\n" + ; + + if (!expected.equals(mf.format(testArgs))) { + errln("Wrong format.\n got:\n" + mf.format(testArgs) + + " expected:\n" + expected); + } + } + + private void setDigits(NumberFormat nf, + int i_max, int i_min, int f_max, int f_min) { + nf.setMaximumIntegerDigits(i_max); + nf.setMinimumIntegerDigits(i_min); + nf.setMaximumFractionDigits(f_max); + nf.setMinimumFractionDigits(f_min); + } + + private void checkFormat(String orig, StringBuffer got, String expected, + int multiplier) { + if (!expected.equals(new String(got))) { + errln("Formatting... failed." + + "\n original: " + orig + + "\n multiplier: " + multiplier + + "\n formatted: " + got + + "\n expected: " + expected + "\n"); + } + } + + private void checkFieldPosition(String orig, FieldPosition fp, int begin, + int end) { + int position; + + if ((position = fp.getBeginIndex()) != begin) { + errln("Formatting... wrong Begin index returned for " + + fp.getFieldAttribute() + "." + + "\n original: " + orig + + "\n got: " + position + + "\n expected: " + begin + "\n"); + } + if ((position = fp.getEndIndex()) != end) { + errln("Formatting... wrong End index returned for " + + fp.getFieldAttribute() + "." + + "\n original: " + orig + + "\n got: " + position + + "\n expected: " + end + "\n"); + } + } +} diff --git a/ojluni/src/test/java/text/Format/NumberFormat/BigDecimalParse.java b/ojluni/src/test/java/text/Format/NumberFormat/BigDecimalParse.java new file mode 100644 index 00000000000..388ed97078b --- /dev/null +++ b/ojluni/src/test/java/text/Format/NumberFormat/BigDecimalParse.java @@ -0,0 +1,713 @@ +/* + * Copyright (c) 2003, 2016, 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 4018937 8008577 + * @summary Confirm that methods which are newly added to support BigDecimal and BigInteger work as expected. + * @library /java/text/testlib + * @run main/othervm -Djava.locale.providers=COMPAT,SPI BigDecimalParse + */ + +package test.java.text.Format.NumberFormat; + +import java.math.BigDecimal; +import java.text.*; +import java.util.*; + +import test.java.text.testlib.IntlTest; + +public class BigDecimalParse extends IntlTest { + + public static void main(String[] args) throws Exception { + Locale loc = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + new BigDecimalParse().run(args); + } finally { + // restore the reserved locale + Locale.setDefault(loc); + } + } + + static final String nonsep_int = + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890"; + + static final String sep_int = + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890," + + "123,456,789,012,345,678,901,234,567,890"; + + static final String nonsep_zero = + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000"; + + static final String sep_zero = + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000," + + "000,000,000,000,000,000,000,000,000,000"; + + static final String fra = + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678901234567890123456789"; + + + Number parsed = null; + ParsePosition pp; + boolean exceptionOccurred; + String msg; + DecimalFormat df; + + /** + * Test for normal big numbers which have the fraction part + */ + void test_Parse_in_DecimalFormat_BigDecimal() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 1234...7890.012...789 + // To: BigDecimal 1234...7890.012...789 + check(nonsep_int + "." + fra, new BigDecimal(nonsep_int + "." + fra)); + + // From: -1,234...7,890.012...789 + // To: BigDecimal -1234...7890.012...789 + check("-" + sep_int + "." + fra, + new BigDecimal("-" + nonsep_int + "." + fra)); + + // From: 000...0000.0...0 + // To: BigDecimal 0E-360 + check(nonsep_zero + "." + nonsep_zero, + new BigDecimal(nonsep_zero + "." + nonsep_zero)); + + // From: 0.000...0000123...789E370 + // To: BigDecimal 0.0123...789 + check("0.0000000000" + nonsep_zero + fra + "E370", + new BigDecimal("0.0000000000" + nonsep_zero + fra + "E370")); + + // From: 0.1123...890E-360 + // To: BigDecimal 1.123...890E-361 + check("0.1" + nonsep_int + "E-360", + new BigDecimal("0.1" + nonsep_int + "E-360")); + + // From: 000...0000.0...0123...7890 + // To: BigDecimal 1.234...890E-361 + check(nonsep_zero + "." + nonsep_zero + nonsep_int, + new BigDecimal(nonsep_zero + "." + nonsep_zero + nonsep_int)); + + // From: 0.123...890E360 + // To: BigDecimal 123...890 + check("0." + nonsep_int + "E360", + new BigDecimal("0." + nonsep_int + "E360")); + } + + /** + * Test for normal big numbers which have the fraction part with multiplier + */ + void test_Parse_in_DecimalFormat_BigDecimal_usingMultiplier() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 250,0...0,000.000...000 + // To: 1000...0000.000...000 + df.setMultiplier(250000000); + check("250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("1" + nonsep_zero + "." + nonsep_zero)); + + // From: -250,0...0,000.000...000 + // To: -1000...0000.000...000 + check("-250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero)); + + // From: 250,0...0,000.000...000 + // To: -1000...0000.000...000 + df.setMultiplier(-250000000); + check("250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero)); + + // From: -250,0...0,000.000...000 + // To: 1000...0000.000...000 + check("-250,000,000," + sep_zero + "." + nonsep_zero, + new BigDecimal("1" + nonsep_zero + "." + nonsep_zero)); + + // Confirm that ArithmeticException is handled properly + // From: 1000.000 + // To: 333.333 + df.setMultiplier(3); + check("1000.000", new BigDecimal("333.333")); + + // Confirm that ArithmeticException is handled properly + // From: 10000.0000 + // To: 303.0303 + df.setMultiplier(33); + check("10000.0000", new BigDecimal("303.0303")); + } + + /** + * Test for division by zero (BigDecimal) + */ + void test_Parse_in_DecimalFormat_BigDecimal_DivisionByZero() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + df.setMultiplier(0); + + // From: 1000.000 + // To: Double.POSITIVE_INFINITY + check("1000.000", Double.POSITIVE_INFINITY); + + // From: -1000 + // To: Double.NEGATIVE_INFINITY + check("-1000", Double.NEGATIVE_INFINITY); + + // From: -0.00 + // To: Double.NaN + check("-0.00", Double.NaN); + } + + /** + * Test for division by zero (Double) + */ + void test_Parse_in_DecimalFormat_Double_DivisionByZero() { + df = new DecimalFormat(); + df.setParseBigDecimal(false); + df.setMultiplier(0); + + // From: 1000.000 + // To: Double.POSITIVE_INFINITY + check("1000.000", Double.POSITIVE_INFINITY); + + // From: -1000.000 + // To: Double.NEGATIVE_INFINITY + check("-1000.000", Double.NEGATIVE_INFINITY); + + // From: 0.0 + // To: Double.NaN + check("0.0", Double.NaN); + + // From: -0.0 (Double) + // To: Double.NaN + check("-0.0", Double.NaN); + + // From: Double.NaN + // To: Double.NaN + check("\ufffd", Double.NaN); + + // From: Double.POSITIVE_INFINITY + // To: Double.NaN + check("\u221e", Double.POSITIVE_INFINITY); + + // From: Double.NEGATIVE_INFINITY + // To: Double.NaN + check("-\u221e", Double.NEGATIVE_INFINITY); + } + + /** + * Test for division by zero (Long) + */ + void test_Parse_in_DecimalFormat_Long_DivisionByZero() { + df = new DecimalFormat(); + df.setParseBigDecimal(false); + df.setMultiplier(0); + + // From: 1000 + // To: Double.POSITIVE_INFINITY + check("1000", Double.POSITIVE_INFINITY); + + // From: -1000 + // To: Double.NEGATIVE_INFINITY + check("-1000", Double.NEGATIVE_INFINITY); + + // From: -000 (Long) + // To: Double.NaN + check("-000", Double.NaN); + } + + /** + * Test for normal big numbers which don't have the fraction part + */ + void test_Parse_in_DecimalFormat_BigInteger() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 123...890 + // To: BigDecimal 123...890 + check(nonsep_int + nonsep_int, new BigDecimal(nonsep_int + nonsep_int)); + + // From: 123,4...7,890 + // To: BigDecimal 1234...7890 + check(sep_int + "," + sep_int, new BigDecimal(nonsep_int + nonsep_int)); + + // From: -000...000123...890 + // To: BigDecimal -123...890 + check("-" + nonsep_zero + nonsep_int, new BigDecimal("-" + nonsep_int)); + + // From: -000,0...0,000,123,4...7,890 + // To: BigDecimal -123...890 + check("-" + sep_zero + "," + sep_int, new BigDecimal("-" + nonsep_int)); + } + + /** + * Test for normal big numbers which don't have the fraction part with + * multiplier + */ + void test_Parse_in_DecimalFormat_BigInteger_usingMultiplier() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + // From: 250,0...0,000 + // To: 1000...0000 + df.setMultiplier(250000000); + check("250,000,000," + sep_zero, new BigDecimal("1" + nonsep_zero)); + + // From: -250,0...0,000 + // To: -1000...0000 + check("-250,000,000," + sep_zero, new BigDecimal("-1" + nonsep_zero)); + + // From: 250,0...0,000 + // To: -1000...0000 + df.setMultiplier(-250000000); + check("250,000,000," + sep_zero, new BigDecimal("-1" + nonsep_zero)); + + // From: -250,0...0,000 + // To: 1000...0000 + check("-250,000,000," + sep_zero, new BigDecimal("1" + nonsep_zero)); + + // From: 250,0...0,000E-360 + // To: -1000...0000.000...000 + check("250,000,000," + sep_zero + "," + sep_zero + "E-360", + new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero)); + + // Confirm that a division which results in a irrational number is done + // properly + // From: 1000 + // To: 333 + df.setMultiplier(3); + check("1000", new BigDecimal("333")); + } + + /** + * Test for special numbers + * Double.NaN + * Double.POSITIVE_INFINITY + * Double.NEGATIVE_INFINITY + */ + void test_Parse_in_DecimalFormat_SpecialNumber() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + String[] numbers = { + "0", "0.0", "25", "25.0", "25.5", "\u221e", "\ufffd", + "-0", "-0.0", "-25", "-25.0", "-25.5", "-\u221e", + }; + int multipliers[] = {5, -5}; + Number[][] expected = { + { + new BigDecimal("0"), new BigDecimal("0.0"), new BigDecimal("5"), + new BigDecimal("5.0"), new BigDecimal("5.1"), + Double.POSITIVE_INFINITY, Double.NaN, + new BigDecimal("0"), new BigDecimal("0.0"), + new BigDecimal("-5"), new BigDecimal("-5.0"), + new BigDecimal("-5.1"), + Double.NEGATIVE_INFINITY, Double.NaN, + }, + { + new BigDecimal("0"), new BigDecimal("0.0"), + new BigDecimal("-5"), new BigDecimal("-5.0"), + new BigDecimal("-5.1"), + Double.NEGATIVE_INFINITY, Double.NaN, + new BigDecimal("0"), new BigDecimal("0.0"), new BigDecimal("5"), + new BigDecimal("5.0"), new BigDecimal("5.1"), + Double.POSITIVE_INFINITY, + }, + }; + + for (int i = 0; i < multipliers.length; i++) { + df.setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + check(String.valueOf(numbers[j]), expected[i][j]); + } + } + } + + /** + * Test for special numbers + */ + void test_Parse_in_DecimalFormat_Other() { + df = new DecimalFormat(); + df.setParseBigDecimal(true); + + String[] numbers = { + "-9223372036854775808", // Long.MIN_VALUE + }; + int multipliers[] = {1, -1}; + String[][] expected = { + {"-9223372036854775808"}, // Long.MIN_VALUE + {"9223372036854775808"}, // Long.MAX_VALUE+1 = abs(MIN_VALUE) + }; + + for (int i = 0; i < multipliers.length; i++) { + df.setMultiplier(multipliers[i]); + for (int j = 0; j < numbers.length; j++) { + check(String.valueOf(numbers[j]), + new BigDecimal(expected[i][j])); + } + } + } + + static final String[] patterns = { + " {0, number} ", + " {0, number} ", + " {0, number, currency} ", + " {0, number, currency} ", + " {0, number, percent} ", + " {0, number, percent} ", + " {0, number,#,##0.###E0} ", + " {0, number,#,##0.###E0} ", + + " {0, number} ", + " {0, number} ", + " {0, number, integer} ", + " {0, number, integer} ", + " {0, number, currency} ", + " {0, number, currency} ", + " {0, number, percent} ", + " {0, number, percent} ", + " {0, number,#,##0.###E0} ", + " {0, number,#,##0.###E0} ", + }; + static final String[] from = { + " 12,345,678,901,234,567,890.98765432109876543210987654321 ", + " -12,345,678,901,234,567,890.98765432109876543210987654321 ", + " $12,345,678,901,234,567,890.98765432109876543210987654321 ", + " ($12,345,678,901,234,567,890.98765432109876543210987654321) ", + " 1,234,567,890,123,456,789,098.76543210987654321098765432100% ", + " -1,234,567,890,123,456,789,098.76543210987654321098765432100% ", + " 12,345,678,901,234,567,890.98765432109876543210987654321E-20 ", + " -12,345,678,901,234,567,890.98765432109876543210987654321E-20 ", + + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210 ", + " -9,876,543,210,987,654,321,098,765,432,109,876,543,210 ", + " 9,876,543,210,987,654,321,098,765,432,109,876,543,210E5 ", + " -9,876,543,210,987,654,321,098,765,432,109,876,543,210E-5 ", + " $9,876,543,210,987,654,321,098,765,432,109,876,543,210.00 ", + " ($9,876,543,210,987,654,321,098,765,432,109,876,543,210.00) ", + " 987,654,321,098,765,432,109,876,543,210,987,654,321,012% ", + " -987,654,321,098,765,432,109,876,543,210,987,654,321,012% ", + " 98,765,432,109,876,543,210.98765432109876543210E20 ", + " -987,654,321,098,765,432,109,876,543,210,987,654,321,000,000,000,000,000,000,000E-20 ", + }; + + static final String[] expected1 = { // isParseIntegerOnly() == false + "12345678901234567890.98765432109876543210987654321", + "-12345678901234567890.98765432109876543210987654321", + "12345678901234567890.98765432109876543210987654321", + "-12345678901234567890.98765432109876543210987654321", + "12345678901234567890.98765432109876543210987654321", + "-12345678901234567890.98765432109876543210987654321", + "0.1234567890123456789098765432109876543210987654321", + "-0.1234567890123456789098765432109876543210987654321", + + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "9.876543210987654321098765432109876543210E44", + "-98765432109876543210987654321098765.43210", + "9876543210987654321098765432109876543210.00", + "-9876543210987654321098765432109876543210.00", + "9876543210987654321098765432109876543210.12", + "-9876543210987654321098765432109876543210.12", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210.00000000000000000000", + }; + static final int[] parsePosition1 = { + 60, 61, 61, 63, 64, 65, 64, 65, + 57, 58, 59, 61, 61, 63, 60, 61, 54, 88, + }; + + /** + * Test for MessageFormat: setParseIntegerOnly(false) + */ + void test_Parse_in_MessageFormat_NotParseIntegerOnly() { + for (int i=0; i < patterns.length; i++) { + pp = new ParsePosition(0); + Object[] parsed = null; + + try { + MessageFormat mf = new MessageFormat(patterns[i]); + Format[] formats = mf.getFormats(); + for (int j=0; j < formats.length; j++) { + ((DecimalFormat)formats[j]).setParseBigDecimal(true); + } + + parsed = mf.parse(from[i], pp); + + if (pp.getErrorIndex() != -1) { + errln("Case" + (i+1) + + ": getErrorIndex() returns wrong value. expected:-1, got:"+ + pp.getErrorIndex() + " for " + from[i]); + } + if (pp.getIndex() != parsePosition1[i]) { + errln("Case" + (i+1) + + ": getIndex() returns wrong value. expected:" + + parsePosition1[i] + ", got:"+ pp.getIndex() + + " for " + from[i]); + } + } + catch(Exception e) { + errln("Unexpected exception: " + e.getMessage()); + } + + checkType(from[i], getType(new BigDecimal(expected1[i])), + getType((Number)parsed[0])); + checkParse(from[i], new BigDecimal(expected1[i]), + (Number)parsed[0]); + } + } + + static final String[] expected2 = { // isParseIntegerOnly() == true + "12345678901234567890", + "-12345678901234567890", + "12345678901234567890", + "-12345678901234567890", + "12345678901234567890", + "-12345678901234567890", + "0", + "0", + + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "9.876543210987654321098765432109876543210E44", + "-98765432109876543210987654321098765.43210", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "9876543210987654321098765432109876543210.12", + "-9876543210987654321098765432109876543210.12", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210.00000000000000000000", + }; + static final int[][] parsePosition2 = { // {errorIndex, index} + /* + * Should keep in mind that the expected result is different from + * DecimalFormat.parse() for some cases. + */ + {28, 0}, // parsing stopped at '.' + {29, 0}, // parsing stopped at '.' + {29, 0}, // parsing stopped at '.' + {2, 0}, // parsing stopped at '(' because cannot find ')' + {2, 0}, // parsing stopped at the first numeric + // because cannot find '%' + {2, 0}, // parsing stopped at the first numeric + // because cannot find '%' + {28, 0}, // parsing stopped at '.' + {29, 0}, // parsing stopped at '.' + + {-1, 57}, {-1, 58}, {-1, 59}, {-1, 61}, + {56, 0}, // parsing stopped at '.' + // because cannot find '%' + {2, 0}, // parsing stopped at '(' because cannot find ')' + {-1, 60}, {-1, 61}, + {28, 0}, // parsing stopped at '.' + {-1, 88}, + }; + + /** + * Test for MessageFormat: setParseIntegerOnly(true) + */ + void test_Parse_in_MessageFormat_ParseIntegerOnly() { + for (int i=0; i < patterns.length; i++) { + pp = new ParsePosition(0); + Object[] parsed = null; + + try { + MessageFormat mf = new MessageFormat(patterns[i]); + Format[] formats = mf.getFormats(); + for (int j=0; j < formats.length; j++) { + ((DecimalFormat)formats[j]).setParseBigDecimal(true); + ((DecimalFormat)formats[j]).setParseIntegerOnly(true); + } + + parsed = mf.parse(from[i], pp); + + if (pp.getErrorIndex() != parsePosition2[i][0]) { + errln("Case" + (i+1) + + ": getErrorIndex() returns wrong value. expected:" + + parsePosition2[i][0] + ", got:"+ pp.getErrorIndex() + + " for " + from[i]); + } + if (pp.getIndex() != parsePosition2[i][1]) { + errln("Case" + (i+1) + + ": getIndex() returns wrong value. expected:" + + parsePosition2[i][1] + ", got:"+ pp.getIndex() + + " for " + from[i]); + } + } + catch(Exception e) { + errln("Unexpected exception: " + e.getMessage()); + } + + if (parsePosition2[i][0] == -1) { + checkType(from[i], getType(new BigDecimal(expected2[i])), + getType((Number)parsed[0])); + checkParse(from[i], new BigDecimal(expected2[i]), + (Number)parsed[0]); + } + } + } + + static final String[] from3 = { + "12,345,678,901,234,567,890.98765432109876543210987654321", + "-12,345,678,901,234,567,890.98765432109876543210987654321", + "9,876,543,210,987,654,321,098,765,432,109,876,543,210", + "-9,876,543,210,987,654,321,098,765,432,109,876,543,210", + "1234556790000E-8", + }; + static final String[] expected3 = { + "12345678901234567890", + "-12345678901234567890", + "9876543210987654321098765432109876543210", + "-9876543210987654321098765432109876543210", + "12345.56790000", + }; + static final int[][] parsePosition3 = { // {errorIndex, index} + {-1, 26}, + {-1, 27}, + {-1, 53}, + {-1, 54}, + {-1, 16}, + }; + + /** + * Test for DecimalFormat: setParseIntegerOnly(true) + */ + void test_Parse_in_DecimalFormat_ParseIntegerOnly() { + DecimalFormat df = (DecimalFormat)NumberFormat.getIntegerInstance(); + df.setParseBigDecimal(true); + + for (int i=0; i < from3.length; i++) { + pp = new ParsePosition(0); + Number parsed = null; + + try { + parsed = df.parse(from3[i], pp); + + if (pp.getErrorIndex() != parsePosition3[i][0]) { + errln("Case" + (i+1) + + ": getErrorIndex() returns wrong value. expected:" + + parsePosition3[i][0] + ", got:"+ pp.getErrorIndex() + + " for " + from3[i]); + } + if (pp.getIndex() != parsePosition3[i][1]) { + errln("Case" + (i+1) + + ": getIndex() returns wrong value. expected:" + + parsePosition3[i][1] + ", got:"+ pp.getIndex() + + " for " + from3[i]); + } + } + catch(Exception e) { + errln("Unexpected exception: " + e.getMessage()); + } + + if (parsePosition3[i][0] == -1) { + checkType(from3[i], getType(new BigDecimal(expected3[i])), + getType(parsed)); + checkParse(from3[i], new BigDecimal(expected3[i]), parsed); + } + } + } + + protected void check(String from, Number to) { + pp = new ParsePosition(0); + try { + parsed = df.parse(from, pp); + } + catch(Exception e) { + exceptionOccurred = true; + errln(e.getMessage()); + } + if (!exceptionOccurred) { + checkParse(from, to, parsed); + checkType(from, getType(to), getType(parsed)); + checkParsePosition(from, from.length(), pp.getIndex()); + } + } + + private void checkParse(String orig, Number expected, Number got) { + if (!expected.equals(got)) { + errln("Parsing... failed." + + "\n original: " + orig + + "\n parsed: " + got + + "\n expected: " + expected + "\n"); + } + } + + private void checkType(String orig, String expected, String got) { + if (!expected.equals(got)) { + errln("Parsing... unexpected Class returned." + + "\n original: " + orig + + "\n got: " + got + + "\n expected: " + expected + "\n"); + } + } + + private void checkParsePosition(String orig, int expected, int got) { + if (expected != got) { + errln("Parsing... wrong ParsePosition returned." + + "\n original: " + orig + + "\n got: " + got + + "\n expected: " + expected + "\n"); + } + } + + private String getType(Number number) { + return number.getClass().getName(); + } +} diff --git a/ojluni/src/test/java/text/Format/NumberFormat/DFSDeserialization142.java b/ojluni/src/test/java/text/Format/NumberFormat/DFSDeserialization142.java new file mode 100644 index 00000000000..ef69d84ad09 --- /dev/null +++ b/ojluni/src/test/java/text/Format/NumberFormat/DFSDeserialization142.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2005, 2016, 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. + */ + +/* + * No at-test for this test, because it needs to be run on older version JDK than 1.6 to test. + * It was tested using 1.4.2. The file object was created using JDK1.6. + */ + +package test.java.text.Format.NumberFormat; + +import java.text.*; +import java.util.*; +import java.io.*; + +public class DFSDeserialization142{ + + public static void main(String[] args) + { + try { + + File file = new File("DecimalFormatSymbols.current"); + FileInputStream istream = new FileInputStream(file); + ObjectInputStream p = new ObjectInputStream(istream); + DecimalFormatSymbols dfs = (DecimalFormatSymbols)p.readObject(); + if (dfs.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){ + System.out.println("Serialization/Deserialization Test Passed."); + }else{ + throw new Exception("Serialization/Deserialization Test Failed:"+dfs.getCurrencySymbol()); + } + istream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/ojluni/src/test/java/text/Format/NumberFormat/DFSExponential.java b/ojluni/src/test/java/text/Format/NumberFormat/DFSExponential.java new file mode 100644 index 00000000000..1cb1e770a1b --- /dev/null +++ b/ojluni/src/test/java/text/Format/NumberFormat/DFSExponential.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2005, 2016, 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 4068067 + * @library /java/text/testlib + * @summary test NumberFormat with exponential separator symbols. It also tests the new + * public methods in DecimalFormatSymbols, setExponentSeparator() and + * getExponentSeparator() + */ + +package test.java.text.Format.NumberFormat; + +import java.util.*; +import java.text.*; + +import test.java.text.testlib.IntlTest; + +public class DFSExponential extends IntlTest +{ + + public static void main(String[] args) throws Exception { + new DFSExponential().run(args); + } + + + public void DFSExponenTest() throws Exception { + DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US); + String pat[] = { "0.####E0", "00.000E00", "##0.####E000", "0.###E0;[0.###E0]" }; + double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 }; + long lval[] = { 0, -1, 1, 123456789 }; + String valFormat[][] = { + {"1.234x10^-2", "1.2346x10^8", "1.23x10^300", "-3.1416x10^-271"}, + {"12.340x10^-03", "12.346x10^07", "12.300x10^299", "-31.416x10^-272"}, + {"12.34x10^-003", "123.4568x10^006", "1.23x10^300", "-314.1593x10^-273"}, + {"1.234x10^-2", "1.235x10^8", "1.23x10^300", "[3.142x10^-271]"}, + }; + + + int ival = 0, ilval = 0; + logln("Default exponent separator: "+sym.getExponentSeparator()); + try { + sym.setExponentSeparator("x10^"); + } catch (NullPointerException e){ + errln("null String was passed to set an exponent separator symbol"); + throw new RuntimeException("Test Malfunction: null String was passed to set an exponent separator symbol" ); + } + logln("Current exponent separator: "+sym.getExponentSeparator()); + + for (int p=0; p<pat.length; ++p){ + DecimalFormat fmt = new DecimalFormat(pat[p], sym); + logln(" Pattern: " + fmt.toPattern()); + String locPattern = fmt.toLocalizedPattern(); + logln(" Localized pattern: "+locPattern); + //fmt.applyLocalizedPattern(locPattern); + //System.out.println(" fmt.applyLocalizedPattern(): "+fmt.toLocalizedPattern()); + + for (int v=0; v<val.length; ++v) { + String s = fmt.format(val[v]); + logln(" " + val[v]+" --> "+s); + if(valFormat[p][v].equals(s)){ + logln(": Passed"); + }else{ + errln(" Failed: Should be formatted as "+valFormat[p][v]+ "but got "+s); + throw new RuntimeException(" Failed: Should be formatted as "+valFormat[p][v]+ "but got "+s); + } + } + } //end of the first for loop + } +} diff --git a/ojluni/src/test/java/text/Format/NumberFormat/DFSSerialization142.java b/ojluni/src/test/java/text/Format/NumberFormat/DFSSerialization142.java new file mode 100644 index 00000000000..e3672a1c4b8 --- /dev/null +++ b/ojluni/src/test/java/text/Format/NumberFormat/DFSSerialization142.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2005, 2016, 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. + */ + +/* + * No at-test for this test, because it needs to be run on JDK 1.4.2 + * Instead, the resulting serialized file + * DecimalFormatSymbols.142 is archived. + */ + +package test.java.text.Format.NumberFormat; + +import java.text.*; +import java.util.*; +import java.io.*; + +public class DFSSerialization142 { + + public static void main(String[] args) + { + try { + + DecimalFormatSymbols dfs= new DecimalFormatSymbols(); + System.out.println("Default currency symbol in the default locale : " + dfs.getCurrencySymbol()); + dfs.setCurrencySymbol("*SpecialCurrencySymbol*"); + System.out.println("The special currency symbol is set : " + dfs.getCurrencySymbol()); + FileOutputStream ostream = new FileOutputStream("DecimalFormatSymbols.142"); + ObjectOutputStream p = new ObjectOutputStream(ostream); + p.writeObject(dfs); + ostream.close(); + System.out.println("DecimalFormatSymbols saved ok."); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/ojluni/src/test/java/text/Format/NumberFormat/PositionTest.java b/ojluni/src/test/java/text/Format/NumberFormat/PositionTest.java new file mode 100644 index 00000000000..c9316187f53 --- /dev/null +++ b/ojluni/src/test/java/text/Format/NumberFormat/PositionTest.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 1997, 2016, 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 4109023 4153060 4153061 + * @library /java/text/testlib + * @summary test ParsePosition and FieldPosition + */ +/* +(C) Copyright Taligent, Inc. 1996 - All Rights Reserved +(C) Copyright IBM Corp. 1996 - All Rights Reserved + + The original version of this source code and documentation is copyrighted and +owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are +provided under terms of a License Agreement between Taligent and Sun. This +technology is protected by multiple US and International patents. This notice and +attribution to Taligent may not be removed. + Taligent is a registered trademark of Taligent, Inc. +*/ + +package test.java.text.Format.NumberFormat; + +import java.text.*; +import java.io.*; + +import test.java.text.testlib.IntlTest; + +public class PositionTest extends IntlTest { + + public static void main(String[] args) throws Exception { + new PositionTest().run(args); + } + + public void TestParsePosition() { + ParsePosition pp1 = new ParsePosition(0); + if (pp1.getIndex() == 0) { + logln("PP constructor() tested."); + }else{ + errln("*** PP getIndex or constructor() result"); + } + + { + int to = 5; + ParsePosition pp2 = new ParsePosition ( to ); + if (pp2.getIndex() == 5) { + logln("PP getIndex and constructor(TextOffset) tested."); + }else{ + errln("*** PP getIndex or constructor(TextOffset) result"); + } + pp2.setIndex( 3 ); + if (pp2.getIndex() == 3) { + logln("PP setIndex tested."); + }else{ + errln("*** PP getIndex or setIndex result"); + } + } + + ParsePosition pp2, pp3; + pp2 = new ParsePosition( 3 ); + pp3 = new ParsePosition( 5 ); + ParsePosition pp4 = new ParsePosition(5); + if (! pp2.equals(pp3)) { + logln("PP not equals tested."); + }else{ + errln("*** PP not equals fails"); + } + if (pp3.equals(pp4)) { + logln("PP equals tested."); + }else{ + errln("*** PP equals fails (" + pp3.getIndex() + " != " + pp4.getIndex() + ")"); + } + + ParsePosition pp5; + pp5 = pp4; + if (pp4.equals(pp5)) { + logln("PP operator= tested."); + }else{ + errln("*** PP operator= operator== or operator != result"); + } + + } + + public void TestFieldPosition() { + FieldPosition fp = new FieldPosition( 7 ); + + if (fp.getField() == 7) { + logln("FP constructor(int) and getField tested."); + }else{ + errln("*** FP constructor(int) or getField"); + } + + FieldPosition fph = new FieldPosition( 3 ); + if ( fph.getField() != 3) errln("*** FP getField or heap constr."); + + boolean err1 = false; + boolean err2 = false; + boolean err3 = false; +// for (long i = -50; i < 50; i++ ) { +// fp.setField( i+8 ); +// fp.setBeginIndex( i+6 ); +// fp.setEndIndex( i+7 ); +// if (fp.getField() != i+8) err1 = true; +// if (fp.getBeginIndex() != i+6) err2 = true; +// if (fp.getEndIndex() != i+7) err3 = true; +// } + if (!err1) { + logln("FP setField and getField tested."); + }else{ + errln("*** FP setField or getField"); + } + if (!err2) { + logln("FP setBeginIndex and getBeginIndex tested."); + }else{ + errln("*** FP setBeginIndex or getBeginIndex"); + } + if (!err3) { + logln("FP setEndIndex and getEndIndex tested."); + }else{ + errln("*** FP setEndIndex or getEndIndex"); + } + + logln(""); + } + + public void TestFieldPosition_example() { + //***** no error detection yet !!!!!!! + //***** this test is for compiler checks and visual verification only. + double doubleNum[] = { 123456789.0, -12345678.9, 1234567.89, -123456.789, + 12345.6789, -1234.56789, 123.456789, -12.3456789, 1.23456789}; + int dNumSize = doubleNum.length; + + DecimalFormat fmt = (DecimalFormat) NumberFormat.getInstance(); + fmt.setDecimalSeparatorAlwaysShown(true); + + final int tempLen = 20; + StringBuffer temp; + + for (int i=0; i<dNumSize; i++) { + temp = new StringBuffer(); // Get new buffer + + FieldPosition pos = new FieldPosition(NumberFormat.INTEGER_FIELD); + StringBuffer buf = new StringBuffer(); + //char fmtText[tempLen]; + //ToCharString(fmt->format(doubleNum[i], buf, pos), fmtText); + StringBuffer res = fmt.format(doubleNum[i], buf, pos); + int tempOffset = (tempLen <= (tempLen - pos.getEndIndex())) ? + tempLen : (tempLen - pos.getEndIndex()); + for (int j=0; j<tempOffset; j++) temp.append('='); // initialize + //cout << temp << fmtText << endl; + logln("FP " + temp + res); + } + + logln(""); + } + /* @bug 4109023 + * Need to override ParsePosition.equals and FieldPosition.equals. + */ + public void Test4109023() + { + + ParsePosition p = new ParsePosition(3); + ParsePosition p2 = new ParsePosition(3); + if (!p.equals(p2)) + errln("Error : ParsePosition.equals() failed"); + FieldPosition fp = new FieldPosition(2); + FieldPosition fp2 = new FieldPosition(2); + if (!fp.equals(fp2)) + errln("Error : FieldPosition.equals() failed"); + } + + /** + * @bug 4153060 + * ParsePosition.hashCode() returns different values on equal objects. + */ + public void Test4153060() { + ParsePosition p = new ParsePosition(53); + ParsePosition q = new ParsePosition(53); + if (!p.equals(q)) { + errln("" + p + " and " + q + " are not equal and should be"); + } + if (p.hashCode() != q.hashCode()) { + errln("ParsePosition.hashCode() different for equal objects"); + } else { + logln("hashCode(" + p + ") = " + p.hashCode()); + } + } + + /** + * @bug 4153061 + * FieldPosition.hashCode() returns different values on equal objects. + */ + public void Test4153061() { + FieldPosition p = new FieldPosition(53); + FieldPosition q = new FieldPosition(53); + if (!p.equals(q)) { + errln("" + p + " and " + q + " are not equal and should be"); + } + if (p.hashCode() != q.hashCode()) { + errln("FieldPosition.hashCode() different for equal objects"); + } else { + logln("hashCode(" + p + ") = " + p.hashCode()); + } + } +} diff --git a/ojluni/src/test/java/text/Format/NumberFormat/SerializationLoadTest.java b/ojluni/src/test/java/text/Format/NumberFormat/SerializationLoadTest.java new file mode 100644 index 00000000000..d4a21ba4395 --- /dev/null +++ b/ojluni/src/test/java/text/Format/NumberFormat/SerializationLoadTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1998, 2016, 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 4101150 + * @library /java/text/testlib + * @build SerializationLoadTest HexDumpReader + * @run main SerializationLoadTest + * @summary test serialization compatibility of DecimalFormat and DecimalFormatSymbols + * @key randomness + */ + +package test.java.text.Format.NumberFormat.SerializationLoadTest; + +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.util.Random; + +import test.java.text.testlib.HexDumpReader; + +public class SerializationLoadTest { + + public static void main(String[] args) + { + try { + InputStream istream1 = HexDumpReader.getStreamFromHexDump("DecimalFormat.114.txt"); + ObjectInputStream p = new ObjectInputStream(istream1); + CheckDecimalFormat it = (CheckDecimalFormat)p.readObject(); + System.out.println("1.1.4 DecimalFormat Loaded ok."); + System.out.println(it.Update()); + System.out.println("Called Update successfully."); + istream1.close(); + + InputStream istream2 = HexDumpReader.getStreamFromHexDump("DecimalFormatSymbols.114.txt"); + ObjectInputStream p2 = new ObjectInputStream(istream2); + CheckDecimalFormatSymbols it2 = (CheckDecimalFormatSymbols)p2.readObject(); + System.out.println("1.1.4 DecimalFormatSymbols Loaded ok."); + System.out.println("getDigit : " + it2.Update()); + System.out.println("Called Update successfully."); + istream2.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} + +@SuppressWarnings("serial") +class CheckDecimalFormat implements Serializable +{ + DecimalFormat _decFormat = (DecimalFormat)NumberFormat.getInstance(); + + public String Update() + { + Random r = new Random(); + return _decFormat.format(r.nextDouble()); + } +} + +@SuppressWarnings("serial") +class CheckDecimalFormatSymbols implements Serializable +{ + DecimalFormatSymbols _decFormatSymbols = new DecimalFormatSymbols(); + + public char Update() + { + return _decFormatSymbols.getDigit(); + } +} diff --git a/ojluni/src/test/java/text/Format/NumberFormat/SerializationSaveTest.java b/ojluni/src/test/java/text/Format/NumberFormat/SerializationSaveTest.java new file mode 100644 index 00000000000..f97eda20804 --- /dev/null +++ b/ojluni/src/test/java/text/Format/NumberFormat/SerializationSaveTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1998, 2016, 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. + */ + +/* + * No at-test for this test, because it needs to be run on JDK 1.1.4. + * Instead, the resulting serialized files DecimalFormat.114 and + * DecimalFormatSymbols.114 are archived. + */ + +package test.java.text.Format.NumberFormat.SerializationSaveTest; + +import java.text.*; +import java.util.*; +import java.io.*; + +public class SerializationSaveTest { + + public static void main(String[] args) + { + try { + CheckDecimalFormat it = new CheckDecimalFormat(); + System.out.println(it.Update()); + FileOutputStream ostream = new FileOutputStream("DecimalFormat.114"); + ObjectOutputStream p = new ObjectOutputStream(ostream); + p.writeObject(it); + ostream.close(); + System.out.println("DecimalFormat saved ok."); + CheckDecimalFormatSymbols it2 = new CheckDecimalFormatSymbols(); + System.out.println("getDigit : " + it2.Update()); + FileOutputStream ostream2 = new FileOutputStream("DecimalFormatSymbols.114"); + ObjectOutputStream p2 = new ObjectOutputStream(ostream2); + p2.writeObject(it2); + ostream2.close(); + System.out.println("DecimalFormatSymbols saved ok."); + } catch (Exception e) { + e.printStackTrace(); + } + } +} + +@SuppressWarnings("serial") +class CheckDecimalFormat implements Serializable +{ + DecimalFormat _decFormat = (DecimalFormat)NumberFormat.getInstance(); + + public String Update() + { + Random r = new Random(); + return _decFormat.format(r.nextDouble()); + } +} + +@SuppressWarnings("serial") +class CheckDecimalFormatSymbols implements Serializable +{ + DecimalFormatSymbols _decFormatSymbols = new DecimalFormatSymbols(); + + public char Update() + { + return _decFormatSymbols.getDigit(); + } +} diff --git a/ojluni/src/test/java/text/testlib/HexDumpReader.java b/ojluni/src/test/java/text/testlib/HexDumpReader.java new file mode 100644 index 00000000000..7221bb0762d --- /dev/null +++ b/ojluni/src/test/java/text/testlib/HexDumpReader.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2016, 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. + */ + +package test.java.text.testlib; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +/** + * HexDumpReader provides utility methods to read a hex dump text file + * and convert to an InputStream. The format supported by the methods + * can be generated by the following command. + * + * $ od -vw -t x1 foo | sed -r -e 's/^[0-9]+ ?//' -e 's/ //g' -e '/^$/d' + */ +public class HexDumpReader { + public static InputStream getStreamFromHexDump(String fileName) { + return getStreamFromHexDump(new File(System.getProperty("test.src", "."), + fileName)); + } + + public static InputStream getStreamFromHexDump(File hexFile) { + ByteArrayBuilder bab = new ByteArrayBuilder(); + int lineNo = 0; + try (BufferedReader reader + = new BufferedReader(new InputStreamReader(new FileInputStream(hexFile), + "us-ascii"))) { + String line; + while ((line = reader.readLine()) != null) { + lineNo++; + line = line.trim(); + // Skip blank and comment lines. + if (line.length() == 0) { + continue; + } + int x = line.indexOf('#'); + if (x == 0) { + continue; + } + if (x > 0) { + line = line.substring(0, x).trim(); + } + int len = line.length(); + for (int i = 0; i < len; i += 2) { + bab.put((byte)Integer.parseInt(line, i, i + 2, 16)); + } + } + } catch (Exception e) { + throw new RuntimeException(hexFile.getName() + ":error:" + lineNo + ": " + e, e); + } + return new ByteArrayInputStream(bab.toArray()); + } + + + private static class ByteArrayBuilder { + private static final int BUFFER_SIZE = 4096; + + private int size; + private List<byte[]> bytes; + private byte[] current; + private int offset; + + ByteArrayBuilder() { + bytes = new ArrayList<>(); + current = new byte[BUFFER_SIZE]; + } + + void put(byte b) { + if (offset == BUFFER_SIZE) { + bytes.add(current); + current = new byte[BUFFER_SIZE]; + offset = 0; + } + current[offset++] = b; + size++; + } + + byte[] toArray() { + byte[] buf = new byte[size]; + int ptr = 0; + for (byte[] ba : bytes) { + System.arraycopy(ba, 0, buf, ptr, ba.length); + ptr += ba.length; + } + System.arraycopy(current, 0, buf, ptr, offset); + assert ptr + offset == size; + return buf; + } + } + +} diff --git a/ojluni/src/test/java/text/testlib/IntlTest.java b/ojluni/src/test/java/text/testlib/IntlTest.java new file mode 100644 index 00000000000..b0c5cde61c7 --- /dev/null +++ b/ojluni/src/test/java/text/testlib/IntlTest.java @@ -0,0 +1,276 @@ +/* + * Copyright (c) 1998, 2016, 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. + */ + +package test.java.text.testlib; + +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Map; +import java.util.LinkedHashMap; +import java.util.List; + +/** + * IntlTest is a base class for tests that can be run conveniently from + * the command line as well as under the Java test harness. + * <p> + * Sub-classes implement a set of public void methods named "Test*" or + * "test*" with no arguments. Each of these methods performs some + * test. Test methods should indicate errors by calling either err() or + * errln(). This will increment the errorCount field and may optionally + * print a message to the log. Debugging information may also be added to + * the log via the log and logln methods. These methods will add their + * arguments to the log only if the test is being run in verbose mode. + */ +public abstract class IntlTest { + + //------------------------------------------------------------------------ + // Everything below here is boilerplate code that makes it possible + // to add a new test by simply adding a method to an existing class. + //------------------------------------------------------------------------ + + protected IntlTest() { + // Populate testMethods with all the test methods. + Method[] methods = getClass().getDeclaredMethods(); + for (Method method : methods) { + if (Modifier.isPublic(method.getModifiers()) + && method.getReturnType() == void.class + && method.getParameterCount() == 0) { + String name = method.getName(); + if (name.length() > 4) { + if (name.startsWith("Test") || name.startsWith("test")) { + testMethods.put(name, method); + } + } + } + } + } + + protected void run(String[] args) throws Exception + { + // Set up the log and reference streams. We use PrintWriters in order to + // take advantage of character conversion. The JavaEsc converter will + // convert Unicode outside the ASCII range to Java's \\uxxxx notation. + log = new PrintWriter(System.out, true); + + // Parse the test arguments. They can be either the flag + // "-verbose" or names of test methods. Create a list of + // tests to be run. + List<Method> testsToRun = new ArrayList<>(args.length); + for (String arg : args) { + switch (arg) { + case "-verbose": + verbose = true; + break; + case "-prompt": + prompt = true; + break; + case "-nothrow": + nothrow = true; + break; + case "-exitcode": + exitCode = true; + break; + default: + Method m = testMethods.get(arg); + if (m == null) { + System.out.println("Method " + arg + ": not found"); + usage(); + return; + } + testsToRun.add(m); + break; + } + } + + // If no test method names were given explicitly, run them all. + if (testsToRun.isEmpty()) { + testsToRun.addAll(testMethods.values()); + } + + System.out.println(getClass().getName() + " {"); + indentLevel++; + + // Run the list of tests given in the test arguments + for (Method testMethod : testsToRun) { + int oldCount = errorCount; + + writeTestName(testMethod.getName()); + + try { + testMethod.invoke(this, new Object[0]); + } catch (IllegalAccessException e) { + errln("Can't acces test method " + testMethod.getName()); + } catch (InvocationTargetException e) { + errln("Uncaught exception thrown in test method " + + testMethod.getName()); + e.getTargetException().printStackTrace(this.log); + } + writeTestResult(errorCount - oldCount); + } + indentLevel--; + writeTestResult(errorCount); + + if (prompt) { + System.out.println("Hit RETURN to exit..."); + try { + System.in.read(); + } catch (IOException e) { + System.out.println("Exception: " + e.toString() + e.getMessage()); + } + } + if (nothrow) { + if (exitCode) { + System.exit(errorCount); + } + if (errorCount > 0) { + throw new IllegalArgumentException("encountered " + errorCount + " errors"); + } + } + } + + /** + * Adds the given message to the log if we are in verbose mode. + */ + protected void log(String message) { + logImpl(message, false); + } + + protected void logln(String message) { + logImpl(message, true); + } + + protected void logln() { + logImpl(null, true); + } + + private void logImpl(String message, boolean newline) { + if (verbose) { + if (message != null) { + indent(indentLevel + 1); + log.print(message); + } + if (newline) { + log.println(); + } + } + } + + protected void err(String message) { + errImpl(message, false); + } + + protected void errln(String message) { + errImpl(message, true); + } + + private void errImpl(String message, boolean newline) { + errorCount++; + indent(indentLevel + 1); + log.print(message); + if (newline) { + log.println(); + } + log.flush(); + + if (!nothrow) { + throw new RuntimeException(message); + } + } + + protected int getErrorCount() { + return errorCount; + } + + protected void writeTestName(String testName) { + indent(indentLevel); + log.print(testName); + log.flush(); + needLineFeed = true; + } + + protected void writeTestResult(int count) { + if (!needLineFeed) { + indent(indentLevel); + log.print("}"); + } + needLineFeed = false; + + if (count != 0) { + log.println(" FAILED"); + } else { + log.println(" Passed"); + } + } + + /* + * Returns a spece-delimited hex String. + */ + protected static String toHexString(String s) { + StringBuilder sb = new StringBuilder(" "); + + for (int i = 0; i < s.length(); i++) { + sb.append(Integer.toHexString(s.charAt(i))); + sb.append(' '); + } + + return sb.toString(); + } + + private void indent(int distance) { + if (needLineFeed) { + log.println(" {"); + needLineFeed = false; + } + log.print(SPACES.substring(0, distance * 2)); + } + + /** + * Print a usage message for this test class. + */ + void usage() { + System.out.println(getClass().getName() + + ": [-verbose] [-nothrow] [-exitcode] [-prompt] [test names]"); + + System.out.println(" Available test names:"); + for (String methodName : testMethods.keySet()) { + System.out.println("\t" + methodName); + } + } + + private boolean prompt; + private boolean nothrow; + protected boolean verbose; + private boolean exitCode; + private PrintWriter log; + private int indentLevel; + private boolean needLineFeed; + private int errorCount; + + private final Map<String, Method> testMethods = new LinkedHashMap<>(); + + private static final String SPACES = " "; +} diff --git a/ojluni/src/test/java/text/testlib/TestUtils.java b/ojluni/src/test/java/text/testlib/TestUtils.java new file mode 100644 index 00000000000..c3f582d960a --- /dev/null +++ b/ojluni/src/test/java/text/testlib/TestUtils.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016, 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. + */ + +package test.java.text.testlib; + +import java.text.DecimalFormatSymbols; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.Locale; + +import java.util.Locale.Builder; + +/** + * TestUtils provides utility methods to get a locale-dependent attribute. + * For example, + * - whether or not a non-Gregorian calendar is used + * - whether or not non-ASCII digits are used + * + * This class was developed to help testing for internationalization & + * localization and is not versatile. + */ +public class TestUtils { + + /** + * Returns true if the give locale uses Gregorian calendar. + */ + public static boolean usesGregorianCalendar(Locale locale) { + return Calendar.getInstance(locale).getClass() == GregorianCalendar.class; + } + + /** + * Returns true if the given locale uses ASCII digits. + */ + public static boolean usesAsciiDigits(Locale locale) { + return DecimalFormatSymbols.getInstance(locale).getZeroDigit() == '0'; + } + + /** + * Returns true if the given locale has a special variant which is treated + * as ill-formed in BCP 47. + * + * BCP 47 requires a variant subtag to be 5 to 8 alphanumerics or a + * single numeric followed by 3 alphanumerics. + * However, note that this methods doesn't check a variant so rigorously + * because this is a utility method for testing. Intended special variants + * are: JP, NY, and TH, which can be commonly provided by + * Locale.getAvailableLocales(). + * + */ + public static boolean hasSpecialVariant(Locale locale) { + String variant = locale.getVariant(); + return !variant.isEmpty() + && "JP".equals(variant) || "NY".equals(variant) || "TH".equals(variant); + } + +} diff --git a/ojluni/src/test/java/util/Arrays/ArrayObjectMethods.java b/ojluni/src/test/java/util/Arrays/ArrayObjectMethods.java new file mode 100644 index 00000000000..03d19066f2c --- /dev/null +++ b/ojluni/src/test/java/util/Arrays/ArrayObjectMethods.java @@ -0,0 +1,508 @@ +/* + * Copyright (c) 2003, 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 4906359 6239296 + * @summary Basic test for content-based array object methods + * @author Josh Bloch, Martin Buchholz + * @key randomness + */ + +package test.java.util.Arrays; + +import java.util.*; +import java.io.*; + +public class ArrayObjectMethods { + int[] sizes = {0, 10, 100, 200, 1000}; + + void test(String[] args) throws Throwable { + equal(Arrays.deepToString(null), "null"); + equal(Arrays.deepToString(new Object[]{}), "[]"); + equal(Arrays.deepToString(new Object[]{null}), "[null]"); + equal(Arrays.deepToString(new Object[]{null, 1}), "[null, 1]"); + equal(Arrays.deepToString(new Object[]{1, null}), "[1, null]"); + equal(Arrays.deepToString(new Object[]{new Object[]{}, null}), "[[], null]"); + + { + Object[] a = {1, null}; + a[1] = a; + equal(Arrays.deepToString(a), "[1, [...]]"); + a[0] = a; + equal(Arrays.deepToString(a), "[[...], [...]]"); + a[0] = a[1] = new Object[]{1, null, a}; + equal(Arrays.deepToString(a), "[[1, null, [...]], [1, null, [...]]]"); + } + + for (int size : sizes) { + { + long[] a = Rnd.longArray(size); + equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); + equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); + } + { + int[] a = Rnd.intArray(size); + equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); + equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); + } + { + short[] a = Rnd.shortArray(size); + equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); + equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); + } + { + char[] a = Rnd.charArray(size); + equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); + equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); + } + { + byte[] a = Rnd.byteArray(size); + equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); + equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); + } + { + boolean[] a = Rnd.booleanArray(size); + equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); + equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); + } + { + double[] a = Rnd.doubleArray(size); + equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); + equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); + } + { + float[] a = Rnd.floatArray(size); + equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); + equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); + } + { + Object[] a = Rnd.flatObjectArray(size); + equal(Arrays.toString(a), Arrays.asList(a).toString()); + equal(Arrays.deepToString(a), Arrays.asList(a).toString()); + equal(Arrays.hashCode(a), Arrays.asList(a).hashCode()); + } + + if (size <= 200) { + Object[] a = Rnd.nestedObjectArray(size); + List aList = deepToList(a); + equal(Arrays.toString(a), Arrays.asList(a).toString()); + equal(Arrays.deepToString(a), aList.toString()); + equal(Arrays.deepHashCode(a), aList.hashCode()); + equal(Arrays.hashCode(a), Arrays.asList(a).hashCode()); + + Object[] deepCopy = (Object[]) deepCopy(a); + check(Arrays.deepEquals(a, deepCopy)); + check(Arrays.deepEquals(deepCopy, a)); + + // Make deepCopy != a + if (size == 0) + deepCopy = new Object[] {"foo"}; + else if (deepCopy[deepCopy.length - 1] == null) + deepCopy[deepCopy.length - 1] = "baz"; + else + deepCopy[deepCopy.length - 1] = null; + check(! Arrays.deepEquals(a, deepCopy)); + check(! Arrays.deepEquals(deepCopy, a)); + } + } + } + + // Utility method to turn an array into a list "deeply," turning + // all primitives into objects + List<Object> deepToList(Object[] a) { + List<Object> result = new ArrayList<Object>(); + for (Object e : a) { + if (e instanceof byte[]) + result.add(PrimitiveArrays.asList((byte[])e)); + else if (e instanceof short[]) + result.add(PrimitiveArrays.asList((short[])e)); + else if (e instanceof int[]) + result.add(PrimitiveArrays.asList((int[])e)); + else if (e instanceof long[]) + result.add(PrimitiveArrays.asList((long[])e)); + else if (e instanceof char[]) + result.add(PrimitiveArrays.asList((char[])e)); + else if (e instanceof double[]) + result.add(PrimitiveArrays.asList((double[])e)); + else if (e instanceof float[]) + result.add(PrimitiveArrays.asList((float[])e)); + else if (e instanceof boolean[]) + result.add(PrimitiveArrays.asList((boolean[])e)); + else if (e instanceof Object[]) + result.add(deepToList((Object[])e)); + else + result.add(e); + } + return result; + } + + // Utility method to do a deep copy of an object *very slowly* using + // serialization/deserialization + Object deepCopy(Object oldObj) { + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(oldObj); + oos.flush(); + ByteArrayInputStream bin = new ByteArrayInputStream( + bos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bin); + return ois.readObject(); + } catch(Exception e) { + throw new IllegalArgumentException(e); + } + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new ArrayObjectMethods().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} + +/** + * Methods to generate "interesting" random primitives and primitive + * arrays. Unlike Random.nextXxx, these methods return small values + * and boundary values (e.g., 0, -1, NaN) with greater than normal + * likelihood. + */ + +class Rnd { + private static Random rnd = new Random(); + + public static long nextLong() { + switch(rnd.nextInt(10)) { + case 0: return 0; + case 1: return Long.MIN_VALUE; + case 2: return Long.MAX_VALUE; + case 3: case 4: case 5: + return (long) (rnd.nextInt(20) - 10); + default: return rnd.nextLong(); + } + } + + public static int nextInt() { + switch(rnd.nextInt(10)) { + case 0: return 0; + case 1: return Integer.MIN_VALUE; + case 2: return Integer.MAX_VALUE; + case 3: case 4: case 5: + return rnd.nextInt(20) - 10; + default: return rnd.nextInt(); + } + } + + public static short nextShort() { + switch(rnd.nextInt(10)) { + case 0: return 0; + case 1: return Short.MIN_VALUE; + case 2: return Short.MAX_VALUE; + case 3: case 4: case 5: + return (short) (rnd.nextInt(20) - 10); + default: return (short) rnd.nextInt(); + } + } + + public static char nextChar() { + switch(rnd.nextInt(10)) { + case 0: return 0; + case 1: return Character.MIN_VALUE; + case 2: return Character.MAX_VALUE; + case 3: case 4: case 5: + return (char) (rnd.nextInt(20) - 10); + default: return (char) rnd.nextInt(); + } + } + + public static byte nextByte() { + switch(rnd.nextInt(10)) { + case 0: return 0; + case 1: return Byte.MIN_VALUE; + case 2: return Byte.MAX_VALUE; + case 3: case 4: case 5: + return (byte) (rnd.nextInt(20) - 10); + default: return (byte) rnd.nextInt(); + } + } + + public static boolean nextBoolean() { + return rnd.nextBoolean(); + } + + public static double nextDouble() { + switch(rnd.nextInt(20)) { + case 0: return 0; + case 1: return -0.0; + case 2: return Double.MIN_VALUE; + case 3: return Double.MAX_VALUE; + case 4: return Double.NaN; + case 5: return Double.NEGATIVE_INFINITY; + case 6: return Double.POSITIVE_INFINITY; + case 7: case 8: case 9: + return (rnd.nextInt(20) - 10); + default: return rnd.nextDouble(); + } + } + + public static float nextFloat() { + switch(rnd.nextInt(20)) { + case 0: return 0; + case 1: return -0.0f; + case 2: return Float.MIN_VALUE; + case 3: return Float.MAX_VALUE; + case 4: return Float.NaN; + case 5: return Float.NEGATIVE_INFINITY; + case 6: return Float.POSITIVE_INFINITY; + case 7: case 8: case 9: + return (rnd.nextInt(20) - 10); + default: return rnd.nextFloat(); + } + } + + public static Object nextObject() { + switch(rnd.nextInt(10)) { + case 0: return null; + case 1: return "foo"; + case 2: case 3: case 4: + return Double.valueOf(nextDouble()); + default: return Integer.valueOf(nextInt()); + } + } + + public static long[] longArray(int length) { + long[] result = new long[length]; + for (int i = 0; i < length; i++) + result[i] = Rnd.nextLong(); + return result; + } + + public static int[] intArray(int length) { + int[] result = new int[length]; + for (int i = 0; i < length; i++) + result[i] = Rnd.nextInt(); + return result; + } + + public static short[] shortArray(int length) { + short[] result = new short[length]; + for (int i = 0; i < length; i++) + result[i] = Rnd.nextShort(); + return result; + } + + public static char[] charArray(int length) { + char[] result = new char[length]; + for (int i = 0; i < length; i++) + result[i] = Rnd.nextChar(); + return result; + } + + public static byte[] byteArray(int length) { + byte[] result = new byte[length]; + for (int i = 0; i < length; i++) + result[i] = Rnd.nextByte(); + return result; + } + + public static boolean[] booleanArray(int length) { + boolean[] result = new boolean[length]; + for (int i = 0; i < length; i++) + result[i] = Rnd.nextBoolean(); + return result; + } + + public static double[] doubleArray(int length) { + double[] result = new double[length]; + for (int i = 0; i < length; i++) + result[i] = Rnd.nextDouble(); + return result; + } + + public static float[] floatArray(int length) { + float[] result = new float[length]; + for (int i = 0; i < length; i++) + result[i] = Rnd.nextFloat(); + return result; + } + + public static Object[] flatObjectArray(int length) { + Object[] result = new Object[length]; + for (int i = 0; i < length; i++) + result[i] = Rnd.nextObject(); + return result; + } + + // Calling this for length >> 100 is likely to run out of memory! It + // should be perhaps be tuned to allow for longer arrays + public static Object[] nestedObjectArray(int length) { + Object[] result = new Object[length]; + for (int i = 0; i < length; i++) { + switch(rnd.nextInt(16)) { + case 0: result[i] = nestedObjectArray(length/2); + break; + case 1: result[i] = longArray(length/2); + break; + case 2: result[i] = intArray(length/2); + break; + case 3: result[i] = shortArray(length/2); + break; + case 4: result[i] = charArray(length/2); + break; + case 5: result[i] = byteArray(length/2); + break; + case 6: result[i] = floatArray(length/2); + break; + case 7: result[i] = doubleArray(length/2); + break; + case 8: result[i] = longArray(length/2); + break; + default: result[i] = Rnd.nextObject(); + } + } + return result; + } +} + +/** + * Primitive arrays viewed as lists. Inefficient but cool. + * This utility should be generally useful in writing regression/unit/basic + * tests. + */ + +class PrimitiveArrays { + public static List<Long> asList(final long[] a) { + return new AbstractList<Long>() { + public Long get(int i) { return a[i]; } + public int size() { return a.length; } + + public Long set(int i, Long e) { + long oldVal = a[i]; + a[i] = e; + return oldVal; + } + }; + } + + public static List<Integer> asList(final int[] a) { + return new AbstractList<Integer>() { + public Integer get(int i) { return a[i]; } + public int size() { return a.length; } + + public Integer set(int i, Integer e) { + int oldVal = a[i]; + a[i] = e; + return oldVal; + } + }; + } + + public static List<Short> asList(final short[] a) { + return new AbstractList<Short>() { + public Short get(int i) { return a[i]; } + public int size() { return a.length; } + + public Short set(int i, Short e) { + short oldVal = a[i]; + a[i] = e; + return oldVal; + } + }; + } + + public static List<Character> asList(final char[] a) { + return new AbstractList<Character>() { + public Character get(int i) { return a[i]; } + public int size() { return a.length; } + + public Character set(int i, Character e) { + Character oldVal = a[i]; + a[i] = e; + return oldVal; + } + }; + } + + public static List<Byte> asList(final byte[] a) { + return new AbstractList<Byte>() { + public Byte get(int i) { return a[i]; } + public int size() { return a.length; } + + public Byte set(int i, Byte e) { + Byte oldVal = a[i]; + a[i] = e; + return oldVal; + } + }; + } + + public static List<Boolean> asList(final boolean[] a) { + return new AbstractList<Boolean>() { + public Boolean get(int i) { return a[i]; } + public int size() { return a.length; } + + public Boolean set(int i, Boolean e) { + Boolean oldVal = a[i]; + a[i] = e; + return oldVal; + } + }; + } + + public static List<Double> asList(final double[] a) { + return new AbstractList<Double>() { + public Double get(int i) { return a[i]; } + public int size() { return a.length; } + + public Double set(int i, Double e) { + Double oldVal = a[i]; + a[i] = e; + return oldVal; + } + }; + } + + public static List<Float> asList(final float[] a) { + return new AbstractList<Float>() { + public Float get(int i) { return a[i]; } + public int size() { return a.length; } + + public Float set(int i, Float e) { + Float oldVal = a[i]; + a[i] = e; + return oldVal; + } + }; + } +} diff --git a/ojluni/src/test/java/util/Arrays/ArraysEqCmpTest.java b/ojluni/src/test/java/util/Arrays/ArraysEqCmpTest.java index 727f7dcae62..380f5b3903c 100644 --- a/ojluni/src/test/java/util/Arrays/ArraysEqCmpTest.java +++ b/ojluni/src/test/java/util/Arrays/ArraysEqCmpTest.java @@ -27,7 +27,7 @@ package test.java.util.Arrays; * @bug 8033148 8141409 * @summary tests for array equals and compare * @run testng ArraysEqCmpTest - */ +*/ import org.testng.Assert; import org.testng.annotations.DataProvider; @@ -106,7 +106,7 @@ public class ArraysEqCmpTest { if (componentType.isPrimitive()) { cpy = l.findStatic(Arrays.class, "copyOfRange", - MethodType.methodType(arrayType, arrayType, int.class, int.class)); + MethodType.methodType(arrayType, arrayType, int.class, int.class)); MethodType eqt = MethodType.methodType( boolean.class, arrayType, arrayType); @@ -118,21 +118,21 @@ public class ArraysEqCmpTest { String compareName = unsigned ? "compareUnsigned" : "compare"; cmp = l.findStatic(Arrays.class, compareName, - eqt.changeReturnType(int.class)); + eqt.changeReturnType(int.class)); cmpr = l.findStatic(Arrays.class, compareName, - eqrt.changeReturnType(int.class)); + eqrt.changeReturnType(int.class)); mm = l.findStatic(Arrays.class, "mismatch", - eqt.changeReturnType(int.class)); + eqt.changeReturnType(int.class)); mmr = l.findStatic(Arrays.class, "mismatch", - eqrt.changeReturnType(int.class)); + eqrt.changeReturnType(int.class)); toString = l.findStatic(Arrays.class, "toString", - MethodType.methodType(String.class, arrayType)); + MethodType.methodType(String.class, arrayType)); } else { cpy = l.findStatic(Arrays.class, "copyOfRange", - MethodType.methodType(Object[].class, Object[].class, int.class, int.class)); + MethodType.methodType(Object[].class, Object[].class, int.class, int.class)); MethodType eqt = MethodType.methodType( boolean.class, Object[].class, Object[].class); @@ -151,12 +151,12 @@ public class ArraysEqCmpTest { cmpr = l.findStatic(Arrays.class, "compare", cmprt); mm = l.findStatic(Arrays.class, "mismatch", - eqt.changeReturnType(int.class)); + eqt.changeReturnType(int.class)); mmr = l.findStatic(Arrays.class, "mismatch", - eqrt.changeReturnType(int.class)); + eqrt.changeReturnType(int.class)); toString = l.findStatic(Arrays.class, "toString", - MethodType.methodType(String.class, Object[].class)); + MethodType.methodType(String.class, Object[].class)); } } @@ -218,7 +218,7 @@ public class ArraysEqCmpTest { } boolean equals(Object a, int aFromIndex, int aToIndex, - Object b, int bFromIndex, int bToIndex) { + Object b, int bFromIndex, int bToIndex) { try { return (boolean) eqr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex); } @@ -243,7 +243,7 @@ public class ArraysEqCmpTest { } int compare(Object a, int aFromIndex, int aToIndex, - Object b, int bFromIndex, int bToIndex) { + Object b, int bFromIndex, int bToIndex) { try { return (int) cmpr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex); } @@ -268,7 +268,7 @@ public class ArraysEqCmpTest { } int mismatch(Object a, int aFromIndex, int aToIndex, - Object b, int bFromIndex, int bToIndex) { + Object b, int bFromIndex, int bToIndex) { try { return (int) mmr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex); } @@ -357,7 +357,7 @@ public class ArraysEqCmpTest { @Override boolean equals(Object a, int aFromIndex, int aToIndex, - Object b, int bFromIndex, int bToIndex) { + Object b, int bFromIndex, int bToIndex) { try { return (boolean) eqcr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex, c); } @@ -384,7 +384,7 @@ public class ArraysEqCmpTest { @Override int compare(Object a, int aFromIndex, int aToIndex, - Object b, int bFromIndex, int bToIndex) { + Object b, int bFromIndex, int bToIndex) { try { return (int) cmpcr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex, c); } @@ -411,7 +411,7 @@ public class ArraysEqCmpTest { @Override int mismatch(Object a, int aFromIndex, int aToIndex, - Object b, int bFromIndex, int bToIndex) { + Object b, int bFromIndex, int bToIndex) { try { return (int) mismatchcr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex, c); } @@ -729,27 +729,27 @@ public class ArraysEqCmpTest { // All nulls testArrayType(arrayType, - (at, s) -> { - Object a = at.construct(s); - for (int x = 0; x < s; x++) { - at.set(a, x, null); - } - return a; - }, - cloner); + (at, s) -> { + Object a = at.construct(s); + for (int x = 0; x < s; x++) { + at.set(a, x, null); + } + return a; + }, + cloner); // Some nulls testArrayType(arrayType, - (at, s) -> { - Object a = at.construct(s); - for (int x = 0; x < s; x++) { - int v = x % 8; - at.set(a, x, v == 0 ? null : v); - } - return a; - }, - cloner); + (at, s) -> { + Object a = at.construct(s); + for (int x = 0; x < s; x++) { + int v = x % 8; + at.set(a, x, v == 0 ? null : v); + } + return a; + }, + cloner); Integer[] a = new Integer[]{null, 0}; Integer[] b = new Integer[]{0, 0}; @@ -764,37 +764,37 @@ public class ArraysEqCmpTest { // One ref Integer one = 1; testArrayType(arrayType, - (at, s) -> { - Integer[] a = (Integer[]) at.construct(s); - for (int x = 0; x < s; x++) { - a[x] = one; - } - return a; - }, - cloner); + (at, s) -> { + Integer[] a = (Integer[]) at.construct(s); + for (int x = 0; x < s; x++) { + a[x] = one; + } + return a; + }, + cloner); // All ref testArrayType(arrayType, - (at, s) -> { - Integer[] a = (Integer[]) at.construct(s); - for (int x = 0; x < s; x++) { - a[x] = Integer.valueOf(s); - } - return a; - }, - cloner); + (at, s) -> { + Integer[] a = (Integer[]) at.construct(s); + for (int x = 0; x < s; x++) { + a[x] = Integer.valueOf(s); + } + return a; + }, + cloner); // Some same ref testArrayType(arrayType, - (at, s) -> { - Integer[] a = (Integer[]) at.construct(s); - for (int x = 0; x < s; x++) { - int v = x % 8; - a[x] = v == 1 ? one : new Integer(v); - } - return a; - }, - cloner); + (at, s) -> { + Integer[] a = (Integer[]) at.construct(s); + for (int x = 0; x < s; x++) { + int v = x % 8; + a[x] = v == 1 ? one : new Integer(v); + } + return a; + }, + cloner); } @Test(dataProvider = "signedUnsignedArrayTypes") @@ -835,8 +835,8 @@ public class ArraysEqCmpTest { } void testArrayType(ArrayType<?> at, - BiFunction<ArrayType<?>, Integer, Object> constructor, - BiFunction<ArrayType<?>, Object, Object> cloner) { + BiFunction<ArrayType<?>, Integer, Object> constructor, + BiFunction<ArrayType<?>, Object, Object> cloner) { int n = arraySizeFor(at.componentType); for (int s : ranges(0, n)) { @@ -944,7 +944,7 @@ public class ArraysEqCmpTest { } static boolean isEqual(ArrayType<?> at, Object a, int aFromIndex, int aToIndex, - Object b, int bFromIndex, int bToIndex) { + Object b, int bFromIndex, int bToIndex) { int aLength = aToIndex - aFromIndex; int bLength = bToIndex - bFromIndex; if (aLength != bLength) @@ -1079,7 +1079,7 @@ public class ArraysEqCmpTest { for (int bFrom : froms) { for (int bTo : tos) { if (aFrom >= 0 && aTo <= s && - bFrom >= 0 && bTo <= s) continue; + bFrom >= 0 && bTo <= s) continue; testAIOBE(() -> arrayType.equals(a, aFrom, aTo, a, bFrom, bTo)); testAIOBE(() -> arrayType.compare(a, aFrom, aTo, a, bFrom, bTo)); diff --git a/ojluni/src/test/java/util/Arrays/AsList.java b/ojluni/src/test/java/util/Arrays/AsList.java new file mode 100644 index 00000000000..6376edf6f88 --- /dev/null +++ b/ojluni/src/test/java/util/Arrays/AsList.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2016, 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 8155600 + * @summary Tests for Arrays.asList() + * @run testng AsList + */ + +package test.java.util.Arrays; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.stream.IntStream; + +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; +import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.fail; + +public class AsList { + /* + * Iterator contract test + */ + @Test(dataProvider = "Arrays") + public void testIterator(Object[] array) { + Iterator<Object> itr = Arrays.asList(array).iterator(); + for (int i = 0; i < array.length; i++) { + assertTrue(itr.hasNext()); + assertTrue(itr.hasNext()); // must be idempotent + assertSame(array[i], itr.next()); + try { + itr.remove(); + fail("Remove must throw"); + } catch (UnsupportedOperationException ex) { + // expected + } + } + assertFalse(itr.hasNext()); + for (int i = 0; i < 3; i++) { + assertFalse(itr.hasNext()); + try { + itr.next(); + fail("Next succeed when there's no data left"); + } catch (NoSuchElementException ex) { + // expected + } + } + } + + @DataProvider(name = "Arrays") + public static Object[][] arrays() { + Object[][] arrays = { + { new Object[] { } }, + { new Object[] { 1 } }, + { new Object[] { null } }, + { new Object[] { null, 1 } }, + { new Object[] { 1, null } }, + { new Object[] { null, null } }, + { new Object[] { null, 1, 2 } }, + { new Object[] { 1, null, 2 } }, + { new Object[] { 1, 2, null } }, + { new Object[] { null, null, null } }, + { new Object[] { 1, 2, 3, null, 4 } }, + { new Object[] { "a", "a", "a", "a" } }, + { IntStream.range(0, 100).boxed().toArray() } + }; + + return arrays; + } +} diff --git a/ojluni/src/test/java/util/Arrays/CopyMethods.java b/ojluni/src/test/java/util/Arrays/CopyMethods.java new file mode 100644 index 00000000000..37ac5f54fb4 --- /dev/null +++ b/ojluni/src/test/java/util/Arrays/CopyMethods.java @@ -0,0 +1,427 @@ +/* + * Copyright (c) 2005, 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 4655503 + * @summary Test for array cloning and slicing methods. + * @author John Rose + * @key randomness + */ + +package test.java.util.Arrays; + +import java.util.*; +import java.lang.reflect.*; + +public class CopyMethods { + static int muzzle; // if !=0, suppresses ("muzzles") messages + + static int maxLen = 40; // maximum length of test arrays + static int shortStepsNear = 4; // interesting span near critical values + static int downShift = 3; + + static int testCasesRun = 0; + static long consing = 0; + + // very simple tests, mainly to test the framework itself + static void simpleTests() { + int[] a = (int[]) makeArray(3, int.class); + if (muzzle == 0) + System.out.println("int[] a = "+Arrays.toString(a)); + check(a.length == 3); + check(a[0] == testValues[0]); + check(a[1] == testValues[1]); + check(a[2] == testValues[2]); + checkArray(a, int.class, 3, 0, 3); + // negative test of testing framework: + for (int bad = -2; bad < a.length; bad++) { + try { + int[] aa = a.clone(); + if (bad < 0) aa = new int[4]; + else aa[bad] = 0; + ++muzzle; + // the following check should fail! + if (bad == -2) + checkArray(new String[3], int.class, 0, 0, a.length); + else + checkArray(aa, int.class, 0, 0, a.length); + throw new Error("Should Not Reach Here"); + } catch (RuntimeException ee) { + --muzzle; + if (muzzle == 0) + System.out.println("Expected: "+ee); + } + } + checkArray(Arrays.copyOf(a, 0), int.class, 0, 0, 3); + checkArray(Arrays.copyOf(a, 1), int.class, 1, 0, 3); + checkArray(Arrays.copyOf(a, 2), int.class, 2, 0, 3); + checkArray(Arrays.copyOf(a, 3), int.class, 3, 0, 3); + checkArray(Arrays.copyOf(a, 4), int.class, 4, 0, 3); + + // quick test of copyOfRange + int[] ar = Arrays.copyOfRange(a, 1, 3); + check(ar.length == 2); + check(ar[0] == a[1]); + check(ar[1] == a[2]); + checkArray(ar, int.class, 2, 1, 2); + ar = Arrays.copyOfRange(a, 2, 4); + check(ar.length == 2); + check(ar[0] == a[2]); + check(ar[1] == 0); + checkArray(ar, int.class, 2, 2, 1); + ar = Arrays.copyOfRange(a, 3, 5); + check(ar.length == 2); + check(ar[0] == 0); + check(ar[1] == 0); + checkArray(ar, int.class, 2, 3, 0); + byte[] ba = (byte[]) makeArray(3, byte.class); + if (muzzle == 0) + System.out.println("byte[] ba = "+Arrays.toString(ba)); + for (int j = 0; j <= ba.length+2; j++) { + byte[] bb = Arrays.copyOf(ba, j); + if (muzzle == 0) + System.out.println("copyOf(ba,"+j+") = "+ + Arrays.toString(bb)); + checkArray(bb, byte.class, j, 0, ba.length); + byte[] bbr = Arrays.copyOfRange(ba, 0, j); + check(Arrays.equals(bb, bbr)); + } + for (int i = 0; i <= a.length; i++) { + for (int j = i; j <= a.length+2; j++) { + byte[] br = Arrays.copyOfRange(ba, i, j); + if (muzzle == 0) + System.out.println("copyOfRange(ba,"+i+","+j+") = "+ + Arrays.toString(br)); + checkArray(br, byte.class, j-i, i, ba.length-i); + } + } + String[] sa = (String[]) makeArray(3, String.class); + if (muzzle == 0) + System.out.println("String[] sa = "+Arrays.toString(sa)); + check(sa[0].equals(Integer.toHexString(testValues[0]))); + check(sa[1].equals(Integer.toHexString(testValues[1]))); + check(sa[2].equals(Integer.toHexString(testValues[2]))); + checkArray(sa, String.class, sa.length, 0, sa.length); + String[] sa4 = Arrays.copyOf(sa, sa.length+1); + check(sa4[0] == sa[0]); + check(sa4[1] == sa[1]); + check(sa4[2] == sa[2]); + check(sa4[sa.length] == null); + checkArray(sa4, String.class, sa4.length, 0, sa.length); + String[] sr4 = Arrays.copyOfRange(sa, 1, 5); + check(sr4[0] == sa[1]); + check(sr4[1] == sa[2]); + check(sr4[2] == null); + check(sr4[3] == null); + checkArray(sr4, String.class, 4, 1, sa.length-1); + if (muzzle == 0) + System.out.println("simpleTests done"); + } + + // the framework: a fixed series of test values + static final int[] testValues; + static { + testValues = new int[1000]; + Random r = new Random(); + for (int i = 0; i < testValues.length; i++) { + testValues[i] = r.nextInt(); + } + } + /** Return a canonical test value of a desired index and type. + * The original test values are random ints. Derive other test + * values as follows: + * <pre> + * int tv = testValues[i] + * (C)tv C is byte, short, char, long, float, double + * (tv&1)!=0 C is boolean + * (Integer)tv C is Object and tv%16 != 0 + * null C is Object and tv%16 == 0 + * Integer.toHexString(tv) C is String and tv != 0 + * null C is String and tv == 0 + * </pre> + * are derived by ordinary Java coercions, except that boolean + * samples the LSB of the int value, and String is the hex numeral. + * + * (Also, the 0th String is null, and the 0th Object mod 16 is null, + * regardless of the original int test value.) + */ + static Object testValue(int i, Class<?> c) { + int tv = testValues[i % testValues.length]; + if (i >= testValues.length) tv ^= i; + // Turn the canonical int to a float, boolean, String, whatever: + return invoke(coercers.get(c), tv); + } + /** Build a test array of the given length, + * packed with a subsequence of the test values. + * The first element of the array is always testValue(0). + */ + static Object makeArray(int len, Class<?> c) { + Object a = Array.newInstance(c, len); + for (int i = 0; i < len; i++) { + Array.set(a, i, testValue(i, c)); + } + return a; + } + /** Check that the given array has the required length. + * Check also that it is packed, up to firstNull, with + * a particular subsequence of the canonical test values. + * The subsequence must begin with a[0] == testValue(offset). + * At a[firstNull] and beyond, the array must contain null values. + */ + static void checkArray(Object a, Class<?> c, int requiredLen, int offset, int firstNull) { + check(c == a.getClass().getComponentType()); + Object nullValue = nullValues.get(c); + // Note: asserts in here are not part of the test program. + // They verify the integrity of the test method itself. + assert(nullValues.containsKey(c)); + + int misses = 0; + int firstMiss = -1; + // Check required length first. + int length = Array.getLength(a); + if (length != requiredLen && requiredLen != -1) { + if (muzzle == 0) + System.out.println("*** a.length = "+length+" != "+requiredLen); + ++misses; + } + + for (int i = 0; i < length; i++) { + Object tv = (i >= firstNull) ? nullValue : testValue(i+offset, c); + Object ai = Array.get(a, i); + if (!eq(ai, tv)) { + if (muzzle == 0) + System.out.println("*** a["+i+"] = "+ai+" != "+tv); + if (misses == 0) firstMiss = i; + if (++misses > 10) break; + } + } + if (misses != 0) { + Method toString = toStrings.get(c); + if (toString == null) toString = toStrings.get(Object.class); + throw new RuntimeException("checkArray failed at "+firstMiss + +" "+c+"[]" + +" : "+invoke(toString, a)); + } + } + // Typical comparison helper. Why isn't this a method somewhere. + static boolean eq(Object x, Object y) { + return x == null? y == null: x.equals(y); + } + // Exception-ignoring invoke function. + static Object invoke(Method m, Object... args) { + Exception ex; + try { + return m.invoke(null, args); + } catch (InvocationTargetException ee) { + ex = ee; + } catch (IllegalAccessException ee) { + ex = ee; + } catch (IllegalArgumentException ee) { + ex = ee; + } + ArrayList<Object> call = new ArrayList<Object>(); + call.add(m); Collections.addAll(call, args); + throw new RuntimeException(call+" : "+ex); + } + // version of assert() that runs unconditionally + static void check(boolean z) { + if (!z) throw new RuntimeException("check failed"); + } + + + /** Run about 10**5 distinct parameter combinations + * on copyOf and copyOfRange. Use all primitive types, + * and String and Object. + * Try to all critical values, looking for fencepost errors. + */ + static void fullTests(int maxLen, Class<?> c) { + Method cloner = cloners.get(c); + assert(cloner != null) : c; + Method cloneRanger = cloneRangers.get(c); + // Note: asserts in here are not part of the test program. + // They verify the integrity of the test method itself. + assert(cloneRanger != null) : c; + for (int src = 0; src <= maxLen; src = inc(src, 0, maxLen)) { + Object a = makeArray(src, c); + for (int x : new ArrayList<Integer>()) {} + for (int j = 0; j <= maxLen; j = inc(j, src, maxLen)) { + // b = Arrays.copyOf(a, j); + Object b = invoke(cloner, a, j); + checkArray(b, c, j, 0, src); + testCasesRun++; + consing += j; + + int maxI = Math.min(src, j); + for (int i = 0; i <= maxI; i = inc(i, src, maxI)) { + // r = Arrays.copyOfRange(a, i, j); + Object r = invoke(cloneRanger, a, i, j); + checkArray(r, c, j-i, i, src-i); + //System.out.println("case c="+c+" src="+src+" i="+i+" j="+j); + testCasesRun++; + consing += j-i; + } + } + } + } + // Increment x by at least one. Increment by a little more unless + // it is near a critical value, either zero, crit1, or crit2. + static int inc(int x, int crit1, int crit2) { + int D = shortStepsNear; + if (crit1 > crit2) { int t = crit1; crit1 = crit2; crit2 = t; } + assert(crit1 <= crit2); + assert(x <= crit2); // next1 or next2 must be the limit value + x += 1; + if (x > D) { + if (x < crit1-D) { + x += (x << 1) >> downShift; // giant step toward crit1-D + if (x > crit1-D) x = crit1-D; + } else if (x >= crit1+D && x < crit2-D) { + x += (x << 1) >> downShift; // giant step toward crit2-D + if (x > crit2-D) x = crit2-D; + } + } + return x; + } + + public static void main(String[] av) { + boolean verbose = (av.length != 0); + muzzle = (verbose? 0: 1); + if (muzzle == 0) + System.out.println("test values: "+Arrays.toString(Arrays.copyOf(testValues, 5))+"..."); + + simpleTests(); + + muzzle = 0; // turn on print statements (affects failures only) + + fullTests(); + if (verbose) + System.out.println("ran "+testCasesRun+" tests, avg len=" + +(float)consing/testCasesRun); + + // test much larger arrays, more sparsely + maxLen = 500; + shortStepsNear = 2; + downShift = 0; + testCasesRun = 0; + consing = 0; + fullTests(); + if (verbose) + System.out.println("ran "+testCasesRun+" tests, avg len=" + +(float)consing/testCasesRun); + } + + static void fullTests() { + for (Class<?> c : allTypes) { + fullTests(maxLen, c); + } + } + + // We must run all the our tests on each of 8 distinct primitive types, + // and two reference types (Object, String) for good measure. + // This would be a pain to write out by hand, statically typed. + // So, use reflection. Following are the tables of methods we use. + // (The initial simple tests exercise enough of the static typing + // features of the API to ensure that they compile as advertised.) + + static Object coerceToObject(int x) { return (x & 0xF) == 0? null: new Integer(x); } + static String coerceToString(int x) { return (x == 0)? null: Integer.toHexString(x); } + static Integer coerceToInteger(int x) { return (x == 0)? null: x; } + static byte coerceToByte(int x) { return (byte)x; } + static short coerceToShort(int x) { return (short)x; } + static int coerceToInt(int x) { return x; } + static long coerceToLong(int x) { return x; } + static char coerceToChar(int x) { return (char)x; } + static float coerceToFloat(int x) { return x; } + static double coerceToDouble(int x) { return x; } + static boolean coerceToBoolean(int x) { return (x&1) != 0; } + + static Integer[] copyOfIntegerArray(Object[] a, int len) { + // This guy exercises the API based on a type-token. + // Note the static typing. + return Arrays.copyOf(a, len, Integer[].class); + } + static Integer[] copyOfIntegerArrayRange(Object[] a, int m, int n) { + // This guy exercises the API based on a type-token. + // Note the static typing. + return Arrays.copyOfRange(a, m, n, Integer[].class); + } + + static final List<Class<?>> allTypes + = Arrays.asList(new Class<?>[] + { Object.class, String.class, Integer.class, + byte.class, short.class, int.class, long.class, + char.class, float.class, double.class, + boolean.class + }); + static final HashMap<Class<?>,Method> coercers; + static final HashMap<Class<?>,Method> cloners; + static final HashMap<Class<?>,Method> cloneRangers; + static final HashMap<Class<?>,Method> toStrings; + static final HashMap<Class<?>,Object> nullValues; + static { + coercers = new HashMap<Class<?>,Method>(); + Method[] testMethods = CopyMethods.class.getDeclaredMethods(); + Method cia = null, ciar = null; + for (int i = 0; i < testMethods.length; i++) { + Method m = testMethods[i]; + if (!Modifier.isStatic(m.getModifiers())) continue; + Class<?> rt = m.getReturnType(); + if (m.getName().startsWith("coerceTo") && allTypes.contains(rt)) + coercers.put(m.getReturnType(), m); + if (m.getName().equals("copyOfIntegerArray")) + cia = m; + if (m.getName().equals("copyOfIntegerArrayRange")) + ciar = m; + } + Method[] arrayMethods = Arrays.class.getDeclaredMethods(); + cloners = new HashMap<Class<?>,Method>(); + cloneRangers = new HashMap<Class<?>,Method>(); + toStrings = new HashMap<Class<?>,Method>(); + for (int i = 0; i < arrayMethods.length; i++) { + Method m = arrayMethods[i]; + if (!Modifier.isStatic(m.getModifiers())) continue; + Class<?> rt = m.getReturnType(); + if (m.getName().equals("copyOf") + && m.getParameterTypes().length == 2) + cloners.put(rt.getComponentType(), m); + if (m.getName().equals("copyOfRange") + && m.getParameterTypes().length == 3) + cloneRangers.put(rt.getComponentType(), m); + if (m.getName().equals("toString")) { + Class<?> pt = m.getParameterTypes()[0]; + toStrings.put(pt.getComponentType(), m); + } + } + cloners.put(String.class, cloners.get(Object.class)); + cloneRangers.put(String.class, cloneRangers.get(Object.class)); + assert(cia != null); + cloners.put(Integer.class, cia); + assert(ciar != null); + cloneRangers.put(Integer.class, ciar); + nullValues = new HashMap<Class<?>,Object>(); + for (Class<?> c : allTypes) { + nullValues.put(c, invoke(coercers.get(c), 0)); + } + } +} diff --git a/ojluni/src/test/java/util/Arrays/Correct.java b/ojluni/src/test/java/util/Arrays/Correct.java new file mode 100644 index 00000000000..1c4ddcd0457 --- /dev/null +++ b/ojluni/src/test/java/util/Arrays/Correct.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2002, 2014, 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 4726380 8037097 + * @summary Check that different sorts give equivalent results. + * @run testng Correct + * @key randomness + */ + +package test.java.util.Arrays; + +import java.util.*; + +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; +import static org.testng.Assert.fail; +import static org.testng.Assert.assertEquals; + +public class Correct { + + static final Random rnd = new Random(); + static final int ITERATIONS = 1000; + static final int TEST_SIZE = 1000; + + @Test + public void testDefaultSort() { + for (int i=0; i<ITERATIONS; i++) { + int size = rnd.nextInt(TEST_SIZE) + 1; + Integer[] array1 = getIntegerArray(size); + Integer[] array2 = Arrays.copyOf(array1, array1.length); + Arrays.sort(array1, array1.length/3, array1.length/2); + stupidSort(array2, array2.length/3, array2.length/2); + assertEquals(array1, array2, "Arrays did not match. size=" + size); + } + } + + @Test(dataProvider = "Comparators") + public void testComparatorSort(Comparator<Integer> comparator) { + for (int i=0; i<ITERATIONS; i++) { + int size = rnd.nextInt(TEST_SIZE) + 1; + Integer[] array1 = getIntegerArray(size); + Integer[] array2 = Arrays.copyOf(array1, array1.length); + Arrays.sort(array1, array1.length/3, array1.length/2, comparator); + stupidSort(array2, array2.length/3, array2.length/2, comparator); + assertEquals(array1, array2, "Arrays did not match. size=" + size); + } + } + + static Integer[] getIntegerArray(int size) { + Integer[] blah = new Integer[size]; + for (int x=0; x<size; x++) { + blah[x] = new Integer(rnd.nextInt()); + } + return blah; + } + + static void stupidSort(Integer[] a1, int from, int to) { + if (from > to - 1 ) + return; + + for (int x=from; x<to; x++) { + Integer lowest = a1[x]; + int lowestIndex = x; + for (int y=x + 1; y<to; y++) { + if (((Comparable)a1[y]).compareTo((Comparable)lowest) < 0) { + lowest = a1[y]; + lowestIndex = y; + } + } + if (lowestIndex != x) { + swap(a1, x, lowestIndex); + } + } + } + + static void stupidSort(Integer[] a1, int from, int to, Comparator<Integer> comparator) { + if (from > to - 1 ) + return; + + for (int x=from; x<to; x++) { + Integer lowest = a1[x]; + int lowestIndex = x; + for (int y=x + 1; y<to; y++) { + if (comparator.compare(a1[y], lowest) < 0) { + lowest = a1[y]; + lowestIndex = y; + } + } + if (lowestIndex != x) { + swap(a1, x, lowestIndex); + } + } + } + + static <T> void swap(T[] x, int a, int b) { + T t = x[a]; + x[a] = x[b]; + x[b] = t; + } + + @DataProvider(name = "Comparators", parallel = true) + public static Iterator<Object[]> comparators() { + Object[][] comparators = new Object[][] { + new Object[] { Comparator.naturalOrder() }, + new Object[] { Comparator.<Integer>naturalOrder().reversed() }, + new Object[] { STANDARD_ORDER }, + new Object[] { STANDARD_ORDER.reversed() }, + new Object[] { REVERSE_ORDER }, + new Object[] { REVERSE_ORDER.reversed() }, + new Object[] { Comparator.comparingInt(Integer::intValue) } + }; + + return Arrays.asList(comparators).iterator(); + } + + private static final Comparator<Integer> STANDARD_ORDER = new Comparator<Integer>() { + public int compare(Integer o1, Integer o2) { + return o1.compareTo(o2); + } + }; + + private static final Comparator<Integer> REVERSE_ORDER = new Comparator<Integer>() { + public int compare(Integer o1, Integer o2) { + return - o1.compareTo(o2); + } + }; +} diff --git a/ojluni/src/test/java/util/Arrays/Fill.java b/ojluni/src/test/java/util/Arrays/Fill.java new file mode 100644 index 00000000000..930c0b0b258 --- /dev/null +++ b/ojluni/src/test/java/util/Arrays/Fill.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2005, 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 4229892 + * @summary Arrays.fill(Object[], ...) should throw ArrayStoreException + * @author Martin Buchholz + */ + +package test.java.util.Arrays; + +import java.io.*; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; + +@SuppressWarnings("ArrayFillIncompatibleType") +public class Fill { + private static void realMain(String[] args) throws Throwable { + try { + Arrays.fill(new Integer[3], "foo"); + fail("Expected ArrayStoreException"); + } + catch (ArrayStoreException e) { pass(); } + catch (Throwable t) { unexpected(t); } + + try { + Arrays.fill(new Integer[3], 0, 2, "foo"); + fail("Expected ArrayStoreException"); + } + catch (ArrayStoreException e) { pass(); } + catch (Throwable t) { unexpected(t); } + + try { + Arrays.fill(new Integer[3], 0, 4, "foo"); + fail("Expected ArrayIndexOutOfBoundsException"); + } + catch (ArrayIndexOutOfBoundsException e) { pass(); } + catch (Throwable t) { unexpected(t); } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void check(boolean cond) {if (cond) pass(); else fail();} + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/ojluni/src/test/java/util/Arrays/FloatDoubleOrder.java b/ojluni/src/test/java/util/Arrays/FloatDoubleOrder.java new file mode 100644 index 00000000000..af721e3a4d4 --- /dev/null +++ b/ojluni/src/test/java/util/Arrays/FloatDoubleOrder.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 1998, 2007, 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 4143272 6548425 + * @summary The natural ordering on Float and Double was not even a partial + * order (i.e., it violated the contract of Comparable.compareTo). + * Now it's a total ordering. Arrays.sort(double[]) + * and Arrays.sort(double[]) reflect the new ordering. Also, + * Arrays.equals(double[], double[]) and + * Arrays.equals(float[], float[]) reflect the definition of + * equality used by Float and Double. + */ + +package test.java.util.Arrays; + +import java.util.*; + +@SuppressWarnings("unchecked") +public class FloatDoubleOrder { + void test(String[] args) throws Throwable { + double[] unsortedDbl = new double[] {1.0d, 3.7d, Double.NaN, -2.0d, + Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0.0d, -0.0d}; + + double[] sortedDbl = new double[] {Double.NEGATIVE_INFINITY, -2.0d, + -0.0d, 0.0d, 1.0d, 3.7d, Double.POSITIVE_INFINITY, Double.NaN}; + + List list = new ArrayList(); + for (int i=0; i<unsortedDbl.length; i++) + list.add(new Double(unsortedDbl[i])); + Collections.sort(list); + + List sortedList = new ArrayList(); + for (int i=0; i<sortedDbl.length; i++) + sortedList.add(new Double(sortedDbl[i])); + + check(list.equals(sortedList)); + + Arrays.sort(unsortedDbl); + check(Arrays.equals(unsortedDbl, sortedDbl)); + + double negNan = Double.longBitsToDouble(0xfff8000000000000L); + for (int i = 0; i < sortedDbl.length; i++) { + equal(Arrays.binarySearch(sortedDbl, sortedDbl[i]), i); + if (Double.isNaN(sortedDbl[i])) + equal(Arrays.binarySearch(sortedDbl, negNan), i); + } + + float[] unsortedFlt = new float[] {1.0f, 3.7f, Float.NaN, -2.0f, + Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, 0.0f, -0.0f}; + + float[] sortedFlt = new float[] {Float.NEGATIVE_INFINITY, -2.0f, + -0.0f, 0.0f, 1.0f, 3.7f, Float.POSITIVE_INFINITY, Float.NaN}; + + list.clear(); + for (int i=0; i<unsortedFlt.length; i++) + list.add(new Float(unsortedFlt[i])); + Collections.sort(list); + + sortedList.clear(); + for (int i=0; i<sortedFlt.length; i++) + sortedList.add(new Float(sortedFlt[i])); + + check(list.equals(sortedList)); + + Arrays.sort(unsortedFlt); + check(Arrays.equals(unsortedFlt, sortedFlt)); + + float negNaN = Float.intBitsToFloat(0xFfc00000); + for (int i = 0; i < sortedDbl.length; i++) { + equal(Arrays.binarySearch(sortedFlt, sortedFlt[i]), i); + if (Float.isNaN(sortedFlt[i])) + equal(Arrays.binarySearch(sortedFlt, negNaN), i); + } + + + // 6548425: Arrays.sort incorrectly sorts a double array + // containing negative zeros + double[] da = {-0.0d, -0.0d, 0.0d, -0.0d}; + Arrays.sort(da, 1, 4); + check(Arrays.equals(da, new double[] {-0.0d, -0.0d, -0.0d, 0.0d})); + + float[] fa = {-0.0f, -0.0f, 0.0f, -0.0f}; + Arrays.sort(fa, 1, 4); + check(Arrays.equals(fa, new float[] {-0.0f, -0.0f, -0.0f, 0.0f})); + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new FloatDoubleOrder().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/ojluni/src/test/java/util/Arrays/SetAllTest.java b/ojluni/src/test/java/util/Arrays/SetAllTest.java new file mode 100644 index 00000000000..b0692cb5652 --- /dev/null +++ b/ojluni/src/test/java/util/Arrays/SetAllTest.java @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2013, 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 8012650 + * @summary Unit test for setAll, parallelSetAll variants + * @run testng SetAllTest + */ + +package test.java.util.Arrays; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.function.IntFunction; +import java.util.function.IntToDoubleFunction; +import java.util.function.IntToLongFunction; +import java.util.function.IntUnaryOperator; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertSame; +import static org.testng.Assert.fail; + +@Test +public class SetAllTest { + private static final IntFunction<String> toString = i -> "N" + Integer.valueOf(i); + private static final IntFunction<String> fillString = i -> "X"; + private static final String[] r0 = {}; + private static final String[] r1 = { "N0" }; + private static final String[] r10 = { "N0", "N1", "N2", "N3", "N4", "N5", "N6", "N7", "N8", "N9" }; + + private Object[][] stringData = new Object[][] { + { "empty", 0, toString, r0 }, + { "one", 1, toString, r1 }, + { "ten", 10, toString, r10 }, + { "fill", 3, fillString, new String[] { "X", "X", "X" }} + }; + + private static final IntUnaryOperator toInt = i -> i << 1; + private static final IntUnaryOperator fillInt = i -> 99; + private static final int[] ir0 = {}; + private static final int[] ir1 = { 0 }; + private static final int[] ir10 = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 }; + private Object[][] intData = new Object[][] { + { "empty", 0, toInt, ir0 }, + { "one", 1, toInt, ir1 }, + { "ten", 10, toInt, ir10 }, + { "fill", 3, fillInt, new int[] { 99, 99, 99 }} + }; + + private static final IntToLongFunction toLong = i -> i << 1; + private static final IntToLongFunction fillLong = i -> 9999L; + private static final long[] lr0 = {}; + private static final long[] lr1 = { 0L }; + private static final long[] lr10 = { 0L, 2L, 4L, 6L, 8L, 10L, 12L, 14L, 16L, 18L }; + private Object[][] longData = new Object[][] { + { "empty", 0, toLong, lr0 }, + { "one", 1, toLong, lr1 }, + { "ten", 10, toLong, lr10 }, + { "fill", 3, fillLong, new long[] { 9999L, 9999L, 9999L }} + }; + + private static final IntToDoubleFunction toDouble = i -> i * 1.1; + private static final IntToDoubleFunction fillDouble = i -> 3.14; + private static final double[] dr0 = {}; + private static final double[] dr1 = { 0.0 }; + private static final double[] dr10 = { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 }; + private Object[][] doubleData = new Object[][] { + { "empty", 0, toDouble, dr0 }, + { "one", 1, toDouble, dr1 }, + { "ten", 10, toDouble, dr10 }, + { "fill", 3, fillDouble, new double[] { 3.14, 3.14, 3.14 }} + }; + + @DataProvider(name="string") + public Object[][] stringTests() { return stringData; } + + @DataProvider(name="int") + public Object[][] intTests() { return intData; } + + @DataProvider(name="long") + public Object[][] longTests() { return longData; } + + @DataProvider(name="double") + public Object[][] doubleTests() { return doubleData; } + + @Test(dataProvider = "string") + public void testSetAllString(String name, int size, IntFunction<String> generator, String[] expected) { + String[] result = new String[size]; + Arrays.setAll(result, generator); + assertEquals(result, expected, "setAll(String[], IntFunction<String>) case " + name + " failed."); + + // ensure fresh array + result = new String[size]; + Arrays.parallelSetAll(result, generator); + assertEquals(result, expected, "parallelSetAll(String[], IntFunction<String>) case " + name + " failed."); + } + + @Test(dataProvider = "int") + public void testSetAllInt(String name, int size, IntUnaryOperator generator, int[] expected) { + int[] result = new int[size]; + Arrays.setAll(result, generator); + assertEquals(result, expected, "setAll(int[], IntUnaryOperator) case " + name + " failed."); + + // ensure fresh array + result = new int[size]; + Arrays.parallelSetAll(result, generator); + assertEquals(result, expected, "parallelSetAll(int[], IntUnaryOperator) case " + name + " failed."); + } + + @Test(dataProvider = "long") + public void testSetAllLong(String name, int size, IntToLongFunction generator, long[] expected) { + long[] result = new long[size]; + Arrays.setAll(result, generator); + assertEquals(result, expected, "setAll(long[], IntToLongFunction) case " + name + " failed."); + + // ensure fresh array + result = new long[size]; + Arrays.parallelSetAll(result, generator); + assertEquals(result, expected, "parallelSetAll(long[], IntToLongFunction) case " + name + " failed."); + } + + private void assertDoubleArrayEquals(double[] actual, double[] expected, double delta, String msg) { + if (actual.length != expected.length) { + fail(msg + ": length mismatch, expected " + expected.length + ", got " + actual.length); + } + + for (int i = 0; i < actual.length; i++) { + assertEquals(actual[i], expected[i], delta, msg + "(mismatch at index " + i + ")"); + } + } + + @Test(dataProvider = "double") + public void testSetAllDouble(String name, int size, IntToDoubleFunction generator, double[] expected) { + double[] result = new double[size]; + Arrays.setAll(result, generator); + assertDoubleArrayEquals(result, expected, 0.05, "setAll(double[], IntToDoubleFunction) case " + name + " failed."); + + // ensure fresh array + result = new double[size]; + Arrays.parallelSetAll(result, generator); + assertDoubleArrayEquals(result, expected, 0.05, "setAll(double[], IntToDoubleFunction) case " + name + " failed."); + } + + @Test + public void testStringSetNulls() { + String[] ar = new String[2]; + try { + Arrays.setAll(null, (IntFunction<String>) i -> "X"); + fail("Arrays.setAll(null, foo) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + try { + Arrays.parallelSetAll(null, (IntFunction<String>) i -> "X"); + fail("Arrays.parallelSetAll(null, foo) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + try { + Arrays.setAll(ar, null); + fail("Arrays.setAll(array, null) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + try { + Arrays.parallelSetAll(ar, null); + fail("Arrays.parallelSetAll(array, null) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + } + + @Test + public void testIntSetNulls() { + int[] ar = new int[2]; + try { + Arrays.setAll(null, (IntUnaryOperator) i -> i); + fail("Arrays.setAll(null, foo) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + try { + Arrays.parallelSetAll(null, (IntUnaryOperator) i -> i); + fail("Arrays.parallelSetAll(null, foo) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + try { + Arrays.setAll(ar, null); + fail("Arrays.setAll(array, null) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + try { + Arrays.parallelSetAll(ar, null); + fail("Arrays.parallelSetAll(array, null) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + } + + @Test + public void testLongSetNulls() { + long[] ar = new long[2]; + try { + Arrays.setAll(null, (IntToLongFunction) i -> Long.MAX_VALUE); + fail("Arrays.setAll(null, foo) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + try { + Arrays.parallelSetAll(null, (IntToLongFunction) i -> Long.MAX_VALUE); + fail("Arrays.parallelSetAll(null, foo) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + try { + Arrays.setAll(ar, null); + fail("Arrays.setAll(array, null) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + try { + Arrays.parallelSetAll(ar, null); + fail("Arrays.parallelSetAll(array, null) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + } + + @Test + public void testDoubleSetNulls() { + double[] ar = new double[2]; + try { + Arrays.setAll(null, (IntToDoubleFunction) i -> Math.E); + fail("Arrays.setAll(null, foo) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + try { + Arrays.parallelSetAll(null, (IntToDoubleFunction) i -> Math.E); + fail("Arrays.parallelSetAll(null, foo) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + try { + Arrays.setAll(ar, null); + fail("Arrays.setAll(array, null) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + try { + Arrays.parallelSetAll(ar, null); + fail("Arrays.parallelSetAll(array, null) should throw NPE"); + } catch (NullPointerException npe) { + // expected + } + } +} diff --git a/ojluni/src/test/java/util/Arrays/Sorting.java b/ojluni/src/test/java/util/Arrays/Sorting.java new file mode 100644 index 00000000000..c025da9e919 --- /dev/null +++ b/ojluni/src/test/java/util/Arrays/Sorting.java @@ -0,0 +1,2069 @@ +/* + * Copyright (c) 2009, 2019, 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 + * @compile/module=java.base java/util/SortingHelper.java + * @bug 6880672 6896573 6899694 6976036 7013585 7018258 8003981 8226297 + * @build Sorting + * @run main Sorting -shortrun + * @summary Exercise Arrays.sort, Arrays.parallelSort + * + * @author Vladimir Yaroslavskiy + * @author Jon Bentley + * @author Josh Bloch + */ + +package test.java.util.Arrays; + +import android.platform.test.annotations.LargeTest; + +import java.io.PrintStream; +import java.util.Comparator; +import java.util.Random; + +@LargeTest +@SuppressWarnings("IdentityBinaryExpression") +public class Sorting { + + private static final PrintStream out = System.out; + private static final PrintStream err = System.err; + + // Array lengths used in a long run (default) + private static final int[] LONG_RUN_LENGTHS = { + 1, 3, 8, 21, 55, 100, 1_000, 10_000, 100_000 }; + + // Array lengths used in a short run + private static final int[] SHORT_RUN_LENGTHS = { + 1, 8, 55, 100, 10_000 }; + + // Random initial values used in a long run (default) + private static final TestRandom[] LONG_RUN_RANDOMS = { + TestRandom.BABA, TestRandom.DEDA, TestRandom.C0FFEE }; + + // Random initial values used in a short run + private static final TestRandom[] SHORT_RUN_RANDOMS = { + TestRandom.C0FFEE }; + + // Constants used in subarray sorting + private static final int A380 = 0xA380; + private static final int B747 = 0xB747; + + public static void main(String[] args) { + long start = System.currentTimeMillis(); + // Android-changed: coverage run with this flag set to true takes too + // much time. Locally it was killed after 45 minutes. + // boolean shortRun = args.length > 0 && args[0].equals("-shortrun"); + boolean shortRun = true; + + int[] lengths = shortRun ? SHORT_RUN_LENGTHS : LONG_RUN_LENGTHS; + TestRandom[] randoms = shortRun ? SHORT_RUN_RANDOMS : LONG_RUN_RANDOMS; + + new InnerState(SortingHelper.DUAL_PIVOT_QUICKSORT, randoms, lengths).testCore(); + new InnerState(SortingHelper.PARALLEL_SORT, randoms, lengths).testCore(); + new InnerState(SortingHelper.HEAP_SORT, randoms, lengths).testBasic(); + new InnerState(SortingHelper.ARRAYS_SORT, randoms, lengths).testAll(); + new InnerState(SortingHelper.ARRAYS_PARALLEL_SORT, randoms, lengths).testAll(); + + long end = System.currentTimeMillis(); + out.format("PASSED in %d sec.\n", (end - start) / 1000); + } + + // Android-changed: runner can't run test with non-default contructor. + private static class InnerState { + private final SortingHelper sortingHelper; + private final TestRandom[] randoms; + private final int[] lengths; + private Object[] gold; + private Object[] test; + + public InnerState(SortingHelper sortingHelper, TestRandom[] randoms, int[] lengths) { + this.sortingHelper = sortingHelper; + this.randoms = randoms; + this.lengths = lengths; + } + + private void testBasic() { + testEmptyArray(); + + for (int length : lengths) { + createData(length); + testBasic(length); + } + } + + private void testBasic(int length) { + for (TestRandom random : randoms) { + testWithInsertionSort(length, random); + testWithCheckSum(length, random); + testWithScrambling(length, random); + } + } + + private void testCore() { + for (int length : lengths) { + createData(length); + testCore(length); + } + } + + private void testCore(int length) { + testBasic(length); + + for (TestRandom random : randoms) { + testMergingSort(length, random); + testSubArray(length, random); + testNegativeZero(length, random); + testFloatingPointSorting(length, random); + } + } + + private void testAll() { + for (int length : lengths) { + createData(length); + testAll(length); + } + } + + private void testAll(int length) { + testCore(length); + + for (TestRandom random : randoms) { + testRange(length, random); + testStability(length, random); + } + } + + private void testEmptyArray() { + testEmptyAndNullIntArray(); + testEmptyAndNullLongArray(); + testEmptyAndNullByteArray(); + testEmptyAndNullCharArray(); + testEmptyAndNullShortArray(); + testEmptyAndNullFloatArray(); + testEmptyAndNullDoubleArray(); + } + + private void testStability(int length, TestRandom random) { + printTestName("Test stability", random, length); + + Pair[] a = build(length, random); + sortingHelper.sort(a); + checkSorted(a); + checkStable(a); + + a = build(length, random); + sortingHelper.sort(a, pairComparator); + checkSorted(a); + checkStable(a); + + out.println(); + } + + private void testEmptyAndNullIntArray() { + sortingHelper.sort(new int[]{}); + sortingHelper.sort(new int[]{}, 0, 0); + + try { + sortingHelper.sort(null); + } catch (NullPointerException expected) { + try { + sortingHelper.sort(null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + fail(sortingHelper + "(int[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + fail(sortingHelper + "(int[]) shouldn't catch null array"); + } + + private void testEmptyAndNullLongArray() { + sortingHelper.sort(new long[]{}); + sortingHelper.sort(new long[]{}, 0, 0); + + try { + sortingHelper.sort(null); + } catch (NullPointerException expected) { + try { + sortingHelper.sort(null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + fail(sortingHelper + "(long[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + fail(sortingHelper + "(long[]) shouldn't catch null array"); + } + + private void testEmptyAndNullByteArray() { + sortingHelper.sort(new byte[]{}); + sortingHelper.sort(new byte[]{}, 0, 0); + + try { + sortingHelper.sort(null); + } catch (NullPointerException expected) { + try { + sortingHelper.sort(null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + fail(sortingHelper + "(byte[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + fail(sortingHelper + "(byte[]) shouldn't catch null array"); + } + + private void testEmptyAndNullCharArray() { + sortingHelper.sort(new char[]{}); + sortingHelper.sort(new char[]{}, 0, 0); + + try { + sortingHelper.sort(null); + } catch (NullPointerException expected) { + try { + sortingHelper.sort(null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + fail(sortingHelper + "(char[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + fail(sortingHelper + "(char[]) shouldn't catch null array"); + } + + private void testEmptyAndNullShortArray() { + sortingHelper.sort(new short[]{}); + sortingHelper.sort(new short[]{}, 0, 0); + + try { + sortingHelper.sort(null); + } catch (NullPointerException expected) { + try { + sortingHelper.sort(null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + fail(sortingHelper + "(short[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + fail(sortingHelper + "(short[]) shouldn't catch null array"); + } + + private void testEmptyAndNullFloatArray() { + sortingHelper.sort(new float[]{}); + sortingHelper.sort(new float[]{}, 0, 0); + + try { + sortingHelper.sort(null); + } catch (NullPointerException expected) { + try { + sortingHelper.sort(null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + fail(sortingHelper + "(float[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + fail(sortingHelper + "(float[]) shouldn't catch null array"); + } + + private void testEmptyAndNullDoubleArray() { + sortingHelper.sort(new double[]{}); + sortingHelper.sort(new double[]{}, 0, 0); + + try { + sortingHelper.sort(null); + } catch (NullPointerException expected) { + try { + sortingHelper.sort(null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + fail(sortingHelper + "(double[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + fail(sortingHelper + "(double[]) shouldn't catch null array"); + } + + private void testSubArray(int length, TestRandom random) { + if (length < 4) { + return; + } + for (int m = 1; m < length / 2; m <<= 1) { + int fromIndex = m; + int toIndex = length - m; + + prepareSubArray((int[]) gold[0], fromIndex, toIndex); + convertData(length); + + for (int i = 0; i < test.length; i++) { + printTestName("Test subarray", random, length, + ", m = " + m + ", " + getType(i)); + sortingHelper.sort(test[i], fromIndex, toIndex); + checkSubArray(test[i], fromIndex, toIndex); + } + } + out.println(); + } + + private void testRange(int length, TestRandom random) { + if (length < 2) { + return; + } + for (int m = 1; m < length; m <<= 1) { + for (int i = 1; i <= length; i++) { + ((int[]) gold[0])[i - 1] = i % m + m % i; + } + convertData(length); + + for (int i = 0; i < test.length; i++) { + printTestName("Test range check", random, length, + ", m = " + m + ", " + getType(i)); + checkRange(test[i], m); + } + } + out.println(); + } + + private void checkSorted(Pair[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i].getKey() > a[i + 1].getKey()) { + fail("Array is not sorted at " + i + "-th position: " + + a[i].getKey() + " and " + a[i + 1].getKey()); + } + } + } + + private void checkStable(Pair[] a) { + for (int i = 0; i < a.length / 4; ) { + int key1 = a[i].getKey(); + int value1 = a[i++].getValue(); + int key2 = a[i].getKey(); + int value2 = a[i++].getValue(); + int key3 = a[i].getKey(); + int value3 = a[i++].getValue(); + int key4 = a[i].getKey(); + int value4 = a[i++].getValue(); + + if (!(key1 == key2 && key2 == key3 && key3 == key4)) { + fail("Keys are different " + key1 + ", " + key2 + ", " + + key3 + ", " + key4 + " at position " + i); + } + if (!(value1 < value2 && value2 < value3 && value3 < value4)) { + fail("Sorting is not stable at position " + i + + ". Second values have been changed: " + value1 + ", " + + value2 + ", " + value3 + ", " + value4); + } + } + } + + private Pair[] build(int length, Random random) { + Pair[] a = new Pair[length * 4]; + + for (int i = 0; i < a.length; ) { + int key = random.nextInt(); + a[i++] = new Pair(key, 1); + a[i++] = new Pair(key, 2); + a[i++] = new Pair(key, 3); + a[i++] = new Pair(key, 4); + } + return a; + } + + private void testWithInsertionSort(int length, TestRandom random) { + if (length > 1000) { + return; + } + for (int m = 1; m <= length; m <<= 1) { + for (UnsortedBuilder builder : UnsortedBuilder.values()) { + builder.build((int[]) gold[0], m, random); + convertData(length); + + for (int i = 0; i < test.length; i++) { + printTestName("Test with insertion sort", random, length, + ", m = " + m + ", " + getType(i) + " " + builder); + sortingHelper.sort(test[i]); + sortByInsertionSort(gold[i]); + compare(test[i], gold[i]); + } + } + } + out.println(); + } + + private void testMergingSort(int length, TestRandom random) { + if (length < (4 << 10)) { // DualPivotQuicksort.MIN_TRY_MERGE_SIZE + return; + } + final int PERIOD = 50; + + for (int m = PERIOD - 2; m <= PERIOD + 2; m++) { + for (MergingBuilder builder : MergingBuilder.values()) { + builder.build((int[]) gold[0], m); + convertData(length); + + for (int i = 0; i < test.length; i++) { + printTestName("Test merging sort", random, length, + ", m = " + m + ", " + getType(i) + " " + builder); + sortingHelper.sort(test[i]); + checkSorted(test[i]); + } + } + } + out.println(); + } + + private void testWithCheckSum(int length, TestRandom random) { + for (int m = 1; m <= length; m <<= 1) { + for (UnsortedBuilder builder : UnsortedBuilder.values()) { + builder.build((int[]) gold[0], m, random); + convertData(length); + + for (int i = 0; i < test.length; i++) { + printTestName("Test with check sum", random, length, + ", m = " + m + ", " + getType(i) + " " + builder); + sortingHelper.sort(test[i]); + checkWithCheckSum(test[i], gold[i]); + } + } + } + out.println(); + } + + private void testWithScrambling(int length, TestRandom random) { + for (int m = 1; m <= length; m <<= 1) { + for (SortedBuilder builder : SortedBuilder.values()) { + builder.build((int[]) gold[0], m); + convertData(length); + + for (int i = 0; i < test.length; i++) { + printTestName("Test with scrambling", random, length, + ", m = " + m + ", " + getType(i) + " " + builder); + scramble(test[i], random); + sortingHelper.sort(test[i]); + compare(test[i], gold[i]); + } + } + } + out.println(); + } + + private void testNegativeZero(int length, TestRandom random) { + for (int i = 5; i < test.length; i++) { + printTestName("Test negative zero -0.0", random, length, " " + getType(i)); + + NegativeZeroBuilder builder = NegativeZeroBuilder.values()[i - 5]; + builder.build(test[i], random); + + sortingHelper.sort(test[i]); + checkNegativeZero(test[i]); + } + out.println(); + } + + private void testFloatingPointSorting(int length, TestRandom random) { + if (length < 2) { + return; + } + final int MAX = 13; + + for (int a = 0; a < MAX; a++) { + for (int g = 0; g < MAX; g++) { + for (int z = 0; z < MAX; z++) { + for (int n = 0; n < MAX; n++) { + for (int p = 0; p < MAX; p++) { + if (a + g + z + n + p != length) { + continue; + } + for (int i = 5; i < test.length; i++) { + printTestName("Test float-pointing sorting", random, length, + ", a = " + a + ", g = " + g + ", z = " + z + + ", n = " + n + ", p = " + p + ", " + getType( + i)); + FloatingPointBuilder builder = + FloatingPointBuilder.values()[i - 5]; + builder.build(gold[i], a, g, z, n, p, random); + copy(test[i], gold[i]); + scramble(test[i], random); + sortingHelper.sort(test[i]); + compare(test[i], gold[i], a, n, g); + } + } + } + } + } + } + + for (int m = 13; m > 4; m--) { + int t = length / m; + int g = t, z = t, n = t, p = t; + int a = length - g - z - n - p; + + for (int i = 5; i < test.length; i++) { + printTestName("Test float-pointing sorting", random, length, + ", a = " + a + ", g = " + g + ", z = " + z + + ", n = " + n + ", p = " + p + ", " + getType(i)); + FloatingPointBuilder builder = FloatingPointBuilder.values()[i - 5]; + builder.build(gold[i], a, g, z, n, p, random); + copy(test[i], gold[i]); + scramble(test[i], random); + sortingHelper.sort(test[i]); + compare(test[i], gold[i], a, n, g); + } + } + out.println(); + } + + private void prepareSubArray(int[] a, int fromIndex, int toIndex) { + for (int i = 0; i < fromIndex; i++) { + a[i] = A380; + } + int middle = (fromIndex + toIndex) >>> 1; + int k = 0; + + for (int i = fromIndex; i < middle; i++) { + a[i] = k++; + } + + for (int i = middle; i < toIndex; i++) { + a[i] = k--; + } + + for (int i = toIndex; i < a.length; i++) { + a[i] = B747; + } + } + + private void scramble(Object a, Random random) { + if (a instanceof int[]) { + scramble((int[]) a, random); + } else if (a instanceof long[]) { + scramble((long[]) a, random); + } else if (a instanceof byte[]) { + scramble((byte[]) a, random); + } else if (a instanceof char[]) { + scramble((char[]) a, random); + } else if (a instanceof short[]) { + scramble((short[]) a, random); + } else if (a instanceof float[]) { + scramble((float[]) a, random); + } else if (a instanceof double[]) { + scramble((double[]) a, random); + } else { + fail("Unknown type of array: " + a.getClass().getName()); + } + } + + private void scramble(int[] a, Random random) { + for (int i = 0; i < a.length * 7; i++) { + swap(a, random.nextInt(a.length), random.nextInt(a.length)); + } + } + + private void scramble(long[] a, Random random) { + for (int i = 0; i < a.length * 7; i++) { + swap(a, random.nextInt(a.length), random.nextInt(a.length)); + } + } + + private void scramble(byte[] a, Random random) { + for (int i = 0; i < a.length * 7; i++) { + swap(a, random.nextInt(a.length), random.nextInt(a.length)); + } + } + + private void scramble(char[] a, Random random) { + for (int i = 0; i < a.length * 7; i++) { + swap(a, random.nextInt(a.length), random.nextInt(a.length)); + } + } + + private void scramble(short[] a, Random random) { + for (int i = 0; i < a.length * 7; i++) { + swap(a, random.nextInt(a.length), random.nextInt(a.length)); + } + } + + private void scramble(float[] a, Random random) { + for (int i = 0; i < a.length * 7; i++) { + swap(a, random.nextInt(a.length), random.nextInt(a.length)); + } + } + + private void scramble(double[] a, Random random) { + for (int i = 0; i < a.length * 7; i++) { + swap(a, random.nextInt(a.length), random.nextInt(a.length)); + } + } + + private void swap(int[] a, int i, int j) { + int t = a[i]; + a[i] = a[j]; + a[j] = t; + } + + private void swap(long[] a, int i, int j) { + long t = a[i]; + a[i] = a[j]; + a[j] = t; + } + + private void swap(byte[] a, int i, int j) { + byte t = a[i]; + a[i] = a[j]; + a[j] = t; + } + + private void swap(char[] a, int i, int j) { + char t = a[i]; + a[i] = a[j]; + a[j] = t; + } + + private void swap(short[] a, int i, int j) { + short t = a[i]; + a[i] = a[j]; + a[j] = t; + } + + private void swap(float[] a, int i, int j) { + float t = a[i]; + a[i] = a[j]; + a[j] = t; + } + + private void swap(double[] a, int i, int j) { + double t = a[i]; + a[i] = a[j]; + a[j] = t; + } + + private void checkWithCheckSum(Object test, Object gold) { + checkSorted(test); + checkCheckSum(test, gold); + } + + private void fail(String message) { + err.format("\n*** TEST FAILED ***\n\n%s\n\n", message); + throw new RuntimeException("Test failed"); + } + + private void checkNegativeZero(Object a) { + if (a instanceof float[]) { + checkNegativeZero((float[]) a); + } else if (a instanceof double[]) { + checkNegativeZero((double[]) a); + } else { + fail("Unknown type of array: " + a.getClass().getName()); + } + } + + private void checkNegativeZero(float[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (Float.floatToRawIntBits(a[i]) == 0 && Float.floatToRawIntBits(a[i + 1]) < 0) { + fail(a[i] + " before " + a[i + 1] + " at position " + i); + } + } + } + + private void checkNegativeZero(double[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (Double.doubleToRawLongBits(a[i]) == 0 && Double.doubleToRawLongBits(a[i + 1]) + < 0) { + fail(a[i] + " before " + a[i + 1] + " at position " + i); + } + } + } + + private void compare(Object a, Object b, int numNaN, int numNeg, int numNegZero) { + if (a instanceof float[]) { + compare((float[]) a, (float[]) b, numNaN, numNeg, numNegZero); + } else if (a instanceof double[]) { + compare((double[]) a, (double[]) b, numNaN, numNeg, numNegZero); + } else { + fail("Unknown type of array: " + a.getClass().getName()); + } + } + + private void compare(float[] a, float[] b, int numNaN, int numNeg, int numNegZero) { + for (int i = a.length - numNaN; i < a.length; i++) { + if (a[i] == a[i]) { + fail("There must be NaN instead of " + a[i] + " at position " + i); + } + } + final int NEGATIVE_ZERO = Float.floatToIntBits(-0.0f); + + for (int i = numNeg; i < numNeg + numNegZero; i++) { + if (NEGATIVE_ZERO != Float.floatToIntBits(a[i])) { + fail("There must be -0.0 instead of " + a[i] + " at position " + i); + } + } + + for (int i = 0; i < a.length - numNaN; i++) { + if (a[i] != b[i]) { + fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i); + } + } + } + + private void compare(double[] a, double[] b, int numNaN, int numNeg, int numNegZero) { + for (int i = a.length - numNaN; i < a.length; i++) { + if (a[i] == a[i]) { + fail("There must be NaN instead of " + a[i] + " at position " + i); + } + } + final long NEGATIVE_ZERO = Double.doubleToLongBits(-0.0d); + + for (int i = numNeg; i < numNeg + numNegZero; i++) { + if (NEGATIVE_ZERO != Double.doubleToLongBits(a[i])) { + fail("There must be -0.0 instead of " + a[i] + " at position " + i); + } + } + + for (int i = 0; i < a.length - numNaN; i++) { + if (a[i] != b[i]) { + fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i); + } + } + } + + private void compare(Object a, Object b) { + if (a instanceof int[]) { + compare((int[]) a, (int[]) b); + } else if (a instanceof long[]) { + compare((long[]) a, (long[]) b); + } else if (a instanceof byte[]) { + compare((byte[]) a, (byte[]) b); + } else if (a instanceof char[]) { + compare((char[]) a, (char[]) b); + } else if (a instanceof short[]) { + compare((short[]) a, (short[]) b); + } else if (a instanceof float[]) { + compare((float[]) a, (float[]) b); + } else if (a instanceof double[]) { + compare((double[]) a, (double[]) b); + } else { + fail("Unknown type of array: " + a.getClass().getName()); + } + } + + private void compare(int[] a, int[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i); + } + } + } + + private void compare(long[] a, long[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i); + } + } + } + + private void compare(byte[] a, byte[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i); + } + } + } + + private void compare(char[] a, char[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i); + } + } + } + + private void compare(short[] a, short[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i); + } + } + } + + private void compare(float[] a, float[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i); + } + } + } + + private void compare(double[] a, double[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i); + } + } + } + + private String getType(int i) { + Object a = test[i]; + + if (a instanceof int[]) { + return "INT "; + } + if (a instanceof long[]) { + return "LONG "; + } + if (a instanceof byte[]) { + return "BYTE "; + } + if (a instanceof char[]) { + return "CHAR "; + } + if (a instanceof short[]) { + return "SHORT "; + } + if (a instanceof float[]) { + return "FLOAT "; + } + if (a instanceof double[]) { + return "DOUBLE"; + } + fail("Unknown type of array: " + a.getClass().getName()); + return null; + } + + private void checkSorted(Object a) { + if (a instanceof int[]) { + checkSorted((int[]) a); + } else if (a instanceof long[]) { + checkSorted((long[]) a); + } else if (a instanceof byte[]) { + checkSorted((byte[]) a); + } else if (a instanceof char[]) { + checkSorted((char[]) a); + } else if (a instanceof short[]) { + checkSorted((short[]) a); + } else if (a instanceof float[]) { + checkSorted((float[]) a); + } else if (a instanceof double[]) { + checkSorted((double[]) a); + } else { + fail("Unknown type of array: " + a.getClass().getName()); + } + } + + private void checkSorted(int[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i] > a[i + 1]) { + fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i + + 1]); + } + } + } + + private void checkSorted(long[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i] > a[i + 1]) { + fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i + + 1]); + } + } + } + + private void checkSorted(byte[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i] > a[i + 1]) { + fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i + + 1]); + } + } + } + + private void checkSorted(char[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i] > a[i + 1]) { + fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i + + 1]); + } + } + } + + private void checkSorted(short[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i] > a[i + 1]) { + fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i + + 1]); + } + } + } + + private void checkSorted(float[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i] > a[i + 1]) { + fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i + + 1]); + } + } + } + + private void checkSorted(double[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i] > a[i + 1]) { + fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i + + 1]); + } + } + } + + private void checkCheckSum(Object test, Object gold) { + if (checkSumXor(test) != checkSumXor(gold)) { + fail("Original and sorted arrays are not identical [^]"); + } + if (checkSumPlus(test) != checkSumPlus(gold)) { + fail("Original and sorted arrays are not identical [+]"); + } + } + + private int checkSumXor(Object a) { + if (a instanceof int[]) { + return checkSumXor((int[]) a); + } + if (a instanceof long[]) { + return checkSumXor((long[]) a); + } + if (a instanceof byte[]) { + return checkSumXor((byte[]) a); + } + if (a instanceof char[]) { + return checkSumXor((char[]) a); + } + if (a instanceof short[]) { + return checkSumXor((short[]) a); + } + if (a instanceof float[]) { + return checkSumXor((float[]) a); + } + if (a instanceof double[]) { + return checkSumXor((double[]) a); + } + fail("Unknown type of array: " + a.getClass().getName()); + return -1; + } + + private int checkSumXor(int[] a) { + int checkSum = 0; + + for (int e : a) { + checkSum ^= e; + } + return checkSum; + } + + private int checkSumXor(long[] a) { + long checkSum = 0; + + for (long e : a) { + checkSum ^= e; + } + return (int) checkSum; + } + + private int checkSumXor(byte[] a) { + byte checkSum = 0; + + for (byte e : a) { + checkSum ^= e; + } + return (int) checkSum; + } + + private int checkSumXor(char[] a) { + char checkSum = 0; + + for (char e : a) { + checkSum ^= e; + } + return (int) checkSum; + } + + private int checkSumXor(short[] a) { + short checkSum = 0; + + for (short e : a) { + checkSum ^= e; + } + return (int) checkSum; + } + + private int checkSumXor(float[] a) { + int checkSum = 0; + + for (float e : a) { + checkSum ^= (int) e; + } + return checkSum; + } + + private int checkSumXor(double[] a) { + int checkSum = 0; + + for (double e : a) { + checkSum ^= (int) e; + } + return checkSum; + } + + private int checkSumPlus(Object a) { + if (a instanceof int[]) { + return checkSumPlus((int[]) a); + } + if (a instanceof long[]) { + return checkSumPlus((long[]) a); + } + if (a instanceof byte[]) { + return checkSumPlus((byte[]) a); + } + if (a instanceof char[]) { + return checkSumPlus((char[]) a); + } + if (a instanceof short[]) { + return checkSumPlus((short[]) a); + } + if (a instanceof float[]) { + return checkSumPlus((float[]) a); + } + if (a instanceof double[]) { + return checkSumPlus((double[]) a); + } + fail("Unknown type of array: " + a.getClass().getName()); + return -1; + } + + private int checkSumPlus(int[] a) { + int checkSum = 0; + + for (int e : a) { + checkSum += e; + } + return checkSum; + } + + private int checkSumPlus(long[] a) { + long checkSum = 0; + + for (long e : a) { + checkSum += e; + } + return (int) checkSum; + } + + private int checkSumPlus(byte[] a) { + byte checkSum = 0; + + for (byte e : a) { + checkSum += e; + } + return (int) checkSum; + } + + private int checkSumPlus(char[] a) { + char checkSum = 0; + + for (char e : a) { + checkSum += e; + } + return (int) checkSum; + } + + private int checkSumPlus(short[] a) { + short checkSum = 0; + + for (short e : a) { + checkSum += e; + } + return (int) checkSum; + } + + private int checkSumPlus(float[] a) { + int checkSum = 0; + + for (float e : a) { + checkSum += (int) e; + } + return checkSum; + } + + private int checkSumPlus(double[] a) { + int checkSum = 0; + + for (double e : a) { + checkSum += (int) e; + } + return checkSum; + } + + private void sortByInsertionSort(Object a) { + if (a instanceof int[]) { + sortByInsertionSort((int[]) a); + } else if (a instanceof long[]) { + sortByInsertionSort((long[]) a); + } else if (a instanceof byte[]) { + sortByInsertionSort((byte[]) a); + } else if (a instanceof char[]) { + sortByInsertionSort((char[]) a); + } else if (a instanceof short[]) { + sortByInsertionSort((short[]) a); + } else if (a instanceof float[]) { + sortByInsertionSort((float[]) a); + } else if (a instanceof double[]) { + sortByInsertionSort((double[]) a); + } else { + fail("Unknown type of array: " + a.getClass().getName()); + } + } + + private void sortByInsertionSort(int[] a) { + for (int j, i = 1; i < a.length; i++) { + int ai = a[i]; + + for (j = i - 1; j >= 0 && ai < a[j]; j--) { + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } + + private void sortByInsertionSort(long[] a) { + for (int j, i = 1; i < a.length; i++) { + long ai = a[i]; + + for (j = i - 1; j >= 0 && ai < a[j]; j--) { + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } + + private void sortByInsertionSort(byte[] a) { + for (int j, i = 1; i < a.length; i++) { + byte ai = a[i]; + + for (j = i - 1; j >= 0 && ai < a[j]; j--) { + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } + + private void sortByInsertionSort(char[] a) { + for (int j, i = 1; i < a.length; i++) { + char ai = a[i]; + + for (j = i - 1; j >= 0 && ai < a[j]; j--) { + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } + + private void sortByInsertionSort(short[] a) { + for (int j, i = 1; i < a.length; i++) { + short ai = a[i]; + + for (j = i - 1; j >= 0 && ai < a[j]; j--) { + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } + + private void sortByInsertionSort(float[] a) { + for (int j, i = 1; i < a.length; i++) { + float ai = a[i]; + + for (j = i - 1; j >= 0 && ai < a[j]; j--) { + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } + + private void sortByInsertionSort(double[] a) { + for (int j, i = 1; i < a.length; i++) { + double ai = a[i]; + + for (j = i - 1; j >= 0 && ai < a[j]; j--) { + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } + + private void checkSubArray(Object a, int fromIndex, int toIndex) { + if (a instanceof int[]) { + checkSubArray((int[]) a, fromIndex, toIndex); + } else if (a instanceof long[]) { + checkSubArray((long[]) a, fromIndex, toIndex); + } else if (a instanceof byte[]) { + checkSubArray((byte[]) a, fromIndex, toIndex); + } else if (a instanceof char[]) { + checkSubArray((char[]) a, fromIndex, toIndex); + } else if (a instanceof short[]) { + checkSubArray((short[]) a, fromIndex, toIndex); + } else if (a instanceof float[]) { + checkSubArray((float[]) a, fromIndex, toIndex); + } else if (a instanceof double[]) { + checkSubArray((double[]) a, fromIndex, toIndex); + } else { + fail("Unknown type of array: " + a.getClass().getName()); + } + } + + private void checkSubArray(int[] a, int fromIndex, int toIndex) { + for (int i = 0; i < fromIndex; i++) { + if (a[i] != A380) { + fail("Range sort changes left element at position " + i + hex(a[i], A380)); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i] > a[i + 1]) { + fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i + + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i] != B747) { + fail("Range sort changes right element at position " + i + hex(a[i], B747)); + } + } + } + + private void checkSubArray(long[] a, int fromIndex, int toIndex) { + for (int i = 0; i < fromIndex; i++) { + if (a[i] != (long) A380) { + fail("Range sort changes left element at position " + i + hex(a[i], A380)); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i] > a[i + 1]) { + fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i + + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i] != (long) B747) { + fail("Range sort changes right element at position " + i + hex(a[i], B747)); + } + } + } + + private void checkSubArray(byte[] a, int fromIndex, int toIndex) { + for (int i = 0; i < fromIndex; i++) { + if (a[i] != (byte) A380) { + fail("Range sort changes left element at position " + i + hex(a[i], A380)); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i] > a[i + 1]) { + fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i + + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i] != (byte) B747) { + fail("Range sort changes right element at position " + i + hex(a[i], B747)); + } + } + } + + private void checkSubArray(char[] a, int fromIndex, int toIndex) { + for (int i = 0; i < fromIndex; i++) { + if (a[i] != (char) A380) { + fail("Range sort changes left element at position " + i + hex(a[i], A380)); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i] > a[i + 1]) { + fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i + + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i] != (char) B747) { + fail("Range sort changes right element at position " + i + hex(a[i], B747)); + } + } + } + + private void checkSubArray(short[] a, int fromIndex, int toIndex) { + for (int i = 0; i < fromIndex; i++) { + if (a[i] != (short) A380) { + fail("Range sort changes left element at position " + i + hex(a[i], A380)); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i] > a[i + 1]) { + fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i + + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i] != (short) B747) { + fail("Range sort changes right element at position " + i + hex(a[i], B747)); + } + } + } + + private void checkSubArray(float[] a, int fromIndex, int toIndex) { + for (int i = 0; i < fromIndex; i++) { + if (a[i] != (float) A380) { + fail("Range sort changes left element at position " + i + hex((long) a[i], + A380)); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i] > a[i + 1]) { + fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i + + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i] != (float) B747) { + fail("Range sort changes right element at position " + i + hex((long) a[i], + B747)); + } + } + } + + private void checkSubArray(double[] a, int fromIndex, int toIndex) { + for (int i = 0; i < fromIndex; i++) { + if (a[i] != (double) A380) { + fail("Range sort changes left element at position " + i + hex((long) a[i], + A380)); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i] > a[i + 1]) { + fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i + + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i] != (double) B747) { + fail("Range sort changes right element at position " + i + hex((long) a[i], + B747)); + } + } + } + + private void checkRange(Object a, int m) { + if (a instanceof int[]) { + checkRange((int[]) a, m); + } else if (a instanceof long[]) { + checkRange((long[]) a, m); + } else if (a instanceof byte[]) { + checkRange((byte[]) a, m); + } else if (a instanceof char[]) { + checkRange((char[]) a, m); + } else if (a instanceof short[]) { + checkRange((short[]) a, m); + } else if (a instanceof float[]) { + checkRange((float[]) a, m); + } else if (a instanceof double[]) { + checkRange((double[]) a, m); + } else { + fail("Unknown type of array: " + a.getClass().getName()); + } + } + + private void checkRange(int[] a, int m) { + try { + sortingHelper.sort(a, m + 1, m); + fail(sortingHelper + " does not throw IllegalArgumentException " + + "as expected: fromIndex = " + (m + 1) + " toIndex = " + m); + } catch (IllegalArgumentException iae) { + try { + sortingHelper.sort(a, -m, a.length); + fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " + + "as expected: fromIndex = " + (-m)); + } catch (ArrayIndexOutOfBoundsException aoe) { + try { + sortingHelper.sort(a, 0, a.length + m); + fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " + + "as expected: toIndex = " + (a.length + m)); + } catch (ArrayIndexOutOfBoundsException expected) { + } + } + } + } + + private void checkRange(long[] a, int m) { + try { + sortingHelper.sort(a, m + 1, m); + fail(sortingHelper + " does not throw IllegalArgumentException " + + "as expected: fromIndex = " + (m + 1) + " toIndex = " + m); + } catch (IllegalArgumentException iae) { + try { + sortingHelper.sort(a, -m, a.length); + fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " + + "as expected: fromIndex = " + (-m)); + } catch (ArrayIndexOutOfBoundsException aoe) { + try { + sortingHelper.sort(a, 0, a.length + m); + fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " + + "as expected: toIndex = " + (a.length + m)); + } catch (ArrayIndexOutOfBoundsException expected) { + } + } + } + } + + private void checkRange(byte[] a, int m) { + try { + sortingHelper.sort(a, m + 1, m); + fail(sortingHelper + " does not throw IllegalArgumentException " + + "as expected: fromIndex = " + (m + 1) + " toIndex = " + m); + } catch (IllegalArgumentException iae) { + try { + sortingHelper.sort(a, -m, a.length); + fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " + + "as expected: fromIndex = " + (-m)); + } catch (ArrayIndexOutOfBoundsException aoe) { + try { + sortingHelper.sort(a, 0, a.length + m); + fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " + + "as expected: toIndex = " + (a.length + m)); + } catch (ArrayIndexOutOfBoundsException expected) { + } + } + } + } + + private void checkRange(char[] a, int m) { + try { + sortingHelper.sort(a, m + 1, m); + fail(sortingHelper + " does not throw IllegalArgumentException " + + "as expected: fromIndex = " + (m + 1) + " toIndex = " + m); + } catch (IllegalArgumentException iae) { + try { + sortingHelper.sort(a, -m, a.length); + fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " + + "as expected: fromIndex = " + (-m)); + } catch (ArrayIndexOutOfBoundsException aoe) { + try { + sortingHelper.sort(a, 0, a.length + m); + fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " + + "as expected: toIndex = " + (a.length + m)); + } catch (ArrayIndexOutOfBoundsException expected) { + } + } + } + } + + private void checkRange(short[] a, int m) { + try { + sortingHelper.sort(a, m + 1, m); + fail(sortingHelper + " does not throw IllegalArgumentException " + + "as expected: fromIndex = " + (m + 1) + " toIndex = " + m); + } catch (IllegalArgumentException iae) { + try { + sortingHelper.sort(a, -m, a.length); + fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " + + "as expected: fromIndex = " + (-m)); + } catch (ArrayIndexOutOfBoundsException aoe) { + try { + sortingHelper.sort(a, 0, a.length + m); + fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " + + "as expected: toIndex = " + (a.length + m)); + } catch (ArrayIndexOutOfBoundsException expected) { + } + } + } + } + + private void checkRange(float[] a, int m) { + try { + sortingHelper.sort(a, m + 1, m); + fail(sortingHelper + " does not throw IllegalArgumentException " + + "as expected: fromIndex = " + (m + 1) + " toIndex = " + m); + } catch (IllegalArgumentException iae) { + try { + sortingHelper.sort(a, -m, a.length); + fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " + + "as expected: fromIndex = " + (-m)); + } catch (ArrayIndexOutOfBoundsException aoe) { + try { + sortingHelper.sort(a, 0, a.length + m); + fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " + + "as expected: toIndex = " + (a.length + m)); + } catch (ArrayIndexOutOfBoundsException expected) { + } + } + } + } + + private void checkRange(double[] a, int m) { + try { + sortingHelper.sort(a, m + 1, m); + fail(sortingHelper + " does not throw IllegalArgumentException " + + "as expected: fromIndex = " + (m + 1) + " toIndex = " + m); + } catch (IllegalArgumentException iae) { + try { + sortingHelper.sort(a, -m, a.length); + fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " + + "as expected: fromIndex = " + (-m)); + } catch (ArrayIndexOutOfBoundsException aoe) { + try { + sortingHelper.sort(a, 0, a.length + m); + fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " + + "as expected: toIndex = " + (a.length + m)); + } catch (ArrayIndexOutOfBoundsException expected) { + } + } + } + } + + private void copy(Object dst, Object src) { + if (src instanceof float[]) { + copy((float[]) dst, (float[]) src); + } else if (src instanceof double[]) { + copy((double[]) dst, (double[]) src); + } else { + fail("Unknown type of array: " + src.getClass().getName()); + } + } + + private void copy(float[] dst, float[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + private void copy(double[] dst, double[] src) { + System.arraycopy(src, 0, dst, 0, src.length); + } + + private void printTestName(String test, TestRandom random, int length) { + printTestName(test, random, length, ""); + } + + private void createData(int length) { + gold = new Object[]{ + new int[length], new long[length], + new byte[length], new char[length], new short[length], + new float[length], new double[length] + }; + + test = new Object[]{ + new int[length], new long[length], + new byte[length], new char[length], new short[length], + new float[length], new double[length] + }; + } + + private void convertData(int length) { + for (int i = 1; i < gold.length; i++) { + TypeConverter converter = TypeConverter.values()[i - 1]; + converter.convert((int[]) gold[0], gold[i]); + } + + for (int i = 0; i < gold.length; i++) { + System.arraycopy(gold[i], 0, test[i], 0, length); + } + } + + private String hex(long a, int b) { + return ": " + Long.toHexString(a) + ", must be " + Integer.toHexString(b); + } + + private void printTestName(String test, TestRandom random, int length, String message) { + out.println("[" + sortingHelper + "] '" + test + + "' length = " + length + ", random = " + random + message); + } + } + + private static enum TypeConverter { + LONG { + void convert(int[] src, Object dst) { + long[] b = (long[]) dst; + + for (int i = 0; i < src.length; i++) { + b[i] = (long) src[i]; + } + } + }, + + BYTE { + void convert(int[] src, Object dst) { + byte[] b = (byte[]) dst; + + for (int i = 0; i < src.length; i++) { + b[i] = (byte) src[i]; + } + } + }, + + CHAR { + void convert(int[] src, Object dst) { + char[] b = (char[]) dst; + + for (int i = 0; i < src.length; i++) { + b[i] = (char) src[i]; + } + } + }, + + SHORT { + void convert(int[] src, Object dst) { + short[] b = (short[]) dst; + + for (int i = 0; i < src.length; i++) { + b[i] = (short) src[i]; + } + } + }, + + FLOAT { + void convert(int[] src, Object dst) { + float[] b = (float[]) dst; + + for (int i = 0; i < src.length; i++) { + b[i] = (float) src[i]; + } + } + }, + + DOUBLE { + void convert(int[] src, Object dst) { + double[] b = (double[]) dst; + + for (int i = 0; i < src.length; i++) { + b[i] = (double) src[i]; + } + } + }; + + abstract void convert(int[] src, Object dst); + } + + private static enum SortedBuilder { + STEPS { + void build(int[] a, int m) { + for (int i = 0; i < m; i++) { + a[i] = 0; + } + + for (int i = m; i < a.length; i++) { + a[i] = 1; + } + } + }; + + abstract void build(int[] a, int m); + } + + private static enum UnsortedBuilder { + RANDOM { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = random.nextInt(); + } + } + }, + + ASCENDING { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = m + i; + } + } + }, + + DESCENDING { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = a.length - m - i; + } + } + }, + + EQUAL { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = m; + } + } + }, + + SAW { + void build(int[] a, int m, Random random) { + int incCount = 1; + int decCount = a.length; + int i = 0; + int period = m--; + + while (true) { + for (int k = 1; k <= period; k++) { + if (i >= a.length) { + return; + } + a[i++] = incCount++; + } + period += m; + + for (int k = 1; k <= period; k++) { + if (i >= a.length) { + return; + } + a[i++] = decCount--; + } + period += m; + } + } + }, + + REPEATED { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = i % m; + } + } + }, + + DUPLICATED { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = random.nextInt(m); + } + } + }, + + ORGAN_PIPES { + void build(int[] a, int m, Random random) { + int middle = a.length / (m + 1); + + for (int i = 0; i < middle; i++) { + a[i] = i; + } + + for (int i = middle; i < a.length; i++) { + a[i] = a.length - i - 1; + } + } + }, + + STAGGER { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = (i * m + i) % a.length; + } + } + }, + + PLATEAU { + void build(int[] a, int m, Random random) { + for (int i = 0; i < a.length; i++) { + a[i] = Math.min(i, m); + } + } + }, + + SHUFFLE { + void build(int[] a, int m, Random random) { + int x = 0, y = 0; + + for (int i = 0; i < a.length; i++) { + a[i] = random.nextBoolean() ? (x += 2) : (y += 2); + } + } + }, + + LATCH { + void build(int[] a, int m, Random random) { + int max = a.length / m; + max = max < 2 ? 2 : max; + + for (int i = 0; i < a.length; i++) { + a[i] = i % max; + } + } + }; + + abstract void build(int[] a, int m, Random random); + } + + private static enum MergingBuilder { + ASCENDING { + void build(int[] a, int m) { + int period = a.length / m; + int v = 1, i = 0; + + for (int k = 0; k < m; k++) { + v = 1; + + for (int p = 0; p < period; p++) { + a[i++] = v++; + } + } + + for (int j = i; j < a.length - 1; j++) { + a[j] = v++; + } + + a[a.length - 1] = 0; + } + }, + + DESCENDING { + void build(int[] a, int m) { + int period = a.length / m; + int v = -1, i = 0; + + for (int k = 0; k < m; k++) { + v = -1; + + for (int p = 0; p < period; p++) { + a[i++] = v--; + } + } + + for (int j = i; j < a.length - 1; j++) { + a[j] = v--; + } + + a[a.length - 1] = 0; + } + }, + + POINT { + void build(int[] a, int m) { + for (int i = 0; i < a.length; i++) { + a[i] = 0; + } + a[a.length / 2] = m; + } + }, + + LINE { + void build(int[] a, int m) { + for (int i = 0; i < a.length; i++) { + a[i] = i; + } + reverse(a, 0, a.length - 1); + } + }, + + PEARL { + void build(int[] a, int m) { + for (int i = 0; i < a.length; i++) { + a[i] = i; + } + reverse(a, 0, 2); + } + }, + + RING { + void build(int[] a, int m) { + int k1 = a.length / 3; + int k2 = a.length / 3 * 2; + int level = a.length / 3; + + for (int i = 0, k = level; i < k1; i++) { + a[i] = k--; + } + + for (int i = k1; i < k2; i++) { + a[i] = 0; + } + + for (int i = k2, k = level; i < a.length; i++) { + a[i] = k--; + } + } + }; + + abstract void build(int[] a, int m); + + private static void reverse(int[] a, int lo, int hi) { + for (--hi; lo < hi; ) { + int tmp = a[lo]; + a[lo++] = a[hi]; + a[hi--] = tmp; + } + } + } + + private static enum NegativeZeroBuilder { + FLOAT { + void build(Object o, Random random) { + float[] a = (float[]) o; + + for (int i = 0; i < a.length; i++) { + a[i] = random.nextBoolean() ? -0.0f : 0.0f; + } + } + }, + + DOUBLE { + void build(Object o, Random random) { + double[] a = (double[]) o; + + for (int i = 0; i < a.length; i++) { + a[i] = random.nextBoolean() ? -0.0d : 0.0d; + } + } + }; + + abstract void build(Object o, Random random); + } + + private static enum FloatingPointBuilder { + FLOAT { + void build(Object o, int a, int g, int z, int n, int p, Random random) { + float negativeValue = -random.nextFloat(); + float positiveValue = random.nextFloat(); + float[] x = (float[]) o; + int fromIndex = 0; + + writeValue(x, negativeValue, fromIndex, n); + fromIndex += n; + + writeValue(x, -0.0f, fromIndex, g); + fromIndex += g; + + writeValue(x, 0.0f, fromIndex, z); + fromIndex += z; + + writeValue(x, positiveValue, fromIndex, p); + fromIndex += p; + + writeValue(x, Float.NaN, fromIndex, a); + } + }, + + DOUBLE { + void build(Object o, int a, int g, int z, int n, int p, Random random) { + double negativeValue = -random.nextFloat(); + double positiveValue = random.nextFloat(); + double[] x = (double[]) o; + int fromIndex = 0; + + writeValue(x, negativeValue, fromIndex, n); + fromIndex += n; + + writeValue(x, -0.0d, fromIndex, g); + fromIndex += g; + + writeValue(x, 0.0d, fromIndex, z); + fromIndex += z; + + writeValue(x, positiveValue, fromIndex, p); + fromIndex += p; + + writeValue(x, Double.NaN, fromIndex, a); + } + }; + + abstract void build(Object o, int a, int g, int z, int n, int p, Random random); + + private static void writeValue(float[] a, float value, int fromIndex, int count) { + for (int i = fromIndex; i < fromIndex + count; i++) { + a[i] = value; + } + } + + private static void writeValue(double[] a, double value, int fromIndex, int count) { + for (int i = fromIndex; i < fromIndex + count; i++) { + a[i] = value; + } + } + } + + private static Comparator<Pair> pairComparator = new Comparator<Pair>() { + + @Override + public int compare(Pair p1, Pair p2) { + return p1.compareTo(p2); + } + }; + + private static class Pair implements Comparable<Pair> { + + private Pair(int key, int value) { + this.key = key; + this.value = value; + } + + int getKey() { + return key; + } + + int getValue() { + return value; + } + + @Override + public int compareTo(Pair pair) { + return Integer.compare(key, pair.key); + } + + @Override + public String toString() { + return "(" + key + ", " + value + ")"; + } + + private int key; + private int value; + } + + private static class TestRandom extends Random { + + private static final TestRandom BABA = new TestRandom(0xBABA); + private static final TestRandom DEDA = new TestRandom(0xDEDA); + private static final TestRandom C0FFEE = new TestRandom(0xC0FFEE); + + private TestRandom(long seed) { + super(seed); + this.seed = Long.toHexString(seed).toUpperCase(); + } + + @Override + public String toString() { + return seed; + } + + private String seed; + } +} diff --git a/ojluni/src/test/java/util/Arrays/SortingHelper.java b/ojluni/src/test/java/util/Arrays/SortingHelper.java new file mode 100644 index 00000000000..6b5763cc222 --- /dev/null +++ b/ojluni/src/test/java/util/Arrays/SortingHelper.java @@ -0,0 +1,658 @@ +/* + * Copyright (c) 2019, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package test.java.util.Arrays; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Method; +import java.util.*; + +/** + * This class provides access to package-private + * methods of DualPivotQuicksort class. + * + * @author Vladimir Yaroslavskiy + * + * @version 2019.09.19 + * + * @since 14 + */ +public enum SortingHelper { + + DUAL_PIVOT_QUICKSORT("Dual-Pivot Quicksort") { + + @Override + public void sort(Object a) { + // BEGIN Android-changed: we can't place this class in java.util, + // using reflection to get these methods. + /* + if (a instanceof int[]) { + DualPivotQuicksort.sort((int[]) a, SEQUENTIAL, 0, ((int[]) a).length); + } else if (a instanceof long[]) { + DualPivotQuicksort.sort((long[]) a, SEQUENTIAL, 0, ((long[]) a).length); + } else if (a instanceof byte[]) { + DualPivotQuicksort.sort((byte[]) a, 0, ((byte[]) a).length); + } else if (a instanceof char[]) { + DualPivotQuicksort.sort((char[]) a, SEQUENTIAL, 0, ((char[]) a).length); + } else if (a instanceof short[]) { + DualPivotQuicksort.sort((short[]) a, SEQUENTIAL, 0, ((short[]) a).length); + } else if (a instanceof float[]) { + DualPivotQuicksort.sort((float[]) a, SEQUENTIAL, 0, ((float[]) a).length); + } else if (a instanceof double[]) { + DualPivotQuicksort.sort((double[]) a, SEQUENTIAL, 0, ((double[]) a).length); + } else { + fail(a); + } + */ + try { + if (a instanceof int[]) { + MethodHandleHolder.INT_SORT.invoke( + (int[]) a, SEQUENTIAL, 0, ((int[]) a).length); + } else if (a instanceof long[]) { + MethodHandleHolder.LONG_SORT.invoke( + (long[]) a, SEQUENTIAL, 0, ((long[]) a).length); + } else if (a instanceof byte[]) { + MethodHandleHolder.BYTE_SORT.invoke( + (byte[]) a, 0, ((byte[]) a).length); + } else if (a instanceof char[]) { + MethodHandleHolder.CHAR_SORT.invoke( + (char[]) a, SEQUENTIAL, 0, ((char[]) a).length); + } else if (a instanceof short[]) { + MethodHandleHolder.SHORT_SORT.invoke( + (short[]) a, SEQUENTIAL, 0, ((short[]) a).length); + } else if (a instanceof float[]) { + MethodHandleHolder.FLOAT_SORT.invoke( + (float[]) a, SEQUENTIAL, 0, ((float[]) a).length); + } else if (a instanceof double[]) { + MethodHandleHolder.DOUBLE_SORT.invoke( + (double[]) a, SEQUENTIAL, 0, ((double[]) a).length); + } else { + fail(a); + } + } catch (RuntimeException re) { + // propagate RuntimeException as it is. + throw re; + } catch (Throwable e) { + throw new AssertionError(e); + } + // END Android-changed: we can't place this class in java.util, + // using reflection to get these methods. + } + + @Override + public void sort(Object a, int low, int high) { + // BEGIN Android-changed: we can't place this class in java.util, + // using reflection to get these methods. + /* + if (a instanceof int[]) { + DualPivotQuicksort.sort((int[]) a, SEQUENTIAL, low, high); + } else if (a instanceof long[]) { + DualPivotQuicksort.sort((long[]) a, SEQUENTIAL, low, high); + } else if (a instanceof byte[]) { + DualPivotQuicksort.sort((byte[]) a, low, high); + } else if (a instanceof char[]) { + DualPivotQuicksort.sort((char[]) a, SEQUENTIAL, low, high); + } else if (a instanceof short[]) { + DualPivotQuicksort.sort((short[]) a, SEQUENTIAL, low, high); + } else if (a instanceof float[]) { + DualPivotQuicksort.sort((float[]) a, SEQUENTIAL, low, high); + } else if (a instanceof double[]) { + DualPivotQuicksort.sort((double[]) a, SEQUENTIAL, low, high); + } else { + fail(a); + } + */ + try { + if (a instanceof int[]) { + MethodHandleHolder.INT_SORT.invoke( + (int[]) a, SEQUENTIAL, low, high); + } else if (a instanceof long[]) { + MethodHandleHolder.LONG_SORT.invoke( + (long[]) a, SEQUENTIAL, low, high); + } else if (a instanceof byte[]) { + MethodHandleHolder.BYTE_SORT.invoke( + (byte[]) a, low, high); + } else if (a instanceof char[]) { + MethodHandleHolder.CHAR_SORT.invoke( + (char[]) a, SEQUENTIAL, low, high); + } else if (a instanceof short[]) { + MethodHandleHolder.SHORT_SORT.invoke( + (short[]) a, SEQUENTIAL, low, high); + } else if (a instanceof float[]) { + MethodHandleHolder.FLOAT_SORT.invoke( + (float[]) a, SEQUENTIAL, low, high); + } else if (a instanceof double[]) { + MethodHandleHolder.DOUBLE_SORT.invoke( + (double[]) a, SEQUENTIAL, low, high); + } else { + fail(a); + } + } catch (RuntimeException re) { + // propagate RuntimeException as it is. + throw re; + } catch (Throwable e) { + throw new AssertionError(e); + } + // END Android-changed: we can't place this class in java.util, + // using reflection to get these methods. + } + + @Override + public void sort(Object[] a) { + fail(a); + } + + @Override + public void sort(Object[] a, Comparator comparator) { + fail(a); + } + }, + + PARALLEL_SORT("Parallel sort") { + + @Override + public void sort(Object a) { + // BEGIN Android-changed: we can't place this class in java.util, + // using reflection to get these methods. + /* + if (a instanceof int[]) { + DualPivotQuicksort.sort((int[]) a, PARALLEL, 0, ((int[]) a).length); + } else if (a instanceof long[]) { + DualPivotQuicksort.sort((long[]) a, PARALLEL, 0, ((long[]) a).length); + } else if (a instanceof byte[]) { + DualPivotQuicksort.sort((byte[]) a, 0, ((byte[]) a).length); + } else if (a instanceof char[]) { + DualPivotQuicksort.sort((char[]) a, PARALLEL, 0, ((char[]) a).length); + } else if (a instanceof short[]) { + DualPivotQuicksort.sort((short[]) a, PARALLEL, 0, ((short[]) a).length); + } else if (a instanceof float[]) { + DualPivotQuicksort.sort((float[]) a, PARALLEL, 0, ((float[]) a).length); + } else if (a instanceof double[]) { + DualPivotQuicksort.sort((double[]) a, PARALLEL, 0, ((double[]) a).length); + } else { + fail(a); + } + */ + try { + if (a instanceof int[]) { + MethodHandleHolder.INT_SORT.invoke( + (int[]) a, PARALLEL, 0, ((int[]) a).length); + } else if (a instanceof long[]) { + MethodHandleHolder.LONG_SORT.invoke( + (long[]) a, PARALLEL, 0, ((long[]) a).length); + } else if (a instanceof byte[]) { + MethodHandleHolder.BYTE_SORT.invoke( + (byte[]) a, 0, ((byte[]) a).length); + } else if (a instanceof char[]) { + MethodHandleHolder.CHAR_SORT.invoke( + (char[]) a, PARALLEL, 0, ((char[]) a).length); + } else if (a instanceof short[]) { + MethodHandleHolder.SHORT_SORT.invoke( + (short[]) a, PARALLEL, 0, ((short[]) a).length); + } else if (a instanceof float[]) { + MethodHandleHolder.FLOAT_SORT.invoke( + (float[]) a, PARALLEL, 0, ((float[]) a).length); + } else if (a instanceof double[]) { + MethodHandleHolder.DOUBLE_SORT.invoke( + (double[]) a, PARALLEL, 0, ((double[]) a).length); + } else { + fail(a); + } + } catch (RuntimeException re) { + // propagate RuntimeException as it is. + throw re; + } catch (Throwable e) { + throw new AssertionError(e); + } + // END Android-changed: we can't place this class in java.util, + // using reflection to get these methods. + } + + @Override + public void sort(Object a, int low, int high) { + // BEGIN Android-changed: we can't place this class in java.util, + // using reflection to get these methods. + /* + if (a instanceof int[]) { + DualPivotQuicksort.sort((int[]) a, PARALLEL, low, high); + } else if (a instanceof long[]) { + DualPivotQuicksort.sort((long[]) a, PARALLEL, low, high); + } else if (a instanceof byte[]) { + DualPivotQuicksort.sort((byte[]) a, low, high); + } else if (a instanceof char[]) { + DualPivotQuicksort.sort((char[]) a, PARALLEL, low, high); + } else if (a instanceof short[]) { + DualPivotQuicksort.sort((short[]) a, PARALLEL, low, high); + } else if (a instanceof float[]) { + DualPivotQuicksort.sort((float[]) a, PARALLEL, low, high); + } else if (a instanceof double[]) { + DualPivotQuicksort.sort((double[]) a, PARALLEL, low, high); + } else { + fail(a); + } + */ + try { + if (a instanceof int[]) { + MethodHandleHolder.INT_SORT.invoke( + (int[]) a, PARALLEL, low, high); + } else if (a instanceof long[]) { + MethodHandleHolder.LONG_SORT.invoke( + (long[]) a, PARALLEL, low, high); + } else if (a instanceof byte[]) { + MethodHandleHolder.BYTE_SORT.invoke( + (byte[]) a, low, high); + } else if (a instanceof char[]) { + MethodHandleHolder.CHAR_SORT.invoke( + (char[]) a, PARALLEL, low, high); + } else if (a instanceof short[]) { + MethodHandleHolder.SHORT_SORT.invoke( + (short[]) a, PARALLEL, low, high); + } else if (a instanceof float[]) { + MethodHandleHolder.FLOAT_SORT.invoke( + (float[]) a, PARALLEL, low, high); + } else if (a instanceof double[]) { + MethodHandleHolder.DOUBLE_SORT.invoke( + (double[]) a, PARALLEL, low, high); + } else { + fail(a); + } + } catch (RuntimeException re) { + // propagate RuntimeException as it is. + throw re; + } catch (Throwable e) { + throw new AssertionError(e); + } + // END Android-changed: we can't place this class in java.util, + // using reflection to get these methods. + } + + @Override + public void sort(Object[] a) { + fail(a); + } + + @Override + public void sort(Object[] a, Comparator comparator) { + fail(a); + } + }, + + HEAP_SORT("Heap sort") { + + @Override + public void sort(Object a) { + // BEGIN Android-changed: we can't place this class in java.util, + // using reflection to get these methods. + /* + if (a instanceof int[]) { + DualPivotQuicksort.sort(null, (int[]) a, BIG_DEPTH, 0, ((int[]) a).length); + } else if (a instanceof long[]) { + DualPivotQuicksort.sort(null, (long[]) a, BIG_DEPTH, 0, ((long[]) a).length); + } else if (a instanceof byte[]) { + DualPivotQuicksort.sort((byte[]) a, 0, ((byte[]) a).length); + } else if (a instanceof char[]) { + DualPivotQuicksort.sort((char[]) a, BIG_DEPTH, 0, ((char[]) a).length); + } else if (a instanceof short[]) { + DualPivotQuicksort.sort((short[]) a, BIG_DEPTH, 0, ((short[]) a).length); + } else if (a instanceof float[]) { + DualPivotQuicksort.sort(null, (float[]) a, BIG_DEPTH, 0, ((float[]) a).length); + } else if (a instanceof double[]) { + DualPivotQuicksort.sort(null, (double[]) a, BIG_DEPTH, 0, ((double[]) a).length); + } else { + fail(a); + } + */ + try { + if (a instanceof int[]) { + MethodHandleHolder.INT_SORTER_SORT.invoke( + null, (int[]) a, BIG_DEPTH, 0, ((int[]) a).length); + } else if (a instanceof long[]) { + MethodHandleHolder.LONG_SORTER_SORT.invoke( + null, (long[]) a, BIG_DEPTH, 0, ((long[]) a).length); + } else if (a instanceof byte[]) { + MethodHandleHolder.BYTE_SORT.invoke( + (byte[]) a, 0, ((byte[]) a).length); + } else if (a instanceof char[]) { + MethodHandleHolder.CHAR_SORT.invoke( + (char[]) a, BIG_DEPTH, 0, ((char[]) a).length); + } else if (a instanceof short[]) { + MethodHandleHolder.SHORT_SORT.invoke( + (short[]) a, BIG_DEPTH, 0, ((short[]) a).length); + } else if (a instanceof float[]) { + MethodHandleHolder.FLOAT_SORTER_SORT.invoke( + null, (float[]) a, BIG_DEPTH, 0, ((float[]) a).length); + } else if (a instanceof double[]) { + MethodHandleHolder.DOUBLE_SORTER_SORT.invoke( + null, (double[]) a, BIG_DEPTH, 0, ((double[]) a).length); + } else { + fail(a); + } + } catch (RuntimeException re) { + // propagate RuntimeException as it is. + throw re; + } catch (Throwable e) { + throw new AssertionError(e); + } + // END Android-changed: we can't place this class in java.util, + // using reflection to get these methods. + } + + @Override + public void sort(Object a, int low, int high) { + // BEGIN Android-changed: we can't place this class in java.util, + // using reflection to get these methods. + /* + if (a instanceof int[]) { + DualPivotQuicksort.sort(null, (int[]) a, BIG_DEPTH, low, high); + } else if (a instanceof long[]) { + DualPivotQuicksort.sort(null, (long[]) a, BIG_DEPTH, low, high); + } else if (a instanceof byte[]) { + DualPivotQuicksort.sort((byte[]) a, low, high); + } else if (a instanceof char[]) { + DualPivotQuicksort.sort((char[]) a, BIG_DEPTH, low, high); + } else if (a instanceof short[]) { + DualPivotQuicksort.sort((short[]) a, BIG_DEPTH, low, high); + } else if (a instanceof float[]) { + DualPivotQuicksort.sort(null, (float[]) a, BIG_DEPTH, low, high); + } else if (a instanceof double[]) { + DualPivotQuicksort.sort(null, (double[]) a, BIG_DEPTH, low, high); + } else { + fail(a); + } + + */ + try { + if (a instanceof int[]) { + MethodHandleHolder.INT_SORTER_SORT.invoke( + null, (int[]) a, BIG_DEPTH, low, high); + } else if (a instanceof long[]) { + MethodHandleHolder.LONG_SORTER_SORT.invoke( + null, (long[]) a, BIG_DEPTH, low, high); + } else if (a instanceof byte[]) { + MethodHandleHolder.BYTE_SORT.invoke((byte[]) a, low, high); + } else if (a instanceof char[]) { + MethodHandleHolder.CHAR_SORT.invoke( + (char[]) a, BIG_DEPTH, low, high); + } else if (a instanceof short[]) { + MethodHandleHolder.SHORT_SORT.invoke( + (short[]) a, BIG_DEPTH, low, high); + } else if (a instanceof float[]) { + MethodHandleHolder.FLOAT_SORTER_SORT.invoke( + null, (float[]) a, BIG_DEPTH, low, high); + } else if (a instanceof double[]) { + MethodHandleHolder.DOUBLE_SORTER_SORT.invoke( + null, (double[]) a, BIG_DEPTH, low, high); + } else { + fail(a); + } + } catch (RuntimeException re) { + // propagate RuntimeException as it is. + throw re; + } catch (Throwable e) { + throw new AssertionError(e); + } + // END Android-changed: we can't place this class in java.util, + // using reflection to get these methods. + } + + @Override + public void sort(Object[] a) { + fail(a); + } + + @Override + public void sort(Object[] a, Comparator comparator) { + fail(a); + } + }, + + ARRAYS_SORT("Arrays.sort") { + + @Override + public void sort(Object a) { + if (a instanceof int[]) { + Arrays.sort((int[]) a); + } else if (a instanceof long[]) { + Arrays.sort((long[]) a); + } else if (a instanceof byte[]) { + Arrays.sort((byte[]) a); + } else if (a instanceof char[]) { + Arrays.sort((char[]) a); + } else if (a instanceof short[]) { + Arrays.sort((short[]) a); + } else if (a instanceof float[]) { + Arrays.sort((float[]) a); + } else if (a instanceof double[]) { + Arrays.sort((double[]) a); + } else { + fail(a); + } + } + + @Override + public void sort(Object a, int low, int high) { + if (a instanceof int[]) { + Arrays.sort((int[]) a, low, high); + } else if (a instanceof long[]) { + Arrays.sort((long[]) a, low, high); + } else if (a instanceof byte[]) { + Arrays.sort((byte[]) a, low, high); + } else if (a instanceof char[]) { + Arrays.sort((char[]) a, low, high); + } else if (a instanceof short[]) { + Arrays.sort((short[]) a, low, high); + } else if (a instanceof float[]) { + Arrays.sort((float[]) a, low, high); + } else if (a instanceof double[]) { + Arrays.sort((double[]) a, low, high); + } else { + fail(a); + } + } + + @Override + public void sort(Object[] a) { + Arrays.sort(a); + } + + @Override + @SuppressWarnings("unchecked") + public void sort(Object[] a, Comparator comparator) { + Arrays.sort(a, comparator); + } + }, + + ARRAYS_PARALLEL_SORT("Arrays.parallelSort") { + + @Override + public void sort(Object a) { + if (a instanceof int[]) { + Arrays.parallelSort((int[]) a); + } else if (a instanceof long[]) { + Arrays.parallelSort((long[]) a); + } else if (a instanceof byte[]) { + Arrays.parallelSort((byte[]) a); + } else if (a instanceof char[]) { + Arrays.parallelSort((char[]) a); + } else if (a instanceof short[]) { + Arrays.parallelSort((short[]) a); + } else if (a instanceof float[]) { + Arrays.parallelSort((float[]) a); + } else if (a instanceof double[]) { + Arrays.parallelSort((double[]) a); + } else { + fail(a); + } + } + + @Override + public void sort(Object a, int low, int high) { + if (a instanceof int[]) { + Arrays.parallelSort((int[]) a, low, high); + } else if (a instanceof long[]) { + Arrays.parallelSort((long[]) a, low, high); + } else if (a instanceof byte[]) { + Arrays.parallelSort((byte[]) a, low, high); + } else if (a instanceof char[]) { + Arrays.parallelSort((char[]) a, low, high); + } else if (a instanceof short[]) { + Arrays.parallelSort((short[]) a, low, high); + } else if (a instanceof float[]) { + Arrays.parallelSort((float[]) a, low, high); + } else if (a instanceof double[]) { + Arrays.parallelSort((double[]) a, low, high); + } else { + fail(a); + } + } + + @Override + @SuppressWarnings("unchecked") + public void sort(Object[] a) { + Arrays.parallelSort((Comparable[]) a); + } + + @Override + @SuppressWarnings("unchecked") + public void sort(Object[] a, Comparator comparator) { + Arrays.parallelSort(a, comparator); + } + }; + + abstract public void sort(Object a); + + abstract public void sort(Object a, int low, int high); + + abstract public void sort(Object[] a); + + abstract public void sort(Object[] a, Comparator comparator); + + private SortingHelper(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + + private static void fail(Object a) { + throw new RuntimeException("Unexpected type of array: " + a.getClass().getName()); + } + + private String name; + + /** + * Parallelism level for sequential and parallel sorting. + */ + private static final int SEQUENTIAL = 0; + private static final int PARALLEL = 87; + + /** + * Heap sort will be invoked, if recursion depth is too big. + * Value is taken from DualPivotQuicksort.MAX_RECURSION_DEPTH. + */ + private static final int BIG_DEPTH = 64 * (3 << 1); +} + +// BEGIN Android-added: we can't place this class in java.util, +// using reflection to get these methods. +class MethodHandleHolder { + public static final MethodHandle INT_SORT; + public static final MethodHandle LONG_SORT; + public static final MethodHandle BYTE_SORT; + public static final MethodHandle CHAR_SORT; + public static final MethodHandle SHORT_SORT; + public static final MethodHandle FLOAT_SORT; + public static final MethodHandle DOUBLE_SORT; + + public static final MethodHandle INT_SORTER_SORT; + public static final MethodHandle LONG_SORTER_SORT; + public static final MethodHandle FLOAT_SORTER_SORT; + public static final MethodHandle DOUBLE_SORTER_SORT; + + + static { + try { + INT_SORT = makeAccessibleAndUnreflect( + Class.forName("java.util.DualPivotQuicksort") + .getDeclaredMethod( + "sort", int[].class, int.class, int.class, int.class)); + LONG_SORT = makeAccessibleAndUnreflect( + Class.forName("java.util.DualPivotQuicksort") + .getDeclaredMethod( + "sort", long[].class, int.class, int.class, int.class)); + BYTE_SORT = makeAccessibleAndUnreflect( + Class.forName("java.util.DualPivotQuicksort") + .getDeclaredMethod( + "sort", byte[].class, int.class, int.class)); + CHAR_SORT = makeAccessibleAndUnreflect( + Class.forName("java.util.DualPivotQuicksort") + .getDeclaredMethod( + "sort", char[].class, int.class, int.class, int.class)); + SHORT_SORT = makeAccessibleAndUnreflect( + Class.forName("java.util.DualPivotQuicksort") + .getDeclaredMethod( + "sort", short[].class, int.class, int.class, int.class)); + FLOAT_SORT = makeAccessibleAndUnreflect( + Class.forName("java.util.DualPivotQuicksort") + .getDeclaredMethod( + "sort", float[].class, int.class, int.class, int.class)); + DOUBLE_SORT = makeAccessibleAndUnreflect( + Class.forName("java.util.DualPivotQuicksort") + .getDeclaredMethod( + "sort", double[].class, int.class, int.class, int.class)); + + Class<?> sorterClass = Class.forName("java.util.DualPivotQuicksort$Sorter"); + INT_SORTER_SORT = makeAccessibleAndUnreflect( + Class.forName("java.util.DualPivotQuicksort") + .getDeclaredMethod("sort", sorterClass, + int[].class, int.class, int.class, int.class)); + LONG_SORTER_SORT = makeAccessibleAndUnreflect( + Class.forName("java.util.DualPivotQuicksort") + .getDeclaredMethod("sort", sorterClass, + long[].class, int.class, int.class, int.class)); + FLOAT_SORTER_SORT = makeAccessibleAndUnreflect( + Class.forName("java.util.DualPivotQuicksort") + .getDeclaredMethod("sort", sorterClass, + float[].class, int.class, int.class, int.class)); + DOUBLE_SORTER_SORT = makeAccessibleAndUnreflect( + Class.forName("java.util.DualPivotQuicksort") + .getDeclaredMethod("sort", sorterClass, + double[].class, int.class, int.class, int.class)); + } catch (Exception e) { + throw new AssertionError(e); + } + } + + private static MethodHandle makeAccessibleAndUnreflect(Method method) + throws IllegalAccessException { + method.setAccessible(true); + return MethodHandles.lookup().unreflect(method); + } +} +// END Android-changed: we can't place this class in java.util, +// using reflection to get these methods.
\ No newline at end of file diff --git a/ojluni/src/test/java/util/Arrays/SortingNearlySortedPrimitive.java b/ojluni/src/test/java/util/Arrays/SortingNearlySortedPrimitive.java new file mode 100644 index 00000000000..5850b0b6129 --- /dev/null +++ b/ojluni/src/test/java/util/Arrays/SortingNearlySortedPrimitive.java @@ -0,0 +1,356 @@ +/* + * Copyright 2015 Goldman Sachs. + * Copyright (c) 2015, 2016, 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 8154049 + * @summary Tests the sorting of a large array of sorted primitive values, + * predominently for cases where the array is nearly sorted. This tests + * code that detects patterns in the array to determine if it is nearly + * sorted and if so employs and optimizes merge sort rather than a + * Dual-Pivot QuickSort. + * + * @run testng SortingNearlySortedPrimitive + */ + +package test.java.util.Arrays; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.StringJoiner; +import java.util.function.IntFunction; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +public class SortingNearlySortedPrimitive { + + static final int BASE = 3; + static final int WIDTH = 4; + // Should be > DualPivotQuicksort.QUICKSORT_THRESHOLD + static final int PAD = 300; + + Stream<int[]> createCombinations() { + // Create all combinations for the BASE value and double the WIDTH + // elements + // This is create various combinations of ascending, descending and + // equal runs to exercise the nearly sorted code paths + return IntStream.range(0, (int) Math.pow(BASE, 2 * WIDTH)). + mapToObj(this::createArray); + } + + // Create an array which at either end is filled with -ve and +ve elements + // according to the base value and padded with zeros in between + int[] createArray(int v) { + int[] a = new int[WIDTH + PAD + WIDTH]; + + // Fill head of array + for (int j = 0; j < WIDTH; j++) { + a[j] = (v % BASE) - (BASE / 2); + v /= BASE; + } + // Fill tail of array + for (int j = 0; j < WIDTH; j++) { + a[WIDTH + PAD + j] = (v % BASE) - (BASE / 2); + v /= BASE; + } + return a; + } + + @Test + public void testCombination() { + createCombinations().forEach(a -> { + try { + // Clone source array to ensure it is not modified + this.sortAndAssert(a.clone()); + this.sortAndAssert(floatCopyFromInt(a)); + this.sortAndAssert(doubleCopyFromInt(a)); + this.sortAndAssert(longCopyFromInt(a)); + this.sortAndAssert(shortCopyFromInt(a)); + this.sortAndAssert(charCopyFromInt(a)); + } catch (AssertionError sae) { + AssertionError ae = new AssertionError("Sort failed for " + arrayToString(a)); + ae.addSuppressed(sae); + throw ae; + } + }); + } + + String arrayToString(int[] a) { + int[] l = Arrays.copyOfRange(a, 0, WIDTH + 2); + int[] r = Arrays.copyOfRange(a, a.length - (WIDTH + 2), a.length); + StringJoiner sj = new StringJoiner(",", "[", "]"); + for (int i : l) { + sj.add(Integer.toString(i)); + } + sj.add("..."); + for (int i : r) { + sj.add(Integer.toString(i)); + } + return sj.toString(); + } + + + @DataProvider(name = "shapes") + public Object[][] createShapes() { + Stream<List<Object>> baseCases = Stream.of( + List.of("hiZeroLowTest", (IntFunction<int[]>) this::hiZeroLowData), + List.of("endLessThanTest", (IntFunction<int[]>) this::endLessThanData), + List.of("highFlatLowTest", (IntFunction<int[]>) this::highFlatLowData), + List.of("identicalTest", (IntFunction<int[]>) this::identicalData), + List.of("sortedReversedSortedTest", (IntFunction<int[]>) this::sortedReversedSortedData), + List.of("pairFlipTest", (IntFunction<int[]>) this::pairFlipData), + List.of("zeroHiTest", (IntFunction<int[]>) this::zeroHiData) + ); + + // Ensure the following inequality holds for certain sizes + // DualPivotQuicksort.QUICKSORT_THRESHOLD <= size - 1 + // < DualPivotQuicksort.COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR + // This guarantees that code paths are taken for checking nearly sorted + // arrays for all primitive types + List<Integer> sizes = List.of(100, 1_000, 10_000, 1_000_000); + return baseCases. + flatMap(l -> sizes.stream().map(s -> append(l, s))). + toArray(Object[][]::new); + } + + Object[] append(List<Object> l, Object value) { + List<Object> nl = new ArrayList<>(l); + nl.add(value); + return nl.toArray(); + } + + @Test(dataProvider = "shapes") + public void testShapes(String testName, IntFunction<int[]> dataMethod, int size) { + int[] intSourceArray = dataMethod.apply(size); + + // Clone source array to ensure it is not modified + this.sortAndAssert(intSourceArray.clone()); + this.sortAndAssert(floatCopyFromInt(intSourceArray)); + this.sortAndAssert(doubleCopyFromInt(intSourceArray)); + this.sortAndAssert(longCopyFromInt(intSourceArray)); + this.sortAndAssert(shortCopyFromInt(intSourceArray)); + this.sortAndAssert(charCopyFromInt(intSourceArray)); + } + + private float[] floatCopyFromInt(int[] src) { + float[] result = new float[src.length]; + for (int i = 0; i < result.length; i++) { + result[i] = src[i]; + } + return result; + } + + private double[] doubleCopyFromInt(int[] src) { + double[] result = new double[src.length]; + for (int i = 0; i < result.length; i++) { + result[i] = src[i]; + } + return result; + } + + private long[] longCopyFromInt(int[] src) { + long[] result = new long[src.length]; + for (int i = 0; i < result.length; i++) { + result[i] = src[i]; + } + return result; + } + + private short[] shortCopyFromInt(int[] src) { + short[] result = new short[src.length]; + for (int i = 0; i < result.length; i++) { + result[i] = (short) src[i]; + } + return result; + } + + private char[] charCopyFromInt(int[] src) { + char[] result = new char[src.length]; + for (int i = 0; i < result.length; i++) { + result[i] = (char) src[i]; + } + return result; + } + + private void sortAndAssert(int[] array) { + Arrays.sort(array); + for (int i = 1; i < array.length; i++) { + if (array[i] < array[i - 1]) { + throw new AssertionError("not sorted"); + } + } + } + + private void sortAndAssert(char[] array) { + Arrays.sort(array); + for (int i = 1; i < array.length; i++) { + if (array[i] < array[i - 1]) { + throw new AssertionError("not sorted"); + } + } + } + + private void sortAndAssert(short[] array) { + Arrays.sort(array); + for (int i = 1; i < array.length; i++) { + if (array[i] < array[i - 1]) { + throw new AssertionError("not sorted"); + } + } + } + + private void sortAndAssert(double[] array) { + Arrays.sort(array); + for (int i = 1; i < array.length; i++) { + if (array[i] < array[i - 1]) { + throw new AssertionError("not sorted"); + } + } + } + + private void sortAndAssert(float[] array) { + Arrays.sort(array); + for (int i = 1; i < array.length; i++) { + if (array[i] < array[i - 1]) { + throw new AssertionError("not sorted"); + } + } + } + + private void sortAndAssert(long[] array) { + Arrays.sort(array); + for (int i = 1; i < array.length; i++) { + if (array[i] < array[i - 1]) { + throw new AssertionError("not sorted"); + } + } + } + + private int[] zeroHiData(int size) { + int[] array = new int[size]; + + int threeQuarters = (int) (size * 0.75); + for (int i = 0; i < threeQuarters; i++) { + array[i] = 0; + } + int k = 1; + for (int i = threeQuarters; i < size; i++) { + array[i] = k; + k++; + } + + return array; + } + + private int[] hiZeroLowData(int size) { + int[] array = new int[size]; + + int oneThird = size / 3; + for (int i = 0; i < oneThird; i++) { + array[i] = i; + } + int twoThirds = oneThird * 2; + for (int i = oneThird; i < twoThirds; i++) { + array[i] = 0; + } + for (int i = twoThirds; i < size; i++) { + array[i] = oneThird - i + twoThirds; + } + return array; + } + + private int[] highFlatLowData(int size) { + int[] array = new int[size]; + + int oneThird = size / 3; + for (int i = 0; i < oneThird; i++) { + array[i] = i; + } + int twoThirds = oneThird * 2; + int constant = oneThird - 1; + for (int i = oneThird; i < twoThirds; i++) { + array[i] = constant; + } + for (int i = twoThirds; i < size; i++) { + array[i] = constant - i + twoThirds; + } + + return array; + } + + private int[] identicalData(int size) { + int[] array = new int[size]; + int listNumber = 24; + + for (int i = 0; i < size; i++) { + array[i] = listNumber; + } + + return array; + } + + private int[] endLessThanData(int size) { + int[] array = new int[size]; + + for (int i = 0; i < size - 1; i++) { + array[i] = 3; + } + array[size - 1] = 1; + + return array; + } + + private int[] sortedReversedSortedData(int size) { + int[] array = new int[size]; + + for (int i = 0; i < size / 2; i++) { + array[i] = i; + } + int num = 0; + for (int i = size / 2; i < size; i++) { + array[i] = size - num; + num++; + } + + return array; + } + + private int[] pairFlipData(int size) { + int[] array = new int[size]; + + for (int i = 0; i < size; i++) { + array[i] = i; + } + for (int i = 0; i < size; i += 2) { + int temp = array[i]; + array[i] = array[i + 1]; + array[i + 1] = temp; + } + + return array; + } +} diff --git a/ojluni/src/test/java/util/Arrays/StreamAndSpliterator.java b/ojluni/src/test/java/util/Arrays/StreamAndSpliterator.java new file mode 100644 index 00000000000..863ed5fb381 --- /dev/null +++ b/ojluni/src/test/java/util/Arrays/StreamAndSpliterator.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2014, 2017, 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 8037857 + * @summary tests for stream and spliterator factory methods + * @run testng StreamAndSpliterator + */ + +package test.java.util.Arrays; + +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.Spliterators; + +import org.testng.Assert.ThrowingRunnable; + +import static org.testng.Assert.assertThrows; + +public class StreamAndSpliterator { + @Test + public void testStreamNPEs() { + assertThrowsNPE(() -> Arrays.stream((int[]) null, 0, 0)); + assertThrowsNPE(() -> Arrays.stream((long[]) null, 0, 0)); + assertThrowsNPE(() -> Arrays.stream((double[]) null, 0, 0)); + assertThrowsNPE(() -> Arrays.stream((String[]) null, 0, 0)); + } + + @Test + public void testStreamAIOBEs() { + // origin > fence + assertThrowsAIOOB(() -> Arrays.stream(new int[]{}, 1, 0)); + assertThrowsAIOOB(() -> Arrays.stream(new long[]{}, 1, 0)); + assertThrowsAIOOB(() -> Arrays.stream(new double[]{}, 1, 0)); + assertThrowsAIOOB(() -> Arrays.stream(new String[]{}, 1, 0)); + + // bad origin + assertThrowsAIOOB(() -> Arrays.stream(new int[]{}, -1, 0)); + assertThrowsAIOOB(() -> Arrays.stream(new long[]{}, -1, 0)); + assertThrowsAIOOB(() -> Arrays.stream(new double[]{}, -1, 0)); + assertThrowsAIOOB(() -> Arrays.stream(new String[]{}, -1, 0)); + + // bad fence + assertThrowsAIOOB(() -> Arrays.stream(new int[]{}, 0, 1)); + assertThrowsAIOOB(() -> Arrays.stream(new long[]{}, 0, 1)); + assertThrowsAIOOB(() -> Arrays.stream(new double[]{}, 0, 1)); + assertThrowsAIOOB(() -> Arrays.stream(new String[]{}, 0, 1)); + } + + + @Test + public void testSpliteratorNPEs() { + assertThrowsNPE(() -> Arrays.spliterator((int[]) null, 0, 0)); + assertThrowsNPE(() -> Arrays.spliterator((long[]) null, 0, 0)); + assertThrowsNPE(() -> Arrays.spliterator((double[]) null, 0, 0)); + assertThrowsNPE(() -> Arrays.spliterator((String[]) null, 0, 0)); + } + + @Test + public void testSpliteratorAIOBEs() { + // origin > fence + assertThrowsAIOOB(() -> Arrays.spliterator(new int[]{}, 1, 0)); + assertThrowsAIOOB(() -> Arrays.spliterator(new long[]{}, 1, 0)); + assertThrowsAIOOB(() -> Arrays.spliterator(new double[]{}, 1, 0)); + assertThrowsAIOOB(() -> Arrays.spliterator(new String[]{}, 1, 0)); + + // bad origin + assertThrowsAIOOB(() -> Arrays.spliterator(new int[]{}, -1, 0)); + assertThrowsAIOOB(() -> Arrays.spliterator(new long[]{}, -1, 0)); + assertThrowsAIOOB(() -> Arrays.spliterator(new double[]{}, -1, 0)); + assertThrowsAIOOB(() -> Arrays.spliterator(new String[]{}, -1, 0)); + + // bad fence + assertThrowsAIOOB(() -> Arrays.spliterator(new int[]{}, 0, 1)); + assertThrowsAIOOB(() -> Arrays.spliterator(new long[]{}, 0, 1)); + assertThrowsAIOOB(() -> Arrays.spliterator(new double[]{}, 0, 1)); + assertThrowsAIOOB(() -> Arrays.spliterator(new String[]{}, 0, 1)); + } + + + @Test + public void testSpliteratorNPEsFromSpliterators() { + assertThrowsNPE(() -> Spliterators.spliterator((int[]) null, 0, 0, 0)); + assertThrowsNPE(() -> Spliterators.spliterator((long[]) null, 0, 0, 0)); + assertThrowsNPE(() -> Spliterators.spliterator((double[]) null, 0, 0, 0)); + assertThrowsNPE(() -> Spliterators.spliterator((String[]) null, 0, 0, 0)); + } + + @Test + public void testSpliteratorAIOBEsFromSpliterators() { + // origin > fence + assertThrowsAIOOB(() -> Spliterators.spliterator(new int[]{}, 1, 0, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new long[]{}, 1, 0, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new double[]{}, 1, 0, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new String[]{}, 1, 0, 0)); + + // bad origin + assertThrowsAIOOB(() -> Spliterators.spliterator(new int[]{}, -1, 0, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new long[]{}, -1, 0, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new double[]{}, -1, 0, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new String[]{}, -1, 0, 0)); + + // bad fence + assertThrowsAIOOB(() -> Spliterators.spliterator(new int[]{}, 0, 1, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new long[]{}, 0, 1, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new double[]{}, 0, 1, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new String[]{}, 0, 1, 0)); + } + + void assertThrowsNPE(ThrowingRunnable r) { + assertThrows(NullPointerException.class, r); + } + + void assertThrowsAIOOB(ThrowingRunnable r) { + assertThrows(ArrayIndexOutOfBoundsException.class, r); + } +} diff --git a/ojluni/src/test/java/util/Arrays/TimSortStackSize.java b/ojluni/src/test/java/util/Arrays/TimSortStackSize.java new file mode 100644 index 00000000000..f3828c3a178 --- /dev/null +++ b/ojluni/src/test/java/util/Arrays/TimSortStackSize.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2013, 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 8011944 + * @summary Test TimSort stack size + */ + +package test.java.util.Arrays; + +import java.util.Arrays; +import java.util.ArrayDeque; + +public class TimSortStackSize { + + public static void main(String[] args) { + testComparableTimSort(); + testTimSort(); + } + + static void testComparableTimSort() { + System.out.printf("testComparableTimSort()%n"); + Arrays.sort(genData()); + } + + static void testTimSort() { + System.out.printf("testTimSort()%n"); + Arrays.sort(genData(), Integer::compare); + } + + private static final int MIN = 16; + + private static final int BOUND1 = 2 * MIN + 1; + private static final int BOUND2 = BOUND1 + MIN + 2; + private static final int BOUND3 = BOUND1 + 1 + BOUND2; + private static final int BOUND4 = BOUND2 + 1 + BOUND3; + private static final int BOUND5 = BOUND3 + 1 + BOUND4; + + static int build(int size, int B, ArrayDeque<Integer> chunks) { + chunks.addFirst(B); + if (size < BOUND1) { + chunks.addFirst(size); + return size; + } + + int asize = (size + 2) / 2; + if (size >= BOUND2 && asize < BOUND1) { + asize = BOUND1; + } else if (size >= BOUND3 && asize < BOUND2) { + asize = BOUND2; + } else if (size >= BOUND4 && asize < BOUND3) { + asize = BOUND3; + } else if (size >= BOUND5 && asize < BOUND4) { + asize = BOUND4; + } + if (size - asize >= B) { + throw new AssertionError(" " + size + " , " + asize + " , " + B); + } + return build(asize, size - asize, chunks); + } + + static Integer[] genData() { + ArrayDeque<Integer> chunks = new ArrayDeque<Integer>(); + chunks.addFirst(MIN); + + int B = MIN + 4; + int A = B + MIN + 1; + + for (int i = 0; i < 8; i++) { + int eps = build(A, B, chunks); + B = B + A + 1; + A = B + eps + 1; + } + chunks.addFirst(B); + chunks.addFirst(A); + int total = 0; + for (Integer len : chunks) { + total += len; + } + int pow = MIN; + while (pow < total) { + pow += pow; + } + chunks.addLast(pow - total); + System.out.println(" Total: " + total); + Integer[] array = new Integer[pow]; + int off = 0; + int pos = 0; + for (Integer len : chunks) { + for (int i = 0; i < len; i++) { + array[pos++] = Integer.valueOf(i == 0 ? 0 : 1); + } + off++; + } + return array; + } + +} diff --git a/ojluni/src/test/java/util/BitSet/And.java b/ojluni/src/test/java/util/BitSet/And.java new file mode 100644 index 00000000000..5b56eada014 --- /dev/null +++ b/ojluni/src/test/java/util/BitSet/And.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1999, 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. + */ + +package test.java.util.BitSet; + +/** + * @test + * @bug 4201163 + * @summary test the BitSet.and() method + */ +import java.util.BitSet; + +public final class And { + public static void main(String[] args) throws Exception { + BitSet a = new BitSet(); + BitSet b = new BitSet(); + + a.set(0); + a.set(70); + b.set(40); + a.and(b); + if (a.length() != 0) + throw new RuntimeException("Incorrect length after and()."); + } +} diff --git a/ojluni/src/test/java/util/BitSet/BSMethods.java b/ojluni/src/test/java/util/BitSet/BSMethods.java new file mode 100644 index 00000000000..26243c9e5d4 --- /dev/null +++ b/ojluni/src/test/java/util/BitSet/BSMethods.java @@ -0,0 +1,988 @@ +/* + * Copyright (c) 1998, 2014, 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 4098239 4107540 4080736 4261102 4274710 4305272 + * 4979017 4979028 4979031 5030267 6222207 8040806 + * @summary Test the operation of the methods of BitSet class + * @author Mike McCloskey, Martin Buchholz + * @run main/othervm BSMethods + * @key randomness + */ + +package test.java.util.BitSet; + +import java.util.*; + +/** + * This is a simple test class created to run tests on the BitSet class. + * + */ +public class BSMethods { + + private static Random generator = new Random(); + private static boolean failure = false; + + private static void fail(String diagnostic) { + new Error(diagnostic).printStackTrace(); + failure = true; + } + + private static void check(boolean condition) { + check(condition, "something's fishy"); + } + + private static void check(boolean condition, String diagnostic) { + if (! condition) + fail(diagnostic); + } + + private static void checkEmpty(BitSet s) { + check(s.isEmpty(), "isEmpty"); + check(s.length() == 0, "length"); + check(s.cardinality() == 0, "cardinality"); + check(s.equals(new BitSet()) , "equals"); + check(s.equals(new BitSet(0)) , "equals"); + check(s.equals(new BitSet(127)), "equals"); + check(s.equals(new BitSet(128)), "equals"); + check(s.nextSetBit(0) == -1, "nextSetBit"); + check(s.nextSetBit(127) == -1, "nextSetBit"); + check(s.nextSetBit(128) == -1, "nextSetBit"); + check(s.nextClearBit(0) == 0, "nextClearBit"); + check(s.nextClearBit(127) == 127, "nextClearBit"); + check(s.nextClearBit(128) == 128, "nextClearBit"); + check(s.toString().equals("{}"), "toString"); + check(! s.get(0), "get"); + } + + private static BitSet makeSet(int... elts) { + BitSet s = new BitSet(); + for (int elt : elts) + s.set(elt); + return s; + } + + private static void checkEquality(BitSet s, BitSet t) { + checkSanity(s, t); + check(s.equals(t), "equals"); + check(s.toString().equals(t.toString()), "equal strings"); + check(s.length() == t.length(), "equal lengths"); + check(s.cardinality() == t.cardinality(), "equal cardinalities"); + } + + private static void checkSanity(BitSet... sets) { + for (BitSet s : sets) { + int len = s.length(); + int cardinality1 = s.cardinality(); + int cardinality2 = 0; + for (int i = s.nextSetBit(0); i >= 0; i = s.nextSetBit(i+1)) { + check(s.get(i)); + cardinality2++; + } + check(s.nextSetBit(len) == -1, "last set bit"); + check(s.nextClearBit(len) == len, "last set bit"); + check(s.isEmpty() == (len == 0), "emptiness"); + check(cardinality1 == cardinality2, "cardinalities"); + check(len <= s.size(), "length <= size"); + check(len >= 0, "length >= 0"); + check(cardinality1 >= 0, "cardinality >= 0"); + } + } + + public static void main(String[] args) { + + //testFlipTime(); + + // These are the single bit versions + testSetGetClearFlip(); + + // Test the ranged versions + testClear(); + + testFlip(); + testSet(); + testGet(); + + // BitSet interaction calls + testAndNot(); + testAnd(); + testOr(); + testXor(); + + // Miscellaneous calls + testLength(); + testEquals(); + testNextSetBit(); + testNextClearBit(); + testIntersects(); + testCardinality(); + testEmpty(); + testEmpty2(); + testToString(); + testLogicalIdentities(); + + if (failure) + throw new RuntimeException("One or more BitSet failures."); + } + + private static void report(String testName, int failCount) { + System.err.println(testName+": " + + (failCount==0 ? "Passed":"Failed("+failCount+")")); + if (failCount > 0) + failure = true; + } + + private static void testFlipTime() { + // Make a fairly random bitset + BitSet b1 = new BitSet(); + b1.set(1000); + long startTime = System.currentTimeMillis(); + for(int x=0; x<100000; x++) { + b1.flip(100, 900); + } + long endTime = System.currentTimeMillis(); + long total = endTime - startTime; + System.out.println("Multiple word flip Time "+total); + + startTime = System.currentTimeMillis(); + for(int x=0; x<100000; x++) { + b1.flip(2, 44); + } + endTime = System.currentTimeMillis(); + total = endTime - startTime; + System.out.println("Single word flip Time "+total); + } + + private static void testNextSetBit() { + int failCount = 0; + + for (int i=0; i<100; i++) { + int numberOfSetBits = generator.nextInt(100) + 1; + BitSet testSet = new BitSet(); + int[] history = new int[numberOfSetBits]; + + // Set some random bits and remember them + int nextBitToSet = 0; + for (int x=0; x<numberOfSetBits; x++) { + nextBitToSet += generator.nextInt(30)+1; + history[x] = nextBitToSet; + testSet.set(nextBitToSet); + } + + // Verify their retrieval using nextSetBit() + int historyIndex = 0; + for(int x=testSet.nextSetBit(0); x>=0; x=testSet.nextSetBit(x+1)) { + if (x != history[historyIndex++]) + failCount++; + } + + checkSanity(testSet); + } + + report("NextSetBit ", failCount); + } + + private static void testNextClearBit() { + int failCount = 0; + + for (int i=0; i<1000; i++) { + BitSet b = new BitSet(256); + int[] history = new int[10]; + + // Set all the bits + for (int x=0; x<256; x++) + b.set(x); + + // Clear some random bits and remember them + int nextBitToClear = 0; + for (int x=0; x<10; x++) { + nextBitToClear += generator.nextInt(24)+1; + history[x] = nextBitToClear; + b.clear(nextBitToClear); + } + + // Verify their retrieval using nextClearBit() + int historyIndex = 0; + for(int x=b.nextClearBit(0); x<256; x=b.nextClearBit(x+1)) { + if (x != history[historyIndex++]) + failCount++; + } + + checkSanity(b); + } + + // regression test for 4350178 + BitSet bs = new BitSet(); + if (bs.nextClearBit(0) != 0) + failCount++; + for (int i = 0; i < 64; i++) { + bs.set(i); + if (bs.nextClearBit(0) != i+1) + failCount++; + } + + checkSanity(bs); + + report("NextClearBit ", failCount); + } + + private static void testSetGetClearFlip() { + int failCount = 0; + + for (int i=0; i<100; i++) { + BitSet testSet = new BitSet(); + HashSet<Integer> history = new HashSet<Integer>(); + + // Set a random number of bits in random places + // up to a random maximum + int nextBitToSet = 0; + int numberOfSetBits = generator.nextInt(100) + 1; + int highestPossibleSetBit = generator.nextInt(1000) + 1; + for (int x=0; x<numberOfSetBits; x++) { + nextBitToSet = generator.nextInt(highestPossibleSetBit); + history.add(new Integer(nextBitToSet)); + testSet.set(nextBitToSet); + } + + // Make sure each bit is set appropriately + for (int x=0; x<highestPossibleSetBit; x++) { + if (testSet.get(x) != history.contains(new Integer(x))) + failCount++; + } + + // Clear the bits + Iterator<Integer> setBitIterator = history.iterator(); + while (setBitIterator.hasNext()) { + Integer setBit = setBitIterator.next(); + testSet.clear(setBit.intValue()); + } + + // Verify they were cleared + for (int x=0; x<highestPossibleSetBit; x++) + if (testSet.get(x)) + failCount++; + if(testSet.length() != 0) + failCount++; + + // Set them with set(int, boolean) + setBitIterator = history.iterator(); + while (setBitIterator.hasNext()) { + Integer setBit = setBitIterator.next(); + testSet.set(setBit.intValue(), true); + } + + // Make sure each bit is set appropriately + for (int x=0; x<highestPossibleSetBit; x++) { + if (testSet.get(x) != history.contains(new Integer(x))) + failCount++; + } + + // Clear them with set(int, boolean) + setBitIterator = history.iterator(); + while (setBitIterator.hasNext()) { + Integer setBit = (Integer)setBitIterator.next(); + testSet.set(setBit.intValue(), false); + } + + // Verify they were cleared + for (int x=0; x<highestPossibleSetBit; x++) + if (testSet.get(x)) + failCount++; + if(testSet.length() != 0) + failCount++; + + // Flip them on + setBitIterator = history.iterator(); + while (setBitIterator.hasNext()) { + Integer setBit = (Integer)setBitIterator.next(); + testSet.flip(setBit.intValue()); + } + + // Verify they were flipped + for (int x=0; x<highestPossibleSetBit; x++) { + if (testSet.get(x) != history.contains(new Integer(x))) + failCount++; + } + + // Flip them off + setBitIterator = history.iterator(); + while (setBitIterator.hasNext()) { + Integer setBit = (Integer)setBitIterator.next(); + testSet.flip(setBit.intValue()); + } + + // Verify they were flipped + for (int x=0; x<highestPossibleSetBit; x++) + if (testSet.get(x)) + failCount++; + if(testSet.length() != 0) + failCount++; + + checkSanity(testSet); + } + + report("SetGetClearFlip ", failCount); + } + + private static void testAndNot() { + int failCount = 0; + + for (int i=0; i<100; i++) { + BitSet b1 = new BitSet(256); + BitSet b2 = new BitSet(256); + + // Set some random bits in first set and remember them + int nextBitToSet = 0; + for (int x=0; x<10; x++) + b1.set(generator.nextInt(255)); + + // Set some random bits in second set and remember them + for (int x=10; x<20; x++) + b2.set(generator.nextInt(255)); + + // andNot the sets together + BitSet b3 = (BitSet)b1.clone(); + b3.andNot(b2); + + // Examine each bit of b3 for errors + for(int x=0; x<256; x++) { + boolean bit1 = b1.get(x); + boolean bit2 = b2.get(x); + boolean bit3 = b3.get(x); + if (!(bit3 == (bit1 & (!bit2)))) + failCount++; + } + checkSanity(b1, b2, b3); + } + + report("AndNot ", failCount); + } + + private static void testAnd() { + int failCount = 0; + + for (int i=0; i<100; i++) { + BitSet b1 = new BitSet(256); + BitSet b2 = new BitSet(256); + + // Set some random bits in first set and remember them + int nextBitToSet = 0; + for (int x=0; x<10; x++) + b1.set(generator.nextInt(255)); + + // Set more random bits in second set and remember them + for (int x=10; x<20; x++) + b2.set(generator.nextInt(255)); + + // And the sets together + BitSet b3 = (BitSet)b1.clone(); + b3.and(b2); + + // Examine each bit of b3 for errors + for(int x=0; x<256; x++) { + boolean bit1 = b1.get(x); + boolean bit2 = b2.get(x); + boolean bit3 = b3.get(x); + if (!(bit3 == (bit1 & bit2))) + failCount++; + } + checkSanity(b1, b2, b3); + } + + // `and' that happens to clear the last word + BitSet b4 = makeSet(2, 127); + b4.and(makeSet(2, 64)); + checkSanity(b4); + if (!(b4.equals(makeSet(2)))) + failCount++; + + report("And ", failCount); + } + + private static void testOr() { + int failCount = 0; + + for (int i=0; i<100; i++) { + BitSet b1 = new BitSet(256); + BitSet b2 = new BitSet(256); + int[] history = new int[20]; + + // Set some random bits in first set and remember them + int nextBitToSet = 0; + for (int x=0; x<10; x++) { + nextBitToSet = generator.nextInt(255); + history[x] = nextBitToSet; + b1.set(nextBitToSet); + } + + // Set more random bits in second set and remember them + for (int x=10; x<20; x++) { + nextBitToSet = generator.nextInt(255); + history[x] = nextBitToSet; + b2.set(nextBitToSet); + } + + // Or the sets together + BitSet b3 = (BitSet)b1.clone(); + b3.or(b2); + + // Verify the set bits of b3 from the history + int historyIndex = 0; + for(int x=0; x<20; x++) { + if (!b3.get(history[x])) + failCount++; + } + + // Examine each bit of b3 for errors + for(int x=0; x<256; x++) { + boolean bit1 = b1.get(x); + boolean bit2 = b2.get(x); + boolean bit3 = b3.get(x); + if (!(bit3 == (bit1 | bit2))) + failCount++; + } + checkSanity(b1, b2, b3); + } + + report("Or ", failCount); + } + + private static void testXor() { + int failCount = 0; + + for (int i=0; i<100; i++) { + BitSet b1 = new BitSet(256); + BitSet b2 = new BitSet(256); + + // Set some random bits in first set and remember them + int nextBitToSet = 0; + for (int x=0; x<10; x++) + b1.set(generator.nextInt(255)); + + // Set more random bits in second set and remember them + for (int x=10; x<20; x++) + b2.set(generator.nextInt(255)); + + // Xor the sets together + BitSet b3 = (BitSet)b1.clone(); + b3.xor(b2); + + // Examine each bit of b3 for errors + for(int x=0; x<256; x++) { + boolean bit1 = b1.get(x); + boolean bit2 = b2.get(x); + boolean bit3 = b3.get(x); + if (!(bit3 == (bit1 ^ bit2))) + failCount++; + } + checkSanity(b1, b2, b3); + b3.xor(b3); checkEmpty(b3); + } + + // xor that happens to clear the last word + BitSet b4 = makeSet(2, 64, 127); + b4.xor(makeSet(64, 127)); + checkSanity(b4); + if (!(b4.equals(makeSet(2)))) + failCount++; + + report("Xor ", failCount); + } + + private static void testEquals() { + int failCount = 0; + + for (int i=0; i<100; i++) { + // Create BitSets of different sizes + BitSet b1 = new BitSet(generator.nextInt(1000)+1); + BitSet b2 = new BitSet(generator.nextInt(1000)+1); + + // Set some random bits + int nextBitToSet = 0; + for (int x=0; x<10; x++) { + nextBitToSet += generator.nextInt(50)+1; + b1.set(nextBitToSet); + b2.set(nextBitToSet); + } + + // Verify their equality despite different storage sizes + if (!b1.equals(b2)) + failCount++; + checkEquality(b1,b2); + } + + report("Equals ", failCount); + } + + private static void testLength() { + int failCount = 0; + + // Test length after set + for (int i=0; i<100; i++) { + BitSet b1 = new BitSet(256); + int highestSetBit = 0; + + for(int x=0; x<100; x++) { + int nextBitToSet = generator.nextInt(255); + if (nextBitToSet > highestSetBit) + highestSetBit = nextBitToSet; + b1.set(nextBitToSet); + if (b1.length() != highestSetBit + 1) + failCount++; + } + checkSanity(b1); + } + + // Test length after flip + for (int i=0; i<100; i++) { + BitSet b1 = new BitSet(256); + for(int x=0; x<100; x++) { + // Flip a random range twice + int rangeStart = generator.nextInt(100); + int rangeEnd = rangeStart + generator.nextInt(100); + b1.flip(rangeStart); + b1.flip(rangeStart); + if (b1.length() != 0) + failCount++; + b1.flip(rangeStart, rangeEnd); + b1.flip(rangeStart, rangeEnd); + if (b1.length() != 0) + failCount++; + } + checkSanity(b1); + } + + // Test length after or + for (int i=0; i<100; i++) { + BitSet b1 = new BitSet(256); + BitSet b2 = new BitSet(256); + int bit1 = generator.nextInt(100); + int bit2 = generator.nextInt(100); + int highestSetBit = (bit1 > bit2) ? bit1 : bit2; + b1.set(bit1); + b2.set(bit2); + b1.or(b2); + if (b1.length() != highestSetBit + 1) + failCount++; + checkSanity(b1, b2); + } + + report("Length ", failCount); + } + + private static void testClear() { + int failCount = 0; + + for (int i=0; i<1000; i++) { + BitSet b1 = new BitSet(); + + // Make a fairly random bitset + int numberOfSetBits = generator.nextInt(100) + 1; + int highestPossibleSetBit = generator.nextInt(1000) + 1; + + for (int x=0; x<numberOfSetBits; x++) + b1.set(generator.nextInt(highestPossibleSetBit)); + + BitSet b2 = (BitSet)b1.clone(); + + // Clear out a random range + int rangeStart = generator.nextInt(100); + int rangeEnd = rangeStart + generator.nextInt(100); + + // Use the clear(int, int) call on b1 + b1.clear(rangeStart, rangeEnd); + + // Use a loop on b2 + for (int x=rangeStart; x<rangeEnd; x++) + b2.clear(x); + + // Verify their equality + if (!b1.equals(b2)) { + System.out.println("rangeStart = " + rangeStart); + System.out.println("rangeEnd = " + rangeEnd); + System.out.println("b1 = " + b1); + System.out.println("b2 = " + b2); + failCount++; + } + checkEquality(b1,b2); + } + + report("Clear ", failCount); + } + + private static void testSet() { + int failCount = 0; + + // Test set(int, int) + for (int i=0; i<1000; i++) { + BitSet b1 = new BitSet(); + + // Make a fairly random bitset + int numberOfSetBits = generator.nextInt(100) + 1; + int highestPossibleSetBit = generator.nextInt(1000) + 1; + + for (int x=0; x<numberOfSetBits; x++) + b1.set(generator.nextInt(highestPossibleSetBit)); + + BitSet b2 = (BitSet)b1.clone(); + + // Set a random range + int rangeStart = generator.nextInt(100); + int rangeEnd = rangeStart + generator.nextInt(100); + + // Use the set(int, int) call on b1 + b1.set(rangeStart, rangeEnd); + + // Use a loop on b2 + for (int x=rangeStart; x<rangeEnd; x++) + b2.set(x); + + // Verify their equality + if (!b1.equals(b2)) { + System.out.println("Set 1"); + System.out.println("rangeStart = " + rangeStart); + System.out.println("rangeEnd = " + rangeEnd); + System.out.println("b1 = " + b1); + System.out.println("b2 = " + b2); + failCount++; + } + checkEquality(b1,b2); + } + + // Test set(int, int, boolean) + for (int i=0; i<100; i++) { + BitSet b1 = new BitSet(); + + // Make a fairly random bitset + int numberOfSetBits = generator.nextInt(100) + 1; + int highestPossibleSetBit = generator.nextInt(1000) + 1; + + for (int x=0; x<numberOfSetBits; x++) + b1.set(generator.nextInt(highestPossibleSetBit)); + + BitSet b2 = (BitSet)b1.clone(); + boolean setOrClear = generator.nextBoolean(); + + // Set a random range + int rangeStart = generator.nextInt(100); + int rangeEnd = rangeStart + generator.nextInt(100); + + // Use the set(int, int, boolean) call on b1 + b1.set(rangeStart, rangeEnd, setOrClear); + + // Use a loop on b2 + for (int x=rangeStart; x<rangeEnd; x++) + b2.set(x, setOrClear); + + // Verify their equality + if (!b1.equals(b2)) { + System.out.println("Set 2"); + System.out.println("b1 = " + b1); + System.out.println("b2 = " + b2); + failCount++; + } + checkEquality(b1,b2); + } + + report("Set ", failCount); + } + + private static void testFlip() { + int failCount = 0; + + for (int i=0; i<1000; i++) { + BitSet b1 = new BitSet(); + + // Make a fairly random bitset + int numberOfSetBits = generator.nextInt(100) + 1; + int highestPossibleSetBit = generator.nextInt(1000) + 1; + + for (int x=0; x<numberOfSetBits; x++) + b1.set(generator.nextInt(highestPossibleSetBit)); + + BitSet b2 = (BitSet)b1.clone(); + + // Flip a random range + int rangeStart = generator.nextInt(100); + int rangeEnd = rangeStart + generator.nextInt(100); + + // Use the flip(int, int) call on b1 + b1.flip(rangeStart, rangeEnd); + + // Use a loop on b2 + for (int x=rangeStart; x<rangeEnd; x++) + b2.flip(x); + + // Verify their equality + if (!b1.equals(b2)) + failCount++; + checkEquality(b1,b2); + } + + report("Flip ", failCount); + } + + private static void testGet() { + int failCount = 0; + + for (int i=0; i<1000; i++) { + BitSet b1 = new BitSet(); + + // Make a fairly random bitset + int numberOfSetBits = generator.nextInt(100) + 1; + int highestPossibleSetBit = generator.nextInt(1000) + 1; + + for (int x=0; x<numberOfSetBits; x++) + b1.set(generator.nextInt(highestPossibleSetBit)); + + // Get a new set from a random range + int rangeStart = generator.nextInt(100); + int rangeEnd = rangeStart + generator.nextInt(100); + + BitSet b2 = b1.get(rangeStart, rangeEnd); + + BitSet b3 = new BitSet(); + for(int x=rangeStart; x<rangeEnd; x++) + b3.set(x-rangeStart, b1.get(x)); + + // Verify their equality + if (!b2.equals(b3)) { + System.out.println("start="+rangeStart); + System.out.println("end="+rangeEnd); + System.out.println(b1); + System.out.println(b2); + System.out.println(b3); + failCount++; + } + checkEquality(b2,b3); + } + + report("Get ", failCount); + } + + + private static void testIntersects() { + int failCount = 0; + + for (int i=0; i<100; i++) { + BitSet b1 = new BitSet(256); + BitSet b2 = new BitSet(256); + + // Set some random bits in first set + int nextBitToSet = 0; + for (int x=0; x<30; x++) { + nextBitToSet = generator.nextInt(255); + b1.set(nextBitToSet); + } + + // Set more random bits in second set + for (int x=0; x<30; x++) { + nextBitToSet = generator.nextInt(255); + b2.set(nextBitToSet); + } + + // Make sure they intersect + nextBitToSet = generator.nextInt(255); + b1.set(nextBitToSet); + b2.set(nextBitToSet); + + if (!b1.intersects(b2)) + failCount++; + + // Remove the common set bits + b1.andNot(b2); + + // Make sure they don't intersect + if (b1.intersects(b2)) + failCount++; + + checkSanity(b1, b2); + } + + report("Intersects ", failCount); + } + + private static void testCardinality() { + int failCount = 0; + + for (int i=0; i<100; i++) { + BitSet b1 = new BitSet(256); + + // Set a random number of increasing bits + int nextBitToSet = 0; + int iterations = generator.nextInt(20)+1; + for (int x=0; x<iterations; x++) { + nextBitToSet += generator.nextInt(20)+1; + b1.set(nextBitToSet); + } + + if (b1.cardinality() != iterations) { + System.out.println("Iterations is "+iterations); + System.out.println("Cardinality is "+b1.cardinality()); + failCount++; + } + + checkSanity(b1); + } + + report("Cardinality ", failCount); + } + + private static void testEmpty() { + int failCount = 0; + + BitSet b1 = new BitSet(); + if (!b1.isEmpty()) + failCount++; + + int nextBitToSet = 0; + int numberOfSetBits = generator.nextInt(100) + 1; + int highestPossibleSetBit = generator.nextInt(1000) + 1; + for (int x=0; x<numberOfSetBits; x++) { + nextBitToSet = generator.nextInt(highestPossibleSetBit); + b1.set(nextBitToSet); + if (b1.isEmpty()) + failCount++; + b1.clear(nextBitToSet); + if (!b1.isEmpty()) + failCount++; + } + + report("Empty ", failCount); + } + + private static void testEmpty2() { + {BitSet t = new BitSet(); t.set(100); t.clear(3,600); checkEmpty(t);} + checkEmpty(new BitSet(0)); + checkEmpty(new BitSet(342)); + BitSet s = new BitSet(0); + checkEmpty(s); + s.clear(92); checkEmpty(s); + s.clear(127,127); checkEmpty(s); + s.set(127,127); checkEmpty(s); + s.set(128,128); checkEmpty(s); + BitSet empty = new BitSet(); + {BitSet t = new BitSet(); t.and (empty); checkEmpty(t);} + {BitSet t = new BitSet(); t.or (empty); checkEmpty(t);} + {BitSet t = new BitSet(); t.xor (empty); checkEmpty(t);} + {BitSet t = new BitSet(); t.andNot(empty); checkEmpty(t);} + {BitSet t = new BitSet(); t.and (t); checkEmpty(t);} + {BitSet t = new BitSet(); t.or (t); checkEmpty(t);} + {BitSet t = new BitSet(); t.xor (t); checkEmpty(t);} + {BitSet t = new BitSet(); t.andNot(t); checkEmpty(t);} + {BitSet t = new BitSet(); t.and(makeSet(1)); checkEmpty(t);} + {BitSet t = new BitSet(); t.and(makeSet(127)); checkEmpty(t);} + {BitSet t = new BitSet(); t.and(makeSet(128)); checkEmpty(t);} + {BitSet t = new BitSet(); t.flip(7);t.flip(7); checkEmpty(t);} + {BitSet t = new BitSet(); checkEmpty(t.get(200,300));} + {BitSet t = makeSet(2,5); check(t.get(2,6).equals(makeSet(0,3)),"");} + } + + private static void testToString() { + check(new BitSet().toString().equals("{}")); + check(makeSet(2,3,42,43,234).toString().equals("{2, 3, 42, 43, 234}")); + + final long MB = 1024*1024; + if (Runtime.getRuntime().maxMemory() >= 512*MB) { + // only run it if we have enough memory + try { + check(makeSet(Integer.MAX_VALUE-1).toString().equals( + "{" + (Integer.MAX_VALUE-1) + "}")); + check(makeSet(Integer.MAX_VALUE).toString().equals( + "{" + Integer.MAX_VALUE + "}")); + check(makeSet(0, 1, Integer.MAX_VALUE-1, Integer.MAX_VALUE).toString().equals( + "{0, 1, " + (Integer.MAX_VALUE-1) + ", " + Integer.MAX_VALUE + "}")); + } catch (IndexOutOfBoundsException exc) { + fail("toString() with indices near MAX_VALUE"); + } + } + } + + private static void testLogicalIdentities() { + int failCount = 0; + + // Verify that (!b1)|(!b2) == !(b1&b2) + for (int i=0; i<50; i++) { + // Construct two fairly random bitsets + BitSet b1 = new BitSet(); + BitSet b2 = new BitSet(); + + int numberOfSetBits = generator.nextInt(100) + 1; + int highestPossibleSetBit = generator.nextInt(1000) + 1; + + for (int x=0; x<numberOfSetBits; x++) { + b1.set(generator.nextInt(highestPossibleSetBit)); + b2.set(generator.nextInt(highestPossibleSetBit)); + } + + BitSet b3 = (BitSet) b1.clone(); + BitSet b4 = (BitSet) b2.clone(); + + for (int x=0; x<highestPossibleSetBit; x++) { + b1.flip(x); + b2.flip(x); + } + b1.or(b2); + b3.and(b4); + for (int x=0; x<highestPossibleSetBit; x++) + b3.flip(x); + if (!b1.equals(b3)) + failCount++; + checkSanity(b1, b2, b3, b4); + } + + // Verify that (b1&(!b2)|(b2&(!b1) == b1^b2 + for (int i=0; i<50; i++) { + // Construct two fairly random bitsets + BitSet b1 = new BitSet(); + BitSet b2 = new BitSet(); + + int numberOfSetBits = generator.nextInt(100) + 1; + int highestPossibleSetBit = generator.nextInt(1000) + 1; + + for (int x=0; x<numberOfSetBits; x++) { + b1.set(generator.nextInt(highestPossibleSetBit)); + b2.set(generator.nextInt(highestPossibleSetBit)); + } + + BitSet b3 = (BitSet) b1.clone(); + BitSet b4 = (BitSet) b2.clone(); + BitSet b5 = (BitSet) b1.clone(); + BitSet b6 = (BitSet) b2.clone(); + + for (int x=0; x<highestPossibleSetBit; x++) + b2.flip(x); + b1.and(b2); + for (int x=0; x<highestPossibleSetBit; x++) + b3.flip(x); + b3.and(b4); + b1.or(b3); + b5.xor(b6); + if (!b1.equals(b5)) + failCount++; + checkSanity(b1, b2, b3, b4, b5, b6); + } + report("Logical Identities ", failCount); + } + +} diff --git a/ojluni/src/test/java/util/BitSet/ImportExport.java b/ojluni/src/test/java/util/BitSet/ImportExport.java new file mode 100644 index 00000000000..83417611f44 --- /dev/null +++ b/ojluni/src/test/java/util/BitSet/ImportExport.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2007, 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 5037068 + * @summary Test import/export constructors and methods + * @author Martin Buchholz + * @key randomness + */ + +package test.java.util.BitSet; + +import java.nio.*; +import java.util.*; + +public class ImportExport { + final Random rnd = new Random(); + + void equal(byte[] x, byte[] y) { + check(Arrays.equals(x, y)); + } + + void equal(long[] x, long[] y) { + check(Arrays.equals(x, y)); + } + + void equal(byte[] bytes, BitSet s) { + equal(s, BitSet.valueOf(bytes)); + equal(s, BitSet.valueOf(ByteBuffer.wrap(bytes))); + equal(s, BitSet.valueOf( + ByteBuffer.wrap( + Arrays.copyOf(bytes, bytes.length + 8 + rnd.nextInt(8))) + .order(ByteOrder.LITTLE_ENDIAN) + .asLongBuffer())); + } + + void checkEmptyBitSet(BitSet s) { + equal(s.toByteArray(), new byte[0]); + equal(s.toLongArray(), new long[0]); + check(s.isEmpty()); + } + + void test(String[] args) throws Throwable { + for (int i = 0; i < 17; i++) { + byte[] bytes = new byte[i]; + BitSet s = new BitSet(); + equal(bytes, s); + equal(BitSet.valueOf(bytes).toByteArray(), new byte[0]); + if (i > 0) { + int k = rnd.nextInt(i); + for (int j = 0; j < 8; j++) { + bytes[k] |= 1 << j; + s.set(8*k+j); + equal(bytes, s); + byte[] expected = new byte[k+1]; expected[k] = bytes[k]; + equal(BitSet.valueOf(bytes).toByteArray(), expected); + ByteBuffer bb = ByteBuffer.wrap(bytes); + bb.position(k); + equal(BitSet.valueOf(bb).toByteArray(), + new byte[]{bytes[k]}); + } + } + } + for (int i = 0; i < 100; i++) { + byte[] bytes = new byte[rnd.nextInt(17)]; + for (int j = 0; j < bytes.length; j++) + bytes[j] = (byte) rnd.nextInt(0x100); + BitSet s = BitSet.valueOf(bytes); + byte[] expected = s.toByteArray(); + equal(expected.length, (s.length()+7)/8); + if (bytes.length == 0) + continue; + if (expected.length > 0) + check(expected[expected.length-1] != 0); + if (bytes[bytes.length-1] != 0) + equal(bytes, expected); + int n = rnd.nextInt(8 * bytes.length); + equal(s.get(n), ((bytes[n/8] & (1<<(n%8))) != 0)); + } + + for (int i = 0; i < 3; i++) { + checkEmptyBitSet(BitSet.valueOf(new byte[i])); + checkEmptyBitSet(BitSet.valueOf(ByteBuffer.wrap(new byte[i]))); + checkEmptyBitSet(BitSet.valueOf(new byte[i*64])); + checkEmptyBitSet(BitSet.valueOf(ByteBuffer.wrap(new byte[i*64]))); + checkEmptyBitSet(BitSet.valueOf(new long[i])); + checkEmptyBitSet(BitSet.valueOf(LongBuffer.wrap(new long[i]))); + } + + { + long[] longs = new long[rnd.nextInt(10)]; + for (int i = 0; i < longs.length; i++) + longs[i] = rnd.nextLong(); + LongBuffer b1 = LongBuffer.wrap(longs); + LongBuffer b2 = LongBuffer.allocate(longs.length + 10); + for (int i = 0; i < b2.limit(); i++) + b2.put(i, rnd.nextLong()); + int beg = rnd.nextInt(10); + b2.position(beg); + b2.put(longs); + b2.limit(b2.position()); + b2.position(beg); + BitSet s1 = BitSet.valueOf(longs); + BitSet s2 = BitSet.valueOf(b1); + BitSet s3 = BitSet.valueOf(b2); + equal(s1, s2); + equal(s1, s3); + if (longs.length > 0 && longs[longs.length -1] != 0) { + equal(longs, s1.toLongArray()); + equal(longs, s2.toLongArray()); + equal(longs, s3.toLongArray()); + } + for (int i = 0; i < 64 * longs.length; i++) { + equal(s1.get(i), ((longs [i/64] & (1L<<(i%64))) != 0)); + equal(s2.get(i), ((b1.get(i/64) & (1L<<(i%64))) != 0)); + equal(s3.get(i), ((b2.get(b2.position()+i/64) & (1L<<(i%64))) != 0)); + } + } + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new ImportExport().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/ojluni/src/test/java/util/BitSet/MemoryLeak.java b/ojluni/src/test/java/util/BitSet/MemoryLeak.java new file mode 100644 index 00000000000..948487385b4 --- /dev/null +++ b/ojluni/src/test/java/util/BitSet/MemoryLeak.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997, 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 4091185 + * @summary Repeatedly OR BitSets; No OutOfMemoryException should result + */ + +package test.java.util.BitSet; + +import java.util.*; + +/** + * This is a simple test class that repeatedly ORs two + * BitSets of unequal size together. Previously this + * caused an exponential growth in the memory underlying + * the BitSets quickly using all available memory + */ +public class MemoryLeak { + + public static void main(String[] args) { + + //create 2 test bitsets + BitSet setOne = new BitSet(); + BitSet setTwo = new BitSet(); + + setOne.set(64); + setTwo.set(129); + + //test for bug #4091185 + //exponential set growth causing memory depletion + for (int i = 0; i < 50; i++) { + setOne.or(setTwo); + setTwo.or(setOne); + } + } +} diff --git a/ojluni/src/test/java/util/BitSet/PreviousBits.java b/ojluni/src/test/java/util/BitSet/PreviousBits.java new file mode 100644 index 00000000000..389d9fae883 --- /dev/null +++ b/ojluni/src/test/java/util/BitSet/PreviousBits.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2007, 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 6410729 6586631 + * @summary Test previousClearBit, previousSetBit + * @key randomness + */ + +package test.java.util.BitSet; + +import java.util.*; + +public class PreviousBits { + + void testHashCode(final BitSet s) { + long h = 1234; + long[] words = s.toLongArray(); + for (int i = words.length; --i >= 0; ) + h ^= words[i] * (i + 1); + equal((int)((h >> 32) ^ h), s.hashCode()); + } + + void testOutOfBounds(final BitSet s) { + THROWS(IndexOutOfBoundsException.class, + new F(){void f(){ s.previousSetBit(-2);}}, + new F(){void f(){ s.previousClearBit(-2);}}, + new F(){void f(){ s.previousSetBit(Integer.MIN_VALUE);}}, + new F(){void f(){ s.previousClearBit(Integer.MIN_VALUE);}}, + new F(){void f(){ s.nextSetBit(-1);}}, + new F(){void f(){ s.nextClearBit(-1);}}, + new F(){void f(){ s.nextSetBit(Integer.MIN_VALUE);}}, + new F(){void f(){ s.nextClearBit(Integer.MIN_VALUE);}}); + } + + void test(String[] args) throws Throwable { + final BitSet s = new BitSet(); + + // Test empty bitset + testOutOfBounds(s); + testHashCode(s); + + for (int i = -1; i < 93;) { + equal(-1, s.previousSetBit(i)); + equal( i, s.previousClearBit(i)); + i++; + equal(-1, s.nextSetBit(i)); + equal( i, s.nextClearBit(i)); + } + + // Test "singleton" bitsets + for (int j = 0; j < 161; j++) { + s.clear(); + s.set(j); + testOutOfBounds(s); + testHashCode(s); + + for (int i = -1; i < j; i++) { + equal(-1, s.previousSetBit(i)); + equal( i, s.previousClearBit(i)); + if (i >= 0) { + equal(j, s.nextSetBit(i)); + equal(i, s.nextClearBit(i)); + } + } + + equal(j, s.previousSetBit(j)); + equal(j-1, s.previousClearBit(j)); + equal(j, s.nextSetBit(j)); + equal(j+1, s.nextClearBit(j)); + + for (int i = j+1; i < j+100; i++) { + equal(j, s.previousSetBit(i)); + equal(i, s.previousClearBit(i)); + equal(-1, s.nextSetBit(i)); + equal(i, s.nextClearBit(i)); + } + } + + // set even bits + s.clear(); + for (int i = 0; i <= 128; i+=2) + s.set(i); + testHashCode(s); + for (int i = 1; i <= 128; i++) { + equal(s.previousSetBit(i), + ((i & 1) == 0) ? i : i - 1); + equal(s.previousClearBit(i), + ((i & 1) == 0) ? i - 1 : i); + } + + // set odd bits as well + for (int i = 1; i <= 128; i+=2) + s.set(i); + testHashCode(s); + for (int i = 1; i <= 128; i++) { + equal(s.previousSetBit(i), i); + equal(s.previousClearBit(i), -1); + } + + // Test loops documented in javadoc + Random rnd = new Random(); + s.clear(); + for (int i = 0; i < 10; i++) + s.set(rnd.nextInt(1066)); + List<Integer> down = new ArrayList<Integer>(); + for (int i = s.length(); (i = s.previousSetBit(i-1)) >= 0; ) + down.add(i); + List<Integer> up = new ArrayList<Integer>(); + for (int i = s.nextSetBit(0); i >= 0; i = s.nextSetBit(i+1)) + up.add(i); + Collections.reverse(up); + equal(up, down); + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new PreviousBits().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + abstract class F {abstract void f() throws Throwable;} + void THROWS(Class<? extends Throwable> k, F... fs) { + for (F f : fs) + try {f.f(); fail("Expected " + k.getName() + " not thrown");} + catch (Throwable t) { + if (k.isAssignableFrom(t.getClass())) pass(); + else unexpected(t);}} +} diff --git a/ojluni/src/test/java/util/BitSet/StickySize.java b/ojluni/src/test/java/util/BitSet/StickySize.java new file mode 100644 index 00000000000..76cfd3d89ad --- /dev/null +++ b/ojluni/src/test/java/util/BitSet/StickySize.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2006, 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 6404711 + * @summary Check capacity management + * @author Martin Buchholz + */ + +package test.java.util.BitSet; + +import java.io.*; +import java.util.*; + +public class StickySize { + static void equalClones(BitSet s, int expectedSize) { + equal(expectedSize, clone(s).size()); + equal(expectedSize, serialClone(s).size()); + equal(expectedSize, s.size()); + equal(clone(s), serialClone(s)); + } + + private static void realMain(String[] args) { + BitSet s; + + s = new BitSet(); // non-sticky + equal(s.size(), 64); + equalClones(s, 0); + s.set(3*64); + s.set(7*64); + equal(s.size(), 8*64); + equalClones(s, 8*64); + s.clear(7*64); + equal(s.size(), 8*64); + equalClones(s, 4*64); + + s = new BitSet(8*64); // sticky + equalClones(s, 8*64); + s.set(3*64); + s.set(7*64); + equalClones(s, 8*64); + s.clear(7*64); + equalClones(s, 8*64); + equalClones(clone(s), 8*64); + equalClones(serialClone(s), 8*64); + s.set(17*64); // Expand beyond sticky size + equalClones(s, 18*64); + s.clear(17*64); + equalClones(s, 4*64); + } + + static BitSet clone(BitSet s) { + return (BitSet) s.clone(); + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void check(boolean cond) {if (cond) pass(); else fail();} + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + static byte[] serializedForm(Object obj) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(obj); + return baos.toByteArray(); + } catch (IOException e) { throw new RuntimeException(e); }} + static Object readObject(byte[] bytes) + throws IOException, ClassNotFoundException { + InputStream is = new ByteArrayInputStream(bytes); + return new ObjectInputStream(is).readObject();} + @SuppressWarnings("unchecked") + static <T> T serialClone(T obj) { + try { return (T) readObject(serializedForm(obj)); } + catch (Exception e) { throw new RuntimeException(e); }} +} diff --git a/ojluni/src/test/java/util/BitSet/stream/BitSetStreamTest.java b/ojluni/src/test/java/util/BitSet/stream/BitSetStreamTest.java new file mode 100644 index 00000000000..629abc9c158 --- /dev/null +++ b/ojluni/src/test/java/util/BitSet/stream/BitSetStreamTest.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2012, 2017, 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. + */ + +package test.java.util.BitSet.stream; + +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Collection; +import java.util.List; +import java.util.PrimitiveIterator; +import java.util.Random; +import java.util.Spliterator; +import org.openjdk.testlib.java.util.SpliteratorOfIntDataBuilder; +import org.openjdk.testlib.java.util.SpliteratorTestHelper; +import java.util.function.IntConsumer; +import java.util.function.IntSupplier; +import java.util.function.Supplier; +import java.util.stream.IntStream; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static java.util.stream.Collectors.toList; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertThrows; +import static org.testng.Assert.assertTrue; + +/** + * @test + * @summary test BitSet stream + * @bug 8012645 8076442 + * @requires os.maxMemory >= 2g + * @library /lib/testlibrary/bootlib + * @build java.base/java.util.SpliteratorTestHelper + * java.base/java.util.SpliteratorOfIntDataBuilder + * @run testng/othervm -Xms512m -Xmx1024m BitSetStreamTest + */ +public class BitSetStreamTest extends SpliteratorTestHelper { + static class Fibs implements IntSupplier { + private int n1 = 0; + private int n2 = 1; + + static int fibs(int n) { + Fibs f = new Fibs(); + while (n-- > 0) f.getAsInt(); + return f.getAsInt(); + } + + public int getAsInt() { int s = n1; n1 = n2; n2 = s + n1; return s; } + } + + @Test + public void testFibs() { + Fibs f = new Fibs(); + assertEquals(0, f.getAsInt()); + assertEquals(1, f.getAsInt()); + assertEquals(1, f.getAsInt()); + assertEquals(2, f.getAsInt()); + assertEquals(3, f.getAsInt()); + assertEquals(5, f.getAsInt()); + assertEquals(8, f.getAsInt()); + assertEquals(13, f.getAsInt()); + assertEquals(987, Fibs.fibs(16)); + } + + + @DataProvider(name = "cases") + public static Object[][] produceCases() { + return new Object[][] { + { "none", IntStream.empty() }, + { "index 0", IntStream.of(0) }, + { "index 255", IntStream.of(255) }, + { "index 0 and 255", IntStream.of(0, 255) }, + // Android-removed: these case OOME. + // { "index Integer.MAX_VALUE", IntStream.of(Integer.MAX_VALUE) }, + // { "index Integer.MAX_VALUE - 1", IntStream.of(Integer.MAX_VALUE - 1) }, + // { "index 0 and Integer.MAX_VALUE", IntStream.of(0, Integer.MAX_VALUE) }, + { "every bit", IntStream.range(0, 255) }, + { "step 2", IntStream.range(0, 255).map(f -> f * 2) }, + { "step 3", IntStream.range(0, 255).map(f -> f * 3) }, + { "step 5", IntStream.range(0, 255).map(f -> f * 5) }, + { "step 7", IntStream.range(0, 255).map(f -> f * 7) }, + { "1, 10, 100, 1000", IntStream.of(1, 10, 100, 1000) }, + { "25 fibs", IntStream.generate(new Fibs()).limit(25) } + }; + } + + @Test(dataProvider = "cases") + public void testBitsetStream(String name, IntStream data) { + BitSet bs = data.collect(BitSet::new, BitSet::set, BitSet::or); + + assertEquals(bs.cardinality(), bs.stream().count()); + + int[] indexHolder = new int[] { -1 }; + bs.stream().forEach(i -> { + int ei = indexHolder[0]; + indexHolder[0] = bs.nextSetBit(ei + 1); + assertEquals(i, indexHolder[0]); + }); + + PrimitiveIterator.OfInt it = bs.stream().iterator(); + for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { + assertTrue(it.hasNext()); + assertEquals(it.nextInt(), i); + if (i == Integer.MAX_VALUE) + break; // or (i + 1) would overflow + } + assertFalse(it.hasNext()); + } + + static Object[][] spliteratorOfIntDataProvider; + + @DataProvider(name = "BitSet.stream.spliterator") + public static Object[][] spliteratorOfIntDataProvider() { + if (spliteratorOfIntDataProvider != null) { + return spliteratorOfIntDataProvider; + } + + List<Object[]> data = new ArrayList<>(); + + Object[][] bitStreamTestcases = new Object[][] { + { "none", IntStream.empty().toArray() }, + { "index 0", IntStream.of(0).toArray() }, + { "index 255", IntStream.of(255).toArray() }, + { "index 0 and 255", IntStream.of(0, 255).toArray() }, + // Android-removed: these cause OOME. + // { "index Integer.MAX_VALUE", IntStream.of(Integer.MAX_VALUE).toArray() }, + // { "index Integer.MAX_VALUE - 1", IntStream.of(Integer.MAX_VALUE - 1).toArray() }, + // { "index 0 and Integer.MAX_VALUE", IntStream.of(0, Integer.MAX_VALUE).toArray() }, + { "every bit", IntStream.range(0, 255).toArray() }, + { "step 2", IntStream.range(0, 255).map(f -> f * 2).toArray() }, + { "step 3", IntStream.range(0, 255).map(f -> f * 3).toArray() }, + { "step 5", IntStream.range(0, 255).map(f -> f * 5).toArray() }, + { "step 7", IntStream.range(0, 255).map(f -> f * 7).toArray() }, + { "1, 10, 100, 1000", IntStream.of(1, 10, 100, 1000).toArray() }, + }; + for (Object[] tc : bitStreamTestcases) { + String description = (String)tc[0]; + int[] exp = (int[])tc[1]; + SpliteratorOfIntDataBuilder db = new SpliteratorOfIntDataBuilder( + data, IntStream.of(exp).boxed().collect(toList())); + + db.add("BitSet.stream.spliterator() {" + description + "}", () -> + IntStream.of(exp).collect(BitSet::new, BitSet::set, BitSet::or). + stream().spliterator() + ); + } + return spliteratorOfIntDataProvider = data.toArray(new Object[0][]); + } + + @Test(dataProvider = "BitSet.stream.spliterator") + public void testIntNullPointerException(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { + assertThrows(NullPointerException.class, () -> s.get().forEachRemaining((IntConsumer) null)); + assertThrows(NullPointerException.class, () -> s.get().tryAdvance((IntConsumer) null)); + } + + @Test(dataProvider = "BitSet.stream.spliterator") + public void testIntForEach(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { + testForEach(exp, s, intBoxingConsumer()); + } + + @Test(dataProvider = "BitSet.stream.spliterator") + public void testIntTryAdvance(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { + testTryAdvance(exp, s, intBoxingConsumer()); + } + + @Test(dataProvider = "BitSet.stream.spliterator") + public void testIntMixedTryAdvanceForEach(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { + testMixedTryAdvanceForEach(exp, s, intBoxingConsumer()); + } + + @Test(dataProvider = "BitSet.stream.spliterator") + public void testIntMixedTraverseAndSplit(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { + testMixedTraverseAndSplit(exp, s, intBoxingConsumer()); + } + + @Test(dataProvider = "BitSet.stream.spliterator") + public void testIntSplitAfterFullTraversal(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { + testSplitAfterFullTraversal(s, intBoxingConsumer()); + } + + @Test(dataProvider = "BitSet.stream.spliterator") + public void testIntSplitOnce(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { + testSplitOnce(exp, s, intBoxingConsumer()); + } + + @Test(dataProvider = "BitSet.stream.spliterator") + public void testIntSplitSixDeep(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { + testSplitSixDeep(exp, s, intBoxingConsumer()); + } + + @Test(dataProvider = "BitSet.stream.spliterator") + public void testIntSplitUntilNull(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { + testSplitUntilNull(exp, s, intBoxingConsumer()); + } + + @Test + public void testRandomStream() { + final int size = 1024 * 1024; + final int[] seeds = { + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, + 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97}; + final byte[] bytes = new byte[size]; + for (int seed : seeds) { + final Random random = new Random(seed); + random.nextBytes(bytes); + + BitSet bitSet = BitSet.valueOf(bytes); + testBitSetContents(bitSet, bitSet.stream().toArray()); + testBitSetContents(bitSet, bitSet.stream().parallel().toArray()); + } + } + + void testBitSetContents(BitSet bitSet, int[] array) { + int cardinality = bitSet.cardinality(); + assertEquals(array.length, cardinality); + int nextSetBit = -1; + for (int i = 0; i < cardinality; i++) { + nextSetBit = bitSet.nextSetBit(nextSetBit + 1); + assertEquals(array[i], nextSetBit); + } + } +} diff --git a/ojluni/src/test/java/util/Collections/AddAll.java b/ojluni/src/test/java/util/Collections/AddAll.java new file mode 100644 index 00000000000..644035be0df --- /dev/null +++ b/ojluni/src/test/java/util/Collections/AddAll.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2003, 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 4822887 + * @summary Basic test for Collections.addAll + * @author Josh Bloch + * @key randomness + */ + +package test.java.util.Collections; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; + +public class AddAll { + static final int N = 100; + public static void main(String[] args) { + test(new ArrayList<Integer>()); + test(new LinkedList<Integer>()); + test(new HashSet<Integer>()); + test(new LinkedHashSet<Integer>()); + } + + private static Random rnd = new Random(); + + static void test(Collection<Integer> c) { + int x = 0; + for (int i = 0; i < N; i++) { + int rangeLen = rnd.nextInt(10); + if (Collections.addAll(c, range(x, x + rangeLen)) != + (rangeLen != 0)) + throw new RuntimeException("" + rangeLen); + x += rangeLen; + } + if (c instanceof List) { + if (!c.equals(Arrays.asList(range(0, x)))) + throw new RuntimeException(x +": "+c); + } else { + if (!c.equals(new HashSet<Integer>(Arrays.asList(range(0, x))))) + throw new RuntimeException(x +": "+c); + } + } + + private static Integer[] range(int from, int to) { + Integer[] result = new Integer[to - from]; + for (int i = from, j=0; i < to; i++, j++) + result[j] = new Integer(i); + return result; + } +} diff --git a/ojluni/src/test/java/util/Collections/AsLifoQueue.java b/ojluni/src/test/java/util/Collections/AsLifoQueue.java new file mode 100644 index 00000000000..1c64d973dd9 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/AsLifoQueue.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2005, 2014, 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 6301085 6192552 6365601 + * @summary Basic tests for asLifoQueue + * @author Martin Buchholz + */ + +package test.java.util.Collections; + +import java.util.*; +import java.util.concurrent.*; + +public class AsLifoQueue { + + private static void realMain(String[] args) throws Throwable { + try { + Deque<String> deq = new ArrayDeque<String>(); + check(deq.addAll(Arrays.asList("b", "a", "c"))); + equal(deq.toString(), "[b, a, c]"); + check(deq.add("d")); + equal(deq.toString(), "[b, a, c, d]"); + Queue<String> q = Collections.asLifoQueue(deq); + check(q.add("e")); + equal(deq.toString(),"[e, b, a, c, d]"); + } catch (Throwable t) { unexpected(t); } + + // Inspired by an excellent bug report by Jason Mehrens + try { + final Queue<String> q = + Collections.asLifoQueue(new LinkedBlockingDeque<String>(3)); + check(q.isEmpty()); equal(q.size(), 0); + check(q.add("a")); check(! q.isEmpty()); equal(q.size(), 1); + check(q.offer("b")); + check(q.add("c")); + equal(q.size(), 3); + check(! q.offer("d")); + equal(q.size(), 3); + THROWS(IllegalStateException.class, () -> q.add("d")); + equal(q.size(), 3); + equal(q.toString(), "[c, b, a]"); + equal(q.peek(), "c"); + equal(q.element(), "c"); + equal(q.remove(), "c"); + equal(q.poll(), "b"); + equal(q.peek(), "a"); + equal(q.remove(), "a"); + THROWS(NoSuchElementException.class, () -> q.remove()); + equal(q.poll(), null); + check(q.isEmpty()); + equal(q.size(), 0); + } catch (Throwable t) { unexpected(t); } + + THROWS(NullPointerException.class, () -> Collections.asLifoQueue(null)); + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void check(boolean cond) {if (cond) pass(); else fail();} + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + interface Fun {void f() throws Throwable;} + private static void THROWS(Class<? extends Throwable> k, Fun... fs) { + for (Fun f : fs) + try { f.f(); fail("Expected " + k.getName() + " not thrown"); } + catch (Throwable t) { + if (k.isAssignableFrom(t.getClass())) pass(); + else unexpected(t);}} +} diff --git a/ojluni/src/test/java/util/Collections/BigBinarySearch.java b/ojluni/src/test/java/util/Collections/BigBinarySearch.java new file mode 100644 index 00000000000..30046b9874a --- /dev/null +++ b/ojluni/src/test/java/util/Collections/BigBinarySearch.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2006, 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 5045582 + * @summary binarySearch of Collections larger than 1<<30 + * @author Martin Buchholz + */ + +package test.java.util.Collections; + +import java.util.AbstractList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.RandomAccess; + +public class BigBinarySearch { + + // Allows creation of very "big" collections without using too + // many real resources + static class SparseIntegerList + extends AbstractList<Integer> + implements RandomAccess + { + private Map<Integer,Integer> m = new HashMap<>(); + + public Integer get(int i) { + if (i < 0) throw new IndexOutOfBoundsException(""+i); + Integer v = m.get(i); + return (v == null) ? Integer.valueOf(0) : v; + } + + public int size() { + return Collections.max(m.keySet()) + 1; + } + + public Integer set(int i, Integer v) { + if (i < 0) throw new IndexOutOfBoundsException(""+i); + Integer ret = get(i); + if (v == 0) + m.remove(i); + else + m.put(i, v); + return ret; + } + } + + /** Checks that binarySearch finds an element where we got it. */ + private static void checkBinarySearch(List<Integer> l, int i) { + try { equal(i, Collections.binarySearch(l, l.get(i))); } + catch (Throwable t) { unexpected(t); } + } + + /** Checks that binarySearch finds an element where we got it. */ + private static void checkBinarySearch(List<Integer> l, int i, + Comparator<Integer> comparator) { + try { equal(i, Collections.binarySearch(l, l.get(i), comparator)); } + catch (Throwable t) { unexpected(t); } + } + + private static void realMain(String[] args) throws Throwable { + final int n = (1<<30) + 47; + + System.out.println("binarySearch(List<Integer>, Integer)"); + List<Integer> big = new SparseIntegerList(); + big.set( 0, -44); + big.set( 1, -43); + big.set(n-2, 43); + big.set(n-1, 44); + int[] ints = { 0, 1, n-2, n-1 }; + Comparator<Integer> reverse = Collections.reverseOrder(); + Comparator<Integer> natural = Collections.reverseOrder(reverse); + + for (int i : ints) { + checkBinarySearch(big, i); + checkBinarySearch(big, i, null); + checkBinarySearch(big, i, natural); + } + for (int i : ints) + big.set(i, - big.get(i)); + for (int i : ints) + checkBinarySearch(big, i, reverse); + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void check(boolean cond) {if (cond) pass(); else fail();} + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/ojluni/src/test/java/util/Collections/BinarySearchNullComparator.java b/ojluni/src/test/java/util/Collections/BinarySearchNullComparator.java new file mode 100644 index 00000000000..8472e8de57c --- /dev/null +++ b/ojluni/src/test/java/util/Collections/BinarySearchNullComparator.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2001, 2004, 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 4528331 5006032 + * @summary Test Collections.binarySearch() with a null comparator + */ + +package test.java.util.Collections; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class BinarySearchNullComparator { + public static void main(String[] args) throws Exception { + List list = Arrays.asList(new String[] {"I", "Love", "You"}); + + int result = Collections.binarySearch(list, "You", null); + if (result != 2) + throw new Exception("Result: " + result); + } +} diff --git a/ojluni/src/test/java/util/Collections/CheckedIdentityMap.java b/ojluni/src/test/java/util/Collections/CheckedIdentityMap.java new file mode 100644 index 00000000000..fd8a24d0de9 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/CheckedIdentityMap.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2007, 2013, 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 6585904 + * @run testng CheckedIdentityMap + * @summary Checked collections with underlying maps with identity comparisons + */ + +package test.java.util.Collections; + +import org.testng.annotations.Test; + +import java.util.IdentityHashMap; +import java.util.Map; + +import static java.util.Collections.checkedMap; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotEquals; + +public class CheckedIdentityMap { + + @Test + public void testHashCode() { + Map<Integer, Integer> m1 = checkedMap( + new IdentityHashMap<Integer, Integer>(), + Integer.class, Integer.class); + Map<Integer, Integer> m2 = checkedMap( + new IdentityHashMap<Integer, Integer>(), + Integer.class, Integer.class); + // NB: these are unique instances. Compare vs. Integer.valueOf(1) + m1.put(new Integer(1), new Integer(1)); + m2.put(new Integer(1), new Integer(1)); + + Map.Entry<Integer, Integer> e1 = m1.entrySet().iterator().next(); + Map.Entry<Integer, Integer> e2 = m2.entrySet().iterator().next(); + + assertNotEquals(e1, e2); + assertEquals(e1.hashCode(), hashCode(e1)); + assertEquals(e2.hashCode(), hashCode(e2)); + } + + static int hashCode(Map.Entry<?,?> e) { + return (System.identityHashCode(e.getKey()) ^ + System.identityHashCode(e.getValue())); + } +} diff --git a/ojluni/src/test/java/util/Collections/CheckedListBash.java b/ojluni/src/test/java/util/Collections/CheckedListBash.java new file mode 100644 index 00000000000..2d7dd2a4d0d --- /dev/null +++ b/ojluni/src/test/java/util/Collections/CheckedListBash.java @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2003, 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 4904067 + * @summary Unit test for Collections.checkedList + * @author Josh Bloch + * @key randomness + */ + +package test.java.util.Collections; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Random; + +public class CheckedListBash { + static Random rnd = new Random(); + + public static void main(String[] args) { + int numItr = 100; + int listSize = 100; + + for (int i=0; i<numItr; i++) { + List s1 = newList(); + AddRandoms(s1, listSize); + + List s2 = newList(); + AddRandoms(s2, listSize); + + List intersection = clone(s1); intersection.retainAll(s2); + List diff1 = clone(s1); diff1.removeAll(s2); + List diff2 = clone(s2); diff2.removeAll(s1); + List union = clone(s1); union.addAll(s2); + + if (diff1.removeAll(diff2)) + fail("List algebra identity 2 failed"); + if (diff1.removeAll(intersection)) + fail("List algebra identity 3 failed"); + if (diff2.removeAll(diff1)) + fail("List algebra identity 4 failed"); + if (diff2.removeAll(intersection)) + fail("List algebra identity 5 failed"); + if (intersection.removeAll(diff1)) + fail("List algebra identity 6 failed"); + if (intersection.removeAll(diff1)) + fail("List algebra identity 7 failed"); + + intersection.addAll(diff1); intersection.addAll(diff2); + if (!(intersection.containsAll(union) && + union.containsAll(intersection))) + fail("List algebra identity 1 failed"); + + Iterator e = union.iterator(); + while (e.hasNext()) + intersection.remove(e.next()); + if (!intersection.isEmpty()) + fail("Copy nonempty after deleting all elements."); + + e = union.iterator(); + while (e.hasNext()) { + Object o = e.next(); + if (!union.contains(o)) + fail("List doesn't contain one of its elements."); + e.remove(); + } + if (!union.isEmpty()) + fail("List nonempty after deleting all elements."); + + s1.clear(); + if (s1.size() != 0) + fail("Clear didn't reduce size to zero."); + + s1.addAll(0, s2); + if (!(s1.equals(s2) && s2.equals(s1))) + fail("addAll(int, Collection) doesn't work."); + // Reverse List + for (int j=0, n=s1.size(); j<n; j++) + s1.set(j, s1.set(n-j-1, s1.get(j))); + // Reverse it again + for (int j=0, n=s1.size(); j<n; j++) + s1.set(j, s1.set(n-j-1, s1.get(j))); + if (!(s1.equals(s2) && s2.equals(s1))) + fail("set(int, Object) doesn't work"); + } + + List s = newList(); + for (int i=0; i<listSize; i++) + s.add(new Integer(i)); + if (s.size() != listSize) + fail("Size of [0..n-1] != n"); + + List even = clone(s); + Iterator it = even.iterator(); + while (it.hasNext()) + if (((Integer)it.next()).intValue() % 2 == 1) + it.remove(); + it = even.iterator(); + while (it.hasNext()) + if (((Integer)it.next()).intValue() % 2 == 1) + fail("Failed to remove all odd nubmers."); + + List odd = clone(s); + for (int i=0; i<(listSize/2); i++) + odd.remove(i); + for (int i=0; i<(listSize/2); i++) + if (((Integer)odd.get(i)).intValue() % 2 != 1) + fail("Failed to remove all even nubmers."); + + List all = clone(odd); + for (int i=0; i<(listSize/2); i++) + all.add(2*i, even.get(i)); + if (!all.equals(s)) + fail("Failed to reconstruct ints from odds and evens."); + + all = clone(odd); + ListIterator itAll = all.listIterator(all.size()); + ListIterator itEven = even.listIterator(even.size()); + while (itEven.hasPrevious()) { + itAll.previous(); + itAll.add(itEven.previous()); + itAll.previous(); // ??? + } + itAll = all.listIterator(); + while (itAll.hasNext()) { + Integer i = (Integer)itAll.next(); + itAll.set(new Integer(i.intValue())); + } + itAll = all.listIterator(); + it = s.iterator(); + while (it.hasNext()) + if (it.next()==itAll.next()) + fail("Iterator.set failed to change value."); + if (!all.equals(s)) + fail("Failed to reconstruct ints with ListIterator."); + + it = all.listIterator(); + int i=0; + while (it.hasNext()) { + Object o = it.next(); + if (all.indexOf(o) != all.lastIndexOf(o)) + fail("Apparent duplicate detected."); + if (all.subList(i, all.size()).indexOf(o) != 0 || + all.subList(i+1, all.size()).indexOf(o) != -1) + fail("subList/indexOf is screwy."); + if (all.subList(0,i+1).lastIndexOf(o) != i) + fail("subList/lastIndexOf is screwy."); + i++; + } + + List l = newList(); + AddRandoms(l, listSize); + Integer[] ia = (Integer[]) l.toArray(new Integer[0]); + if (!l.equals(Arrays.asList(ia))) + fail("toArray(Object[]) is hosed (1)"); + ia = new Integer[listSize]; + Integer[] ib = (Integer[]) l.toArray(ia); + if (ia != ib || !l.equals(Arrays.asList(ia))) + fail("toArray(Object[]) is hosed (2)"); + ia = new Integer[listSize+1]; + ia[listSize] = new Integer(69); + ib = (Integer[]) l.toArray(ia); + if (ia != ib || ia[listSize] != null + || !l.equals(Arrays.asList(ia).subList(0, listSize))) + fail("toArray(Object[]) is hosed (3)"); + + } + + // Done inefficiently so as to exercise toArray + static List clone(List s) { + List a = Arrays.asList(s.toArray()); + if (s.hashCode() != a.hashCode()) + fail("Incorrect hashCode computation."); + + List clone = newList(); + clone.addAll(a); + if (!s.equals(clone)) + fail("List not equal to copy."); + if (!s.containsAll(clone)) + fail("List does not contain copy."); + if (!clone.containsAll(s)) + fail("Copy does not contain list."); + + return clone; + } + + static List newList() { + List s = Collections.checkedList(new ArrayList(), Integer.class); + if (!s.isEmpty()) + fail("New instance non empty."); + return s; + } + + static void AddRandoms(List s, int n) { + for (int i = 0; i < n; i++) { + Integer e = rnd.nextInt(n); + + int preSize = s.size(); + if (!s.add(e)) + fail("Add failed."); + int postSize = s.size(); + if (postSize - preSize != 1) + fail("Add didn't increase size by 1."); + } + } + + static void fail(String s) { + throw new RuntimeException(s); + } +} diff --git a/ojluni/src/test/java/util/Collections/CheckedListReplaceAll.java b/ojluni/src/test/java/util/Collections/CheckedListReplaceAll.java new file mode 100644 index 00000000000..48ec9d88c8a --- /dev/null +++ b/ojluni/src/test/java/util/Collections/CheckedListReplaceAll.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, 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 8047795 8053938 + * @summary Ensure that replaceAll operator cannot add bad elements + * @author Mike Duigou + */ + +package test.java.util.Collections; + +import java.util.*; +import java.util.function.UnaryOperator; + +public class CheckedListReplaceAll { + public static void main(String[] args) { + List unwrapped = Arrays.asList(new Object[]{1, 2, 3}); + List<Object> wrapped = Collections.checkedList(unwrapped, Integer.class); + + UnaryOperator evil = e -> (((int) e) % 2 != 0) ? e : "evil"; + + try { + wrapped.replaceAll(evil); + System.out.printf("Bwahaha! I have defeated you! %s\n", wrapped); + throw new RuntimeException("String added to checked List<Integer>"); + } catch (ClassCastException thwarted) { + thwarted.printStackTrace(System.out); + System.out.println("Curses! Foiled again!"); + } + + unwrapped = Arrays.asList(new Object[]{}); // Empty list + wrapped = Collections.checkedList(unwrapped, Integer.class); + try { + wrapped.replaceAll((UnaryOperator)null); + System.out.printf("Bwahaha! I have defeated you! %s\n", wrapped); + throw new RuntimeException("NPE not thrown when passed a null operator"); + } catch (NullPointerException thwarted) { + thwarted.printStackTrace(System.out); + System.out.println("Curses! Foiled again!"); + } + } +} diff --git a/ojluni/src/test/java/util/Collections/CheckedMapBash.java b/ojluni/src/test/java/util/Collections/CheckedMapBash.java new file mode 100644 index 00000000000..2d4db768df0 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/CheckedMapBash.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2003, 2013, 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 4904067 5023830 7129185 8072015 + * @summary Unit test for Collections.checkedMap + * @author Josh Bloch + * @run testng CheckedMapBash + * @key randomness + */ + +package test.java.util.Collections; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.TreeMap; +import java.util.function.Supplier; + +import static org.testng.Assert.fail; + +public class CheckedMapBash { + static final Random rnd = new Random(); + static final Object nil = new Integer(0); + static final int numItr = 100; + static final int mapSize = 100; + + @Test(dataProvider = "Bash.Supplier<Map<Integer,Integer>>") + public static void testCheckedMap(String description, Supplier<Map<Integer,Integer>> supplier) { + Map m = supplier.get(); + Object head = nil; + + for (int j=0; j<mapSize; j++) { + Object newHead; + do { + newHead = new Integer(rnd.nextInt()); + } while (m.containsKey(newHead) || newHead.equals(nil)); + m.put(newHead, head); + head = newHead; + } + if (m.size() != mapSize) + fail("Size not as expected."); + + { + HashMap hm = new HashMap(m); + if (! (hm.hashCode() == m.hashCode() && + hm.entrySet().hashCode() == m.entrySet().hashCode() && + hm.keySet().hashCode() == m.keySet().hashCode())) + fail("Incorrect hashCode computation."); + + if (! (hm.equals(m) && + hm.entrySet().equals(m.entrySet()) && + hm.keySet().equals(m.keySet()) && + m.equals(hm) && + m.entrySet().equals(hm.entrySet()) && + m.keySet().equals(hm.keySet()))) + fail("Incorrect equals computation."); + } + + Map m2 = supplier.get(); m2.putAll(m); + m2.values().removeAll(m.keySet()); + if (m2.size()!= 1 || !m2.containsValue(nil)) + fail("Collection views test failed."); + + int j=0; + while (head != nil) { + if (!m.containsKey(head)) + fail("Linked list doesn't contain a link."); + Object newHead = m.get(head); + if (newHead == null) + fail("Could not retrieve a link."); + m.remove(head); + head = newHead; + j++; + } + if (!m.isEmpty()) + fail("Map nonempty after removing all links."); + if (j != mapSize) + fail("Linked list size not as expected."); + } + + @Test(dataProvider = "Supplier<Map<Integer,Integer>>") + public static void testCheckedMap2(String description, Supplier<Map<Integer,Integer>> supplier) { + Map m = supplier.get(); + for (int i=0; i<mapSize; i++) + if (m.put(new Integer(i), new Integer(2*i)) != null) + fail("put returns a non-null value erroneously."); + for (int i=0; i<2*mapSize; i++) + if (m.containsValue(new Integer(i)) != (i%2==0)) + fail("contains value "+i); + if (m.put(nil, nil) == null) + fail("put returns a null value erroneously."); + Map m2 = supplier.get(); m2.putAll(m); + if (!m.equals(m2)) + fail("Clone not equal to original. (1)"); + if (!m2.equals(m)) + fail("Clone not equal to original. (2)"); + Set s = m.entrySet(), s2 = m2.entrySet(); + if (!s.equals(s2)) + fail("Clone not equal to original. (3)"); + if (!s2.equals(s)) + fail("Clone not equal to original. (4)"); + if (!s.containsAll(s2)) + fail("Original doesn't contain clone!"); + if (!s2.containsAll(s)) + fail("Clone doesn't contain original!"); + + s2.removeAll(s); + if (!m2.isEmpty()) + fail("entrySet().removeAll failed."); + + m2.putAll(m); + m2.clear(); + if (!m2.isEmpty()) + fail("clear failed."); + + Iterator i = m.entrySet().iterator(); + while (i.hasNext()) { + i.next(); + i.remove(); + } + if (!m.isEmpty()) + fail("Iterator.remove() failed"); + } + + @DataProvider(name = "Bash.Supplier<Map<Integer,Integer>>", parallel = true) + public static Iterator<Object[]> bashNavigableMapProvider() { + ArrayList<Object[]> iters = new ArrayList<>(makeCheckedMaps()); + iters.ensureCapacity(numItr * iters.size()); + for (int each=1; each < numItr; each++) { + iters.addAll(makeCheckedMaps()); + } + return iters.iterator(); + } + + @DataProvider(name = "Supplier<Map<Integer,Integer>>", parallel = true) + public static Iterator<Object[]> navigableMapProvider() { + return makeCheckedMaps().iterator(); + } + + public static Collection<Object[]> makeCheckedMaps() { + Object[][] params = { + {"Collections.checkedMap(HashMap)", + (Supplier) () -> Collections.checkedMap(new HashMap(), Integer.class, Integer.class)}, + {"Collections.checkedMap(TreeMap(reverseOrder))", + (Supplier) () -> Collections.checkedMap(new TreeMap(Collections.reverseOrder()), Integer.class, Integer.class)}, + {"Collections.checkedMap(TreeMap.descendingMap())", + (Supplier) () -> Collections.checkedMap(new TreeMap().descendingMap(), Integer.class, Integer.class)}, + {"Collections.checkedNavigableMap(TreeMap)", + (Supplier) () -> Collections.checkedNavigableMap(new TreeMap(), Integer.class, Integer.class)}, + {"Collections.checkedNavigableMap(TreeMap(reverseOrder))", + (Supplier) () -> Collections.checkedNavigableMap(new TreeMap(Collections.reverseOrder()), Integer.class, Integer.class)}, + {"Collections.checkedNavigableMap(TreeMap.descendingMap())", + (Supplier) () -> Collections.checkedNavigableMap(new TreeMap().descendingMap(), Integer.class, Integer.class)}, + }; + return Arrays.asList(params); + } +} diff --git a/ojluni/src/test/java/util/Collections/CheckedMapReplaceAll.java b/ojluni/src/test/java/util/Collections/CheckedMapReplaceAll.java new file mode 100644 index 00000000000..b474a10057c --- /dev/null +++ b/ojluni/src/test/java/util/Collections/CheckedMapReplaceAll.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014, 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 8047795 + * @summary Ensure that replaceAll operator cannot add bad elements + * @author Mike Duigou + */ + +package test.java.util.Collections; + +import java.util.*; +import java.util.function.BiFunction; + +public class CheckedMapReplaceAll { + public static void main(String[] args) { + Map<Integer,Double> unwrapped = new HashMap<>(); + unwrapped.put(1, 1.0); + unwrapped.put(2, 2.0); + unwrapped.put(3, 3.0); + + Map<Integer,Double> wrapped = Collections.checkedMap(unwrapped, Integer.class, Double.class); + + BiFunction evil = (k, v) -> (((int)k) % 2 != 0) ? v : "evil"; + + try { + wrapped.replaceAll(evil); + System.out.printf("Bwahaha! I have defeated you! %s\n", wrapped); + throw new RuntimeException("String added to checked Map<Integer,Double>"); + } catch (ClassCastException thwarted) { + thwarted.printStackTrace(System.out); + System.out.println("Curses! Foiled again!"); + } + } +} diff --git a/ojluni/src/test/java/util/Collections/CheckedNull.java b/ojluni/src/test/java/util/Collections/CheckedNull.java new file mode 100644 index 00000000000..91b5d9f0548 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/CheckedNull.java @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2007, 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 6409434 + * @summary Test behavior of nulls in checked collections + */ + +package test.java.util.Collections; + +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.TreeSet; + +import static java.util.Collections.singleton; +import static java.util.Collections.singletonMap; + +@SuppressWarnings({"unchecked","serial"}) +public class CheckedNull { + + void test(String[] args) throws Throwable { + testCollection(Collections.checkedCollection( + new ArrayList<String>(), String.class)); + testCollection(Collections.checkedList( + new ArrayList<String>(), String.class)); + testCollection(Collections.checkedSet( + new HashSet<String>(), String.class)); + + final Comparator nullLow = new Comparator() { + public int compare(Object x, Object y) { + return x == y ? 0 : + x == null ? -1 : + y == null ? 1 : + ((Comparable)x).compareTo(y); }}; + testCollection(Collections.checkedSortedSet( + new TreeSet<String>(nullLow), String.class)); + + testMap(Collections.checkedMap( + new HashMap<String, String>(), + String.class, String.class)); + } + + ClassCastException cce(F f) { + try { f.f(); fail(); return null; } + catch (ClassCastException cce) { pass(); return cce; } + catch (Throwable t) { unexpected(t); return null; } + } + + void equalCCE(F ... fs) { + String detailMessage = null; + for (F f : fs) + if (detailMessage == null) + detailMessage = cce(f).getMessage(); + else + equal(detailMessage, cce(f).getMessage()); + } + + void add(Collection c, Object o) { + int s = c.size(); + check(! c.contains(o)); + check(c.add(o)); + check(c.contains(o)); + equal(c.size(), s+1); + check(c.remove(o)); + check(! c.contains(o)); + check(c.addAll(singleton(o))); + check(c.contains(o)); + equal(c.size(), s+1); + check(c.remove(o)); + equal(c.size(), s); + } + + void testCollection(final Collection c) { + try { + check(c.isEmpty()); + add(c, null); + add(c, "foo"); + + check(c.add("bar")); + add(c, null); + add(c, "foo"); + + equalCCE( + new F(){void f(){ c.add(1); }}, + new F(){void f(){ c.addAll(singleton(1)); }}); + + } catch (Throwable t) { unexpected(t); } + } + + void put(Map m, Object k, Object v) { + int s = m.size(); + check(! m.containsKey(k)); + check(! m.containsValue(v)); + equal(null, m.put(k, v)); + check(m.containsKey(k)); + check(m.containsValue(v)); + equal(m.size(), s+1); + equal(v, m.remove(k)); + check(! m.containsKey(k)); + check(! m.containsValue(v)); + m.putAll(singletonMap(k,v)); + check(m.containsKey(k)); + check(m.containsValue(v)); + equal(m.size(), s+1); + equal(v,m.remove(k)); + equal(m.size(), s); + } + + void testMap(final Map m) { + try { + check(m.isEmpty()); + + put(m, "foo", null); + put(m, null, "foo"); + put(m, null, null); + put(m, "foo", "bar"); + + m.put("a", "b"); + + put(m, "foo", null); + put(m, null, "foo"); + put(m, null, null); + put(m, "foo", "bar"); + + equalCCE( + new F(){void f(){ m.put(1, "foo"); }}, + new F(){void f(){ m.putAll(singletonMap(1, "foo")); }}); + + final Collection cheater = new ArrayList() { + public boolean contains(Object o) { + if (o instanceof Map.Entry) + ((Map.Entry)o).setValue(1); + return false; }}; + + equalCCE( + new F(){void f(){ m.put("foo", 1); }}, + new F(){void f(){ m.putAll(singletonMap("foo", 1)); }}, + new F(){void f(){ + ((Map.Entry)m.entrySet().iterator().next()).setValue(1); }}, + new F(){void f(){ + m.entrySet().removeAll(cheater);}}, + new F(){void f(){ + m.entrySet().retainAll(cheater);}}); + + equalCCE( + new F(){void f(){ m.put(3, 1); }}, + new F(){void f(){ m.putAll(singletonMap(3, 1)); }}); + + equal(m.size(), 1); + equal(m.keySet(), singleton("a")); + equal(m.entrySet(), + singleton(new AbstractMap.SimpleImmutableEntry("a","b"))); + + } catch (Throwable t) { unexpected(t); } + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new CheckedNull().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + abstract class F {abstract void f() throws Throwable;} +} diff --git a/ojluni/src/test/java/util/Collections/CheckedQueue.java b/ojluni/src/test/java/util/Collections/CheckedQueue.java new file mode 100644 index 00000000000..109d1170282 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/CheckedQueue.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2011, 2014, 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 5020931 8048207 + * @summary Unit test for Collections.checkedQueue + * @run testng CheckedQueue + */ + +package test.java.util.Collections; + +import java.util.Collections; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; + +import org.testng.annotations.Test; +import static org.testng.Assert.fail; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertFalse; + + +public class CheckedQueue { + + /** + * This test adds items to a queue. + */ + @Test + public void testAdd() { + int arrayLength = 10; + Queue<String> abq = Collections.checkedQueue(new ArrayBlockingQueue<>(arrayLength), String.class); + + for (int i = 0; i < arrayLength; i++) { + abq.add(Integer.toString(i)); + } + + try { + abq.add("full"); + } catch (IllegalStateException full) { + + } + } + + /** + * This test tests the CheckedQueue.add method. It creates a queue of + * {@code String}s gets the checked queue, and attempt to add an Integer to + * the checked queue. + */ + @Test(expectedExceptions = ClassCastException.class) + public void testAddFail1() { + int arrayLength = 10; + ArrayBlockingQueue<String> abq = new ArrayBlockingQueue(arrayLength + 1); + + for (int i = 0; i < arrayLength; i++) { + abq.add(Integer.toString(i)); + } + + Queue q = Collections.checkedQueue(abq, String.class); + q.add(0); + } + + /** + * This test tests the CheckedQueue.add method. It creates a queue of one + * {@code String}, gets the checked queue, and attempt to add an Integer to + * the checked queue. + */ + @Test(expectedExceptions = ClassCastException.class) + public void testAddFail2() { + ArrayBlockingQueue<String> abq = new ArrayBlockingQueue(1); + Queue q = Collections.checkedQueue(abq, String.class); + + q.add(0); + } + + /** + * This test tests the Collections.checkedQueue method call for nulls in + * each and both of the parameters. + */ + @Test + public void testArgs() { + ArrayBlockingQueue<String> abq = new ArrayBlockingQueue(1); + Queue q; + + try { + q = Collections.checkedQueue(null, String.class); + fail( "should throw NullPointerException."); + } catch(NullPointerException npe) { + // Do nothing + } + + try { + q = Collections.checkedQueue(abq, null); + fail( "should throw NullPointerException."); + } catch(Exception e) { + // Do nothing + } + + try { + q = Collections.checkedQueue(null, null); + fail( "should throw NullPointerException."); + } catch(Exception e) { + // Do nothing + } + } + + /** + * This test tests the CheckedQueue.offer method. + */ + @Test + public void testOffer() { + ArrayBlockingQueue<String> abq = new ArrayBlockingQueue(1); + Queue q = Collections.checkedQueue(abq, String.class); + + try { + q.offer(null); + fail("should throw NullPointerException."); + } catch (NullPointerException npe) { + // Do nothing + } + + try { + q.offer(0); + fail("should throw ClassCastException."); + } catch (ClassCastException cce) { + // Do nothing + } + + assertTrue(q.offer("0"), "queue should have room"); + + // no room at the inn! + assertFalse(q.offer("1"), "queue should be full"); + } +} diff --git a/ojluni/src/test/java/util/Collections/CheckedSetBash.java b/ojluni/src/test/java/util/Collections/CheckedSetBash.java new file mode 100644 index 00000000000..a120bc557d3 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/CheckedSetBash.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2003, 2013, 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 4904067 7129185 + * @summary Unit test for Collections.checkedSet + * @author Josh Bloch + * @run testng CheckedSetBash + * @key randomness + */ + +package test.java.util.Collections; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.TreeSet; +import java.util.function.Supplier; + +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +public class CheckedSetBash { + static final int numItr = 100; + static final int setSize = 100; + static final Random rnd = new Random(); + + @Test(dataProvider = "Supplier<Set<Integer>>") + public static void testCheckedSet(String description, Supplier<Set<Integer>> supplier) { + + Set<Integer> s1 = supplier.get(); + assertTrue(s1.isEmpty()); + + AddRandoms(s1, setSize); + + Set<Integer> s2 = supplier.get(); + + assertTrue(s2.isEmpty()); + + AddRandoms(s2, setSize); + + Set<Integer> intersection = clone(s1, supplier); + intersection.retainAll(s2); + Set<Integer> diff1 = clone(s1, supplier); diff1.removeAll(s2); + Set<Integer> diff2 = clone(s2, supplier); diff2.removeAll(s1); + Set<Integer> union = clone(s1, supplier); union.addAll(s2); + + if (diff1.removeAll(diff2)) + fail("Set algebra identity 2 failed"); + if (diff1.removeAll(intersection)) + fail("Set algebra identity 3 failed"); + if (diff2.removeAll(diff1)) + fail("Set algebra identity 4 failed"); + if (diff2.removeAll(intersection)) + fail("Set algebra identity 5 failed"); + if (intersection.removeAll(diff1)) + fail("Set algebra identity 6 failed"); + if (intersection.removeAll(diff1)) + fail("Set algebra identity 7 failed"); + + intersection.addAll(diff1); intersection.addAll(diff2); + if (!intersection.equals(union)) + fail("Set algebra identity 1 failed"); + + if (new HashSet(union).hashCode() != union.hashCode()) + fail("Incorrect hashCode computation."); + + Iterator e = union.iterator(); + while (e.hasNext()) + if (!intersection.remove(e.next())) + fail("Couldn't remove element from copy."); + if (!intersection.isEmpty()) + fail("Copy nonempty after deleting all elements."); + + e = union.iterator(); + while (e.hasNext()) { + Object o = e.next(); + if (!union.contains(o)) + fail("Set doesn't contain one of its elements."); + e.remove(); + if (union.contains(o)) + fail("Set contains element after deletion."); + } + if (!union.isEmpty()) + fail("Set nonempty after deleting all elements."); + + s1.clear(); + if (!s1.isEmpty()) + fail("Set nonempty after clear."); + } + + // Done inefficiently so as to exercise toArray + static <T> Set<T> clone(Set<T> s, Supplier<Set<T>> supplier) { + Set<T> clone = supplier.get(); + List<T> arrayList = Arrays.asList((T[]) s.toArray()); + clone.addAll(arrayList); + if (!s.equals(clone)) + fail("Set not equal to copy."); + if (!s.containsAll(clone)) + fail("Set does not contain copy."); + if (!clone.containsAll(s)) + fail("Copy does not contain set."); + return clone; + } + + static void AddRandoms(Set s, int n) { + for (int i = 0; i < n; i++) { + Integer e = rnd.nextInt(n); + + int preSize = s.size(); + boolean prePresent = s.contains(e); + boolean added = s.add(e); + if (!s.contains(e)) + fail("Element not present after addition."); + if (added == prePresent) + fail("added == alreadyPresent"); + int postSize = s.size(); + if (added && preSize == postSize) + fail("Add returned true, but size didn't change."); + if (!added && preSize != postSize) + fail("Add returned false, but size changed."); + } + } + + @DataProvider(name = "Supplier<Set<Integer>>", parallel = true) + public static Iterator<Object[]> navigableSetsProvider() { + ArrayList<Object[]> iters = new ArrayList<>(makeCheckedSets()); + iters.ensureCapacity(numItr * iters.size()); + for (int each=1; each < numItr; each++) { + iters.addAll(makeCheckedSets()); + } + return iters.iterator(); + } + + public static Collection<Object[]> makeCheckedSets() { + Object[][] params = { + {"Collections.checkedSet(HashSet)", + (Supplier) () -> Collections.checkedSet(new HashSet(), Integer.class)}, + {"Collections.checkedSet(TreeSet(reverseOrder))", + (Supplier) () -> Collections.checkedSet(new TreeSet(Collections.reverseOrder()), Integer.class)}, + {"Collections.checkedSet(TreeSet.descendingSet())", + (Supplier) () -> Collections.checkedSet(new TreeSet().descendingSet(), Integer.class)}, + {"Collections.checkedNavigableSet(TreeSet)", + (Supplier) () -> Collections.checkedNavigableSet(new TreeSet(), Integer.class)}, + {"Collections.checkedNavigableSet(TreeSet(reverseOrder))", + (Supplier) () -> Collections.checkedNavigableSet(new TreeSet(Collections.reverseOrder()), Integer.class)}, + {"Collections.checkedNavigableSet(TreeSet.descendingSet())", + (Supplier) () -> Collections.checkedNavigableSet(new TreeSet().descendingSet(), Integer.class)}, + }; + return Arrays.asList(params); + } +} diff --git a/ojluni/src/test/java/util/Collections/DelegatingIteratorForEachRemaining.java b/ojluni/src/test/java/util/Collections/DelegatingIteratorForEachRemaining.java new file mode 100644 index 00000000000..bf055b66d32 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/DelegatingIteratorForEachRemaining.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2018 Google Inc. 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 + * @run junit DelegatingIteratorForEachRemaining + */ + +package test.java.util.Collections; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.Spliterator; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Stream; + +public class DelegatingIteratorForEachRemaining { + + static abstract class ForwardingIterator<E> implements Iterator<E> { + private final Iterator<E> delegate; + + protected ForwardingIterator(Iterator<E> delegate) { + this.delegate = Objects.requireNonNull(delegate); + } + + @Override public boolean hasNext() { return delegate.hasNext(); } + @Override public E next() { return delegate.next(); } + @Override public void remove() { delegate.remove(); } + @Override public void forEachRemaining(Consumer<? super E> action) { + delegate.forEachRemaining(action); + } + } + + static final class ThrowingIterator<E> extends ForwardingIterator<E> { + public ThrowingIterator(Iterator<E> delegate) { + super(delegate); + } + + @Override + public void forEachRemaining(Consumer<? super E> action) { + throw new UnsupportedOperationException(); + } + } + + static abstract class ForwardingSet<E> implements Set<E> { + private final Set<E> delegate; + + protected ForwardingSet(Set<E> delegate) { + this.delegate = Objects.requireNonNull(delegate); + } + + @Override public int size() { return delegate.size(); } + @Override public boolean isEmpty() { return delegate.isEmpty(); } + @Override public boolean contains(Object o) { return delegate.contains(o); } + @Override public Iterator<E> iterator() { return delegate.iterator(); } + @Override public Object[] toArray() { return delegate.toArray(); } + @Override public <T> T[] toArray( T[] ts) { return delegate.toArray(ts); } + @Override public boolean add(E e) { return delegate.add(e); } + @Override public boolean remove(Object o) { return delegate.remove(o); } + @Override public boolean containsAll( Collection<?> c) { return delegate.containsAll(c); } + @Override public boolean addAll( Collection<? extends E> c) { return delegate.addAll(c); } + @Override public boolean retainAll( Collection<?> c) { return delegate.retainAll(c); } + @Override public boolean removeAll( Collection<?> c) { return delegate.removeAll(c); } + @Override public void clear() { delegate.clear(); } + @Override public boolean equals(Object o) { return delegate.equals(o); } + @Override public int hashCode() { return delegate.hashCode(); } + @Override public Spliterator<E> spliterator() { return delegate.spliterator(); } + @Override public boolean removeIf(Predicate<? super E> filter) { return delegate.removeIf(filter); } + @Override public Stream<E> stream() { return delegate.stream(); } + @Override public Stream<E> parallelStream() { return delegate.parallelStream(); } + @Override public void forEach(Consumer<? super E> action) { delegate.forEach(action); } + } + + static class ThrowingSet<E> extends ForwardingSet<E> { + public ThrowingSet(Set<E> delegate) { + super(delegate); + } + + @Override + public ThrowingIterator<E> iterator() { + return new ThrowingIterator<>(super.iterator()); + } + } + + static abstract class ForwardingMap<K, V> implements Map<K, V> { + private final Map<K, V> delegate; + + public ForwardingMap(Map<K, V> delegate) { + this.delegate = delegate; + } + + @Override public int size() { return delegate.size(); } + @Override public boolean isEmpty() { return delegate.isEmpty(); } + @Override public boolean containsKey(Object o) { return delegate.containsKey(o); } + @Override public boolean containsValue(Object o) { return delegate.containsValue(o); } + @Override public V get(Object o) { return delegate.get(o); } + @Override public V put(K k, V v) { return delegate.put(k, v); } + @Override public V remove(Object o) { return delegate.remove(o); } + @Override public void putAll(Map<? extends K, ? extends V> map) { delegate.putAll(map); } + @Override public void clear() { delegate.clear(); } + @Override public Set<K> keySet() { return delegate.keySet(); } + @Override public Collection<V> values() { return delegate.values(); } + @Override public Set<Entry<K, V>> entrySet() { return delegate.entrySet(); } + @Override public boolean equals(Object o) { return delegate.equals(o); } + @Override public int hashCode() { return delegate.hashCode(); } + @Override public V getOrDefault(Object key, V defaultValue) { return delegate.getOrDefault(key, defaultValue); } + @Override public void forEach(BiConsumer<? super K, ? super V> action) { delegate.forEach(action); } + @Override public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { delegate.replaceAll(function); } + @Override public V putIfAbsent(K key, V value) { return delegate.putIfAbsent(key, value); } + @Override public boolean remove(Object key, Object value) { return delegate.remove(key, value); } + @Override public boolean replace(K key, V oldValue, V newValue) { return delegate.replace(key, oldValue, newValue); } + @Override public V replace(K key, V value) { return delegate.replace(key, value); } + @Override public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { return delegate.computeIfAbsent(key, mappingFunction); } + @Override public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { return delegate.computeIfPresent(key, remappingFunction); } + @Override public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { return delegate.compute(key, remappingFunction); } + @Override public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) { return delegate.merge(key, value, remappingFunction); } + } + + static class ThrowingMap<K, V> extends ForwardingMap<K, V> { + public ThrowingMap(Map<K, V> delegate) { + super(delegate); + } + + @Override + public ThrowingSet<Entry<K, V>> entrySet() { + return new ThrowingSet<>(super.entrySet()); + } + + @Override + public Set<K> keySet() { + return new ThrowingSet(super.keySet()); + } + } + + static<E> void assertThrowingIterator(Iterator<E> iterator) { + try { + iterator.forEachRemaining((entry) -> {}); + Assert.fail(); + } catch (UnsupportedOperationException expected) { + } + } + + private static Map<String, Object> map() { + Map<String, Object> map = new HashMap<>(); + map.put("name", "Bill"); + map.put("age", 23); + return new ThrowingMap<>(map); + } + + @Test public void testUnwrapped() { + assertThrowingIterator(map().entrySet().iterator()); + assertThrowingIterator(map().keySet().iterator()); + } + + @Test public void test_unmodifiableMap_entrySet() { + assertThrowingIterator(Collections.unmodifiableMap(map()).entrySet().iterator()); + } + + @Test public void test_checkedMap_entrySet() { + assertThrowingIterator(Collections.checkedMap(map(), String.class, Object.class).entrySet().iterator()); + } + + @Test public void test_entrySet_checkedSet() { + Set<Map.Entry<String, Object>> entrySet = map().entrySet(); + Class clazz = entrySet.iterator().next().getClass(); + assertThrowingIterator(Collections.checkedSet(entrySet, clazz).iterator()); + } +} diff --git a/ojluni/src/test/java/util/Collections/Disjoint.java b/ojluni/src/test/java/util/Collections/Disjoint.java new file mode 100644 index 00000000000..748629c94b9 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/Disjoint.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2003, 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 4339792 + * @summary Basic test for Collections.disjoint + * @author Josh Bloch + * @key randomness + */ + +package test.java.util.Collections; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Random; + +public class Disjoint { + static final int N = 20; + + public static void main(String[] args) { + // Make an array of lists each of which shares a single element + // with its "neighbors," and no elements with other lists in the array + Random rnd = new Random(); + List[] lists = new List[N]; + int x = 0; + for (int i = 0; i < N; i++) { + int size = rnd.nextInt(10) + 2; + List<Integer> list = new ArrayList<>(size); + for (int j = 1; j < size; j++) + list.add(x++); + list.add(x); + Collections.shuffle(list); + + lists[i] = list; + } + + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + boolean disjoint = (Math.abs(i - j) > 1); + List<Integer> a = (List<Integer>) lists[i]; + List<Integer> b = (List<Integer>) lists[j]; + + if (Collections.disjoint(a, b) != disjoint) + throw new RuntimeException("A: " + i + ", " + j); + if (Collections.disjoint(new HashSet<Integer>(a), b) + != disjoint) + throw new RuntimeException("B: " + i + ", " + j); + if (Collections.disjoint(new HashSet<Integer>(a), + new HashSet<Integer>(b)) != disjoint) + throw new RuntimeException("C: " + i + ", " + j); + } + } + } +} diff --git a/ojluni/src/test/java/util/Collections/EmptyCollectionSerialization.java b/ojluni/src/test/java/util/Collections/EmptyCollectionSerialization.java new file mode 100644 index 00000000000..466c35e29bb --- /dev/null +++ b/ojluni/src/test/java/util/Collections/EmptyCollectionSerialization.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2002, 2013, 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 4684279 7129185 + * @summary Empty utility collections should be singletons + * @author Josh Bloch + * @run testng EmptyCollectionSerialization + */ + +package test.java.util.Collections; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.function.Supplier; + +import static org.testng.Assert.assertSame; +import static org.testng.Assert.fail; + +public class EmptyCollectionSerialization { + private static Object patheticDeepCopy(Object o) throws Exception { + // Serialize + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(o); + byte[] serializedForm = bos.toByteArray(); + + // Deserialize + InputStream is = new ByteArrayInputStream(serializedForm); + ObjectInputStream ois = new ObjectInputStream(is); + return ois.readObject(); + } + + @Test(dataProvider="SerializableSingletons") + public static void serializableSingletons(String description, Supplier<Object> o) { + try { + Object singleton = o.get(); + assertSame(o.get(), singleton, description + ": broken Supplier not returning singleton"); + Object copy = patheticDeepCopy(singleton); + assertSame(copy, singleton, description + ": " + + copy.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(copy)) + + " is not the singleton " + + singleton.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(singleton))); + } catch (Exception all) { + fail(description + ": Unexpected Exception", all); + } + } + + @DataProvider(name = "SerializableSingletons", parallel = true) + public static Iterator<Object[]> navigableMapProvider() { + return makeSingletons().iterator(); + } + + public static Collection<Object[]> makeSingletons() { + Object[][] params = { + {"Collections.EMPTY_LIST", + (Supplier) () -> Collections.EMPTY_LIST}, + {"Collections.EMPTY_MAP", + (Supplier) () -> Collections.EMPTY_MAP}, + {"Collections.EMPTY_SET", + (Supplier) () -> Collections.EMPTY_SET}, + {"Collections.emptyList()", + (Supplier) () -> Collections.emptyList()}, + {"Collections.emptyMap()", + (Supplier) () -> Collections.emptyMap()}, + {"Collections.emptySet()", + (Supplier) () -> Collections.emptySet()}, + {"Collections.emptySortedSet()", + (Supplier) () -> Collections.emptySortedSet()}, + {"Collections.emptySortedMap()", + (Supplier) () -> Collections.emptySortedMap()}, + {"Collections.emptyNavigableSet()", + (Supplier) () -> Collections.emptyNavigableSet()}, + {"Collections.emptyNavigableMap()", + (Supplier) () -> Collections.emptyNavigableMap()}, + }; + return Arrays.asList(params); + } +} diff --git a/ojluni/src/test/java/util/Collections/EmptyIterator.java b/ojluni/src/test/java/util/Collections/EmptyIterator.java new file mode 100644 index 00000000000..a311d8553dd --- /dev/null +++ b/ojluni/src/test/java/util/Collections/EmptyIterator.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2007, 2014, 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 5017904 6356890 8004928 + * @summary Test empty iterators, enumerations, and collections + */ + +package test.java.util.Collections; + +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.concurrent.SynchronousQueue; + +import static java.util.Collections.emptyEnumeration; +import static java.util.Collections.emptyIterator; +import static java.util.Collections.emptyList; +import static java.util.Collections.emptyListIterator; +import static java.util.Collections.emptyMap; +import static java.util.Collections.emptySet; +import static java.util.Collections.nCopies; +import static java.util.Collections.unmodifiableMap; + +public class EmptyIterator { + + void test(String[] args) throws Throwable { + testEmptyCollection(emptyList()); + testEmptyCollection(emptySet()); + testEmptyCollection(new SynchronousQueue<Object>()); + testEmptyMap(emptyMap()); + + Hashtable<?,?> emptyTable = new Hashtable<>(); + testEmptyEnumeration(emptyTable.keys()); + testEmptyEnumeration(emptyTable.elements()); + testEmptyIterator(emptyTable.keySet().iterator()); + testEmptyIterator(emptyTable.values().iterator()); + testEmptyIterator(emptyTable.entrySet().iterator()); + + final Enumeration<EmptyIterator> finalEmptyTyped = emptyEnumeration(); + testEmptyEnumeration(finalEmptyTyped); + + final Enumeration<?> finalEmptyAbstract = emptyEnumeration(); + testEmptyEnumeration(finalEmptyAbstract); + + testEmptyIterator(emptyIterator()); + } + + void testEmptyEnumeration(final Enumeration<?> e) { + check(e == emptyEnumeration()); + check(!e.hasMoreElements()); + THROWS(NoSuchElementException.class, + new F(){void f(){ e.nextElement(); }}); + } + + void testEmptyIterator(final Iterator<?> it) { + check(it == emptyIterator()); + check(! it.hasNext()); + THROWS(NoSuchElementException.class, + new F(){void f(){ it.next(); }}); + THROWS(IllegalStateException.class, + new F(){void f(){ it.remove(); }}); + } + + void testEmptyMap(Map<?,?> m) { + check(m == emptyMap()); + check(m.entrySet().iterator() == + Collections.<Map.Entry<?,?>>emptyIterator()); + check(m.values().iterator() == emptyIterator()); + check(m.keySet().iterator() == emptyIterator()); + equal(m, unmodifiableMap(m)); + + testEmptyCollection(m.keySet()); + testEmptyCollection(m.entrySet()); + testEmptyCollection(m.values()); + } + + void testToArray(final Collection<?> c) { + Object[] a = c.toArray(); + equal(a.length, 0); + equal(a.getClass().getComponentType(), Object.class); + THROWS(NullPointerException.class, + new F(){void f(){ c.toArray((Object[])null); }}); + + { + String[] t = new String[0]; + check(c.toArray(t) == t); + } + + { + String[] t = nCopies(10, "").toArray(new String[0]); + check(c.toArray(t) == t); + check(t[0] == null); + for (int i=1; i<t.length; i++) + check(t[i] == ""); + } + } + + void testEmptyCollection(final Collection<?> c) { + testEmptyIterator(c.iterator()); + + check(c.iterator() == emptyIterator()); + if (c instanceof List) + check(((List<?>)c).listIterator() == emptyListIterator()); + + testToArray(c); + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new EmptyIterator().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + abstract class F {abstract void f() throws Throwable;} + void THROWS(Class<? extends Throwable> k, F... fs) { + for (F f : fs) + try {f.f(); fail("Expected " + k.getName() + " not thrown");} + catch (Throwable t) { + if (k.isAssignableFrom(t.getClass())) pass(); + else unexpected(t);}} +} diff --git a/ojluni/src/test/java/util/Collections/EmptyNavigableMap.java b/ojluni/src/test/java/util/Collections/EmptyNavigableMap.java new file mode 100644 index 00000000000..40f6c5d5dd9 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/EmptyNavigableMap.java @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2011, 2017, 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 4533691 7129185 + * @summary Unit test for Collections.emptyNavigableMap + * @run testng EmptyNavigableMap + */ + +package test.java.util.Collections; + +import org.testng.Assert; +import org.testng.Assert.ThrowingRunnable; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableMap; +import java.util.SortedMap; +import java.util.TreeMap; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +public class EmptyNavigableMap { + + public static <T> void assertInstance(T actual, Class<? extends T> expected) { + assertInstance(actual, expected, null); + } + + public static <T> void assertInstance(T actual, Class<? extends T> expected, String message) { + assertTrue(expected.isInstance(actual), ((null != message) ? message : "") + + " " + (actual == null ? "<null>" : actual.getClass().getSimpleName()) + " != " + expected.getSimpleName() + ". "); + } + + public static <T extends Throwable> void assertEmptyNavigableMap(Object obj) { + assertInstance(obj, NavigableMap.class); + assertTrue(((NavigableMap)obj).isEmpty() && (((NavigableMap)obj).size() == 0)); + } + + public static <T extends Throwable> void assertEmptyNavigableMap(Object obj, String message) { + assertInstance(obj, NavigableMap.class, message); + assertTrue(((NavigableMap)obj).isEmpty() && (((NavigableMap)obj).size() == 0), + ((null != message) ? message : "") + " Not empty. "); + } + + private <T extends Throwable> void assertThrows(Class<T> throwableClass, + ThrowingRunnable runnable, + String message) { + try { + Assert.assertThrows(throwableClass, runnable); + } catch (AssertionError e) { + throw new AssertionError(String.format("%s%n%s", + ((null != message) ? message : ""), e.getMessage()), e); + } + } + + private void assertThrowsCCE(ThrowingRunnable r, String s) { + assertThrows(ClassCastException.class, r, s); + } + + private void assertThrowsNPE(ThrowingRunnable r, String s) { + assertThrows(NullPointerException.class, r, s); + } + + private void assertThrowsIAE(ThrowingRunnable r, String s) { + assertThrows(IllegalArgumentException.class, r, s); + } + + public static final boolean isDescending(SortedMap<?,?> set) { + if (null == set.comparator()) { + // natural order + return false; + } + + if (Collections.reverseOrder() == set.comparator()) { + // reverse natural order. + return true; + } + + if (set.comparator().equals(Collections.reverseOrder(Collections.reverseOrder(set.comparator())))) { + // it's a Collections.reverseOrder(Comparator). + return true; + } + + throw new IllegalStateException("can't determine ordering for " + set); + } + + /** + * Tests that the comparator is {@code null}. + */ + @Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class) + public void testComparatorIsNull(String description, NavigableMap<?,?> navigableMap) { + Comparator comparator = navigableMap.comparator(); + + assertTrue(comparator == null || comparator == Collections.reverseOrder(), description + ": Comparator (" + comparator + ") is not null."); + } + + /** + * Tests that contains requires Comparable + */ + @Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class) + public void testContainsRequiresComparable(String description, NavigableMap<?,?> navigableMap) { + assertThrowsCCE( + () -> navigableMap.containsKey(new Object()), + description + ": Comparable should be required"); + } + + /** + * Tests that the contains method returns {@code false}. + */ + @Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class) + public void testContains(String description, NavigableMap<?,?> navigableMap) { + assertFalse(navigableMap.containsKey(new Integer(1)), + description + ": Should not contain any elements."); + assertFalse(navigableMap.containsValue(new Integer(1)), + description + ": Should not contain any elements."); + } + + /** + * Tests that the containsAll method returns {@code false}. + */ + @Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class) + public void testContainsAll(String description, NavigableMap<?,?> navigableMap) { + TreeMap treeMap = new TreeMap(); + treeMap.put("1", 1); + treeMap.put("2", 2); + treeMap.put("3", 3); + + assertFalse(navigableMap.equals(treeMap), "Should not contain any elements."); + } + + /** + * Tests that the iterator is empty. + */ + @Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class) + public void testEmptyIterator(String description, NavigableMap<?,?> navigableMap) { + assertFalse(navigableMap.keySet().iterator().hasNext(), "The iterator is not empty."); + assertFalse(navigableMap.values().iterator().hasNext(), "The iterator is not empty."); + assertFalse(navigableMap.entrySet().iterator().hasNext(), "The iterator is not empty."); + } + + /** + * Tests that the set is empty. + */ + @Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class) + public void testIsEmpty(String description, NavigableMap<?,?> navigableMap) { + assertTrue(navigableMap.isEmpty(), "The set is not empty."); + } + + /** + * Tests the headMap() method. + */ + @Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class) + public void testHeadMap(String description, NavigableMap navigableMap) { + assertThrowsNPE( + () -> { NavigableMap ss = navigableMap.headMap(null, false); }, + description + ": Must throw NullPointerException for null element"); + + assertThrowsCCE( + () -> { NavigableMap ss = navigableMap.headMap(new Object(), true); }, + description + ": Must throw ClassCastException for non-Comparable element"); + + NavigableMap ss = navigableMap.headMap("1", false); + + assertEmptyNavigableMap(ss, description + ": Returned value is not empty navigable set."); + } + + /** + * Tests that the size is 0. + */ + @Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class) + public void testSizeIsZero(String description, NavigableMap<?,?> navigableMap) { + assertTrue(0 == navigableMap.size(), "The size of the set is not 0."); + } + + /** + * Tests the subMap() method. + */ + @Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class) + public void testSubMap(String description, NavigableMap navigableMap) { + assertThrowsNPE( + () -> { + SortedMap ss = navigableMap.subMap(null, BigInteger.TEN); + }, + description + ": Must throw NullPointerException for null element"); + + assertThrowsNPE( + () -> { + SortedMap ss = navigableMap.subMap(BigInteger.ZERO, null); + }, + description + ": Must throw NullPointerException for null element"); + + assertThrowsNPE( + () -> { + SortedMap ss = navigableMap.subMap(null, null); + }, + description + ": Must throw NullPointerException for null element"); + + Object obj1 = new Object(); + Object obj2 = new Object(); + + assertThrowsCCE( + () -> { + SortedMap ss = navigableMap.subMap(obj1, BigInteger.TEN); + }, + description + ": Must throw ClassCastException for parameter which is not Comparable."); + + assertThrowsCCE( + () -> { + SortedMap ss = navigableMap.subMap(BigInteger.ZERO, obj2); + }, + description + ": Must throw ClassCastException for parameter which is not Comparable."); + + assertThrowsCCE( + () -> { + SortedMap ss = navigableMap.subMap(obj1, obj2); + }, + description + ": Must throw ClassCastException for parameter which is not Comparable."); + + // minimal range + navigableMap.subMap(BigInteger.ZERO, false, BigInteger.ZERO, false); + navigableMap.subMap(BigInteger.ZERO, false, BigInteger.ZERO, true); + navigableMap.subMap(BigInteger.ZERO, true, BigInteger.ZERO, false); + navigableMap.subMap(BigInteger.ZERO, true, BigInteger.ZERO, true); + + Object first = isDescending(navigableMap) ? BigInteger.TEN : BigInteger.ZERO; + Object last = (BigInteger.ZERO == first) ? BigInteger.TEN : BigInteger.ZERO; + + assertThrowsIAE( + () -> navigableMap.subMap(last, true, first, false), + description + ": Must throw IllegalArgumentException when fromElement is not less than toElement."); + + navigableMap.subMap(first, true, last, false); + } + + @Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class) + public void testSubMapRanges(String description, NavigableMap navigableMap) { + Object first = isDescending(navigableMap) ? BigInteger.TEN : BigInteger.ZERO; + Object last = (BigInteger.ZERO == first) ? BigInteger.TEN : BigInteger.ZERO; + + NavigableMap subMap = navigableMap.subMap(first, true, last, true); + + // same subset + subMap.subMap(first, true, last, true); + + // slightly smaller + NavigableMap ns = subMap.subMap(first, false, last, false); + // slight expansion + assertThrowsIAE( + () -> ns.subMap(first, true, last, true), + description + ": Expansion should not be allowed"); + + // much smaller + subMap.subMap(first, false, BigInteger.ONE, false); + } + + @Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class) + public void testheadMapRanges(String description, NavigableMap navigableMap) { + NavigableMap subMap = navigableMap.headMap(BigInteger.ONE, true); + + // same subset + subMap.headMap(BigInteger.ONE, true); + + // slightly smaller + NavigableMap ns = subMap.headMap(BigInteger.ONE, false); + + // slight expansion + assertThrowsIAE( + () -> ns.headMap(BigInteger.ONE, true), + description + ": Expansion should not be allowed"); + + // much smaller + subMap.headMap(isDescending(subMap) ? BigInteger.TEN : BigInteger.ZERO, true); + } + + @Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class) + public void testTailMapRanges(String description, NavigableMap navigableMap) { + NavigableMap subMap = navigableMap.tailMap(BigInteger.ONE, true); + + // same subset + subMap.tailMap(BigInteger.ONE, true); + + // slightly smaller + NavigableMap ns = subMap.tailMap(BigInteger.ONE, false); + + // slight expansion + assertThrowsIAE( + () -> ns.tailMap(BigInteger.ONE, true), + description + ": Expansion should not be allowed"); + + // much smaller + subMap.tailMap(isDescending(subMap) ? BigInteger.ZERO : BigInteger.TEN, false); + } + + /** + * Tests the tailMap() method. + */ + @Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class) + public void testTailMap(String description, NavigableMap navigableMap) { + assertThrowsNPE( + () -> navigableMap.tailMap(null), + description + ": Must throw NullPointerException for null element"); + + assertThrowsCCE( + () -> navigableMap.tailMap(new Object()), + description); + + NavigableMap ss = navigableMap.tailMap("1", true); + + assertEmptyNavigableMap(ss, description + ": Returned value is not empty navigable set."); + } + + @DataProvider(name = "NavigableMap<?,?>", parallel = true) + public static Iterator<Object[]> navigableMapsProvider() { + return makeNavigableMaps().iterator(); + } + + public static Collection<Object[]> makeNavigableMaps() { + return Arrays.asList( + new Object[]{"UnmodifiableNavigableMap(TreeMap)", Collections.unmodifiableNavigableMap(new TreeMap())}, + new Object[]{"UnmodifiableNavigableMap(TreeMap.descendingMap()", Collections.unmodifiableNavigableMap(new TreeMap().descendingMap())}, + new Object[]{"UnmodifiableNavigableMap(TreeMap.descendingMap().descendingMap()", Collections.unmodifiableNavigableMap(new TreeMap().descendingMap().descendingMap())}, + new Object[]{"emptyNavigableMap()", Collections.emptyNavigableMap()}, + new Object[]{"emptyNavigableMap().descendingMap()", Collections.emptyNavigableMap().descendingMap()}, + new Object[]{"emptyNavigableMap().descendingMap().descendingMap()", Collections.emptyNavigableMap().descendingMap().descendingMap()} + ); + } +} diff --git a/ojluni/src/test/java/util/Collections/EmptyNavigableSet.java b/ojluni/src/test/java/util/Collections/EmptyNavigableSet.java new file mode 100644 index 00000000000..19a9bba2035 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/EmptyNavigableSet.java @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2011, 2017, 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 4533691 7129185 + * @summary Unit test for Collections.emptyNavigableSet + * @run testng EmptyNavigableSet + */ + +package test.java.util.Collections; + +import org.testng.Assert; +import org.testng.Assert.ThrowingRunnable; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.SortedSet; +import java.util.TreeSet; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertTrue; + +public class EmptyNavigableSet { + + public static <T> void assertInstance(T actual, Class<? extends T> expected) { + assertInstance(actual, expected, null); + } + + public static <T> void assertInstance(T actual, Class<? extends T> expected, String message) { + assertTrue(expected.isInstance(actual), ((null != message) ? message : "") + + " " + (actual == null ? "<null>" : actual.getClass().getSimpleName()) + " != " + expected.getSimpleName() + ". "); + } + + public static <T extends Throwable> void assertEmptyNavigableSet(Object obj) { + assertInstance(obj, NavigableSet.class); + assertTrue(((NavigableSet)obj).isEmpty() && (((NavigableSet)obj).size() == 0)); + } + + public static <T extends Throwable> void assertEmptyNavigableSet(Object obj, String message) { + assertInstance(obj, NavigableSet.class, message); + assertTrue(((NavigableSet)obj).isEmpty() && (((NavigableSet)obj).size() == 0), + ((null != message) ? message : "") + " Not empty. "); + } + + private <T extends Throwable> void assertThrows(Class<T> throwableClass, + ThrowingRunnable runnable, + String message) { + try { + Assert.assertThrows(throwableClass, runnable); + } catch (AssertionError e) { + throw new AssertionError(String.format("%s%n%s", + ((null != message) ? message : ""), e.getMessage()), e); + } + } + + private void assertThrowsCCE(ThrowingRunnable r, String s) { + assertThrows(ClassCastException.class, r, s); + } + + private void assertThrowsNPE(ThrowingRunnable r, String s) { + assertThrows(NullPointerException.class, r, s); + } + + private void assertThrowsIAE(ThrowingRunnable r, String s) { + assertThrows(IllegalArgumentException.class, r, s); + } + + private void assertThrowsNSEE(ThrowingRunnable r, String s) { + assertThrows(NoSuchElementException.class, r, s); + } + + public static final boolean isDescending(SortedSet<?> set) { + if (null == set.comparator()) { + // natural order + return false; + } + + if (Collections.reverseOrder() == set.comparator()) { + // reverse natural order. + return true; + } + + if (set.comparator().equals(Collections.reverseOrder(Collections.reverseOrder(set.comparator())))) { + // it's a Collections.reverseOrder(Comparator). + return true; + } + + throw new IllegalStateException("can't determine ordering for " + set); + } + + /** + * Tests that the comparator is {@code null}. + */ + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testComparatorIsNull(String description, NavigableSet<?> navigableSet) { + Comparator comparator = navigableSet.comparator(); + + assertTrue(comparator == null || comparator == Collections.reverseOrder(), description + ": Comparator (" + comparator + ") is not null."); + } + + /** + * Tests that contains requires Comparable + */ + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testContainsRequiresComparable(String description, NavigableSet<?> navigableSet) { + assertThrowsCCE( + () -> navigableSet.contains(new Object()), + description + ": Comparable should be required"); + } + + /** + * Tests that the contains method returns {@code false}. + */ + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testContains(String description, NavigableSet<?> navigableSet) { + assertFalse(navigableSet.contains(new Integer(1)), + description + ": Should not contain any elements."); + } + + /** + * Tests that the containsAll method returns {@code false}. + */ + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testContainsAll(String description, NavigableSet<?> navigableSet) { + TreeSet treeSet = new TreeSet(); + treeSet.add("1"); + treeSet.add("2"); + treeSet.add("3"); + + assertFalse(navigableSet.containsAll(treeSet), "Should not contain any elements."); + } + + /** + * Tests that the iterator is empty. + */ + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testEmptyIterator(String description, NavigableSet<?> navigableSet) { + assertFalse(navigableSet.iterator().hasNext(), "The iterator is not empty."); + } + + /** + * Tests that the set is empty. + */ + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testIsEmpty(String description, NavigableSet<?> navigableSet) { + assertTrue(navigableSet.isEmpty(), "The set is not empty."); + } + + /** + * Tests that the first() method throws NoSuchElementException + */ + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testFirst(String description, NavigableSet<?> navigableSet) { + assertThrowsNSEE(navigableSet::first, description); + } + + /** + * Tests the headSet() method. + */ + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testHeadSet(String description, NavigableSet navigableSet) { + assertThrowsNPE( + () -> { NavigableSet ns = navigableSet.headSet(null, false); }, + description + ": Must throw NullPointerException for null element"); + + assertThrowsCCE( + () -> { NavigableSet ns = navigableSet.headSet(new Object(), true); }, + description + ": Must throw ClassCastException for non-Comparable element"); + + NavigableSet ns = navigableSet.headSet("1", false); + + assertEmptyNavigableSet(ns, description + ": Returned value is not empty navigable set."); + } + + /** + * Tests that the last() method throws NoSuchElementException + */ + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testLast(String description, NavigableSet<?> navigableSet) { + assertThrowsNSEE(navigableSet::last, description); + } + + /** + * Tests that the size is 0. + */ + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testSizeIsZero(String description, NavigableSet<?> navigableSet) { + assertTrue(0 == navigableSet.size(), "The size of the set is not 0."); + } + + /** + * Tests the subSet() method. + */ + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testSubSet(String description, NavigableSet navigableSet) { + assertThrowsNPE( + () -> { + SortedSet ss = navigableSet.subSet(null, BigInteger.TEN); + }, + description + ": Must throw NullPointerException for null element"); + + assertThrowsNPE( + () -> { + SortedSet ss = navigableSet.subSet(BigInteger.ZERO, null); + }, + description + ": Must throw NullPointerException for null element"); + + assertThrowsNPE( + () -> { + SortedSet ss = navigableSet.subSet(null, null); + }, + description + ": Must throw NullPointerException for null element"); + + Object obj1 = new Object(); + Object obj2 = new Object(); + + assertThrowsCCE( + () -> { + SortedSet ss = navigableSet.subSet(obj1, BigInteger.TEN); + }, + description + ": Must throw ClassCastException for parameter which is not Comparable."); + + assertThrowsCCE( + () -> { + SortedSet ss = navigableSet.subSet(BigInteger.ZERO, obj2); + }, + description + ": Must throw ClassCastException for parameter which is not Comparable."); + + assertThrowsCCE( + () -> { + SortedSet ss = navigableSet.subSet(obj1, obj2); + }, + description + ": Must throw ClassCastException for parameter which is not Comparable."); + + // minimal range + navigableSet.subSet(BigInteger.ZERO, false, BigInteger.ZERO, false); + navigableSet.subSet(BigInteger.ZERO, false, BigInteger.ZERO, true); + navigableSet.subSet(BigInteger.ZERO, true, BigInteger.ZERO, false); + navigableSet.subSet(BigInteger.ZERO, true, BigInteger.ZERO, true); + + Object first = isDescending(navigableSet) ? BigInteger.TEN : BigInteger.ZERO; + Object last = (BigInteger.ZERO == first) ? BigInteger.TEN : BigInteger.ZERO; + + assertThrowsIAE( + () -> navigableSet.subSet(last, true, first, false), + description + + ": Must throw IllegalArgumentException when fromElement is not less than toElement."); + + navigableSet.subSet(first, true, last, false); + } + + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testSubSetRanges(String description, NavigableSet navigableSet) { + Object first = isDescending(navigableSet) ? BigInteger.TEN : BigInteger.ZERO; + Object last = (BigInteger.ZERO == first) ? BigInteger.TEN : BigInteger.ZERO; + + NavigableSet subSet = navigableSet.subSet(first, true, last, true); + + // same subset + subSet.subSet(first, true, last, true); + + // slightly smaller + NavigableSet ns = subSet.subSet(first, false, last, false); + // slight expansion + assertThrowsIAE( + () -> ns.subSet(first, true, last, true), + description + ": Expansion should not be allowed"); + + // much smaller + subSet.subSet(first, false, BigInteger.ONE, false); + } + + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testheadSetRanges(String description, NavigableSet navigableSet) { + NavigableSet subSet = navigableSet.headSet(BigInteger.ONE, true); + + // same subset + subSet.headSet(BigInteger.ONE, true); + + // slightly smaller + NavigableSet ns = subSet.headSet(BigInteger.ONE, false); + + // slight expansion + assertThrowsIAE( + () -> ns.headSet(BigInteger.ONE, true), + description + ": Expansion should not be allowed"); + + // much smaller + subSet.headSet(isDescending(subSet) ? BigInteger.TEN : BigInteger.ZERO, true); + } + + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testTailSetRanges(String description, NavigableSet navigableSet) { + NavigableSet subSet = navigableSet.tailSet(BigInteger.ONE, true); + + // same subset + subSet.tailSet(BigInteger.ONE, true); + + // slightly smaller + NavigableSet ns = subSet.tailSet(BigInteger.ONE, false); + + // slight expansion + assertThrowsIAE( + () -> ns.tailSet(BigInteger.ONE, true), + description + ": Expansion should not be allowed"); + + // much smaller + subSet.tailSet(isDescending(subSet) ? BigInteger.ZERO : BigInteger.TEN, false); + } + + /** + * Tests the tailSet() method. + */ + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testTailSet(String description, NavigableSet navigableSet) { + assertThrowsNPE( + () -> navigableSet.tailSet(null), + description + ": Must throw NullPointerException for null element"); + + assertThrowsCCE( + () -> navigableSet.tailSet(new Object()), + description); + + NavigableSet ss = navigableSet.tailSet("1", true); + + assertEmptyNavigableSet(ss, description + ": Returned value is not empty navigable set."); + } + + /** + * Tests that the array has a size of 0. + */ + @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class) + public void testToArray(String description, NavigableSet<?> navigableSet) { + Object[] emptyNavigableSetArray = navigableSet.toArray(); + + assertTrue(emptyNavigableSetArray.length == 0, "Returned non-empty Array."); + + emptyNavigableSetArray = new Object[20]; + + Object[] result = navigableSet.toArray(emptyNavigableSetArray); + + assertSame(emptyNavigableSetArray, result); + + assertNull(result[0]); + } + + @DataProvider(name = "NavigableSet<?>", parallel = true) + public static Iterator<Object[]> navigableSetsProvider() { + return makeNavigableSets().iterator(); + } + + public static Collection<Object[]> makeNavigableSets() { + return Arrays.asList( + new Object[]{"UnmodifiableNavigableSet(TreeSet)", Collections.unmodifiableNavigableSet(new TreeSet())}, + new Object[]{"UnmodifiableNavigableSet(TreeSet.descendingSet()", Collections.unmodifiableNavigableSet(new TreeSet().descendingSet())}, + new Object[]{"UnmodifiableNavigableSet(TreeSet.descendingSet().descendingSet()", Collections.unmodifiableNavigableSet(new TreeSet().descendingSet().descendingSet())}, + new Object[]{"emptyNavigableSet()", Collections.emptyNavigableSet()}, + new Object[]{"emptyNavigableSet().descendingSet()", Collections.emptyNavigableSet().descendingSet()}, + new Object[]{"emptyNavigableSet().descendingSet().descendingSet()", Collections.emptyNavigableSet().descendingSet().descendingSet()} + ); + } +} diff --git a/ojluni/src/test/java/util/Collections/Enum.java b/ojluni/src/test/java/util/Collections/Enum.java new file mode 100644 index 00000000000..99acd7193f0 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/Enum.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2000, 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 4323074 + * @summary Basic test for new Enumeration -> List converter + */ + +package test.java.util.Collections; + +import java.util.Collections; +import java.util.List; +import java.util.Vector; + +public class Enum { + public static void main(String[] args) throws Exception { + int[] sizes = {0, 10, 100}; + for (int i=0; i<sizes.length; i++) { + Vector v = new Vector(); + int size = sizes[i]; + for (int j=0; j<size; j++) + v.add(new Integer(j)); + List l = Collections.list(v.elements()); + if (!l.equals(v)) + throw new Exception("Copy failed: "+size); + } + } +} diff --git a/ojluni/src/test/java/util/Collections/EnumerationAsIterator.java b/ojluni/src/test/java/util/Collections/EnumerationAsIterator.java index 60cad8f55a6..5930c4c00de 100644 --- a/ojluni/src/test/java/util/Collections/EnumerationAsIterator.java +++ b/ojluni/src/test/java/util/Collections/EnumerationAsIterator.java @@ -76,43 +76,43 @@ public class EnumerationAsIterator { @DataProvider public static Iterator<Object[]> unmodifiable() { return Arrays.asList( - of("Default-wrapped ArrayList", - () -> wrapInDefault( - Collections.enumeration(new ArrayList<>(Arrays.asList("a")))), - Arrays.asList("a")), - - of("Unmodifiable ArrayList", - Collections.unmodifiableList(new ArrayList<>(Arrays.asList("a"))), - Arrays.asList("a")), - - of("Modifiable ArrayList", - new ArrayList<>(Arrays.asList("a")), - Arrays.asList("a")) + of("Default-wrapped ArrayList", + () -> wrapInDefault( + Collections.enumeration(new ArrayList<>(Arrays.asList("a")))), + Arrays.asList("a")), + + of("Unmodifiable ArrayList", + Collections.unmodifiableList(new ArrayList<>(Arrays.asList("a"))), + Arrays.asList("a")), + + of("Modifiable ArrayList", + new ArrayList<>(Arrays.asList("a")), + Arrays.asList("a")) ).iterator(); } @DataProvider public static Iterator<Object[]> others() { return Arrays.asList( - of("Default Collections.emptyEnumeration()", - () -> wrapInDefault(Collections.emptyEnumeration()), - Collections.emptyList()), + of("Default Collections.emptyEnumeration()", + () -> wrapInDefault(Collections.emptyEnumeration()), + Collections.emptyList()), - of("Collections.emptyEnumeration()", - Collections::emptyEnumeration, - Collections.emptyList()), + of("Collections.emptyEnumeration()", + Collections::emptyEnumeration, + Collections.emptyList()), - of("Collections.emptyList()", - Collections.emptyList(), - Collections.emptyList()), + of("Collections.emptyList()", + Collections.emptyList(), + Collections.emptyList()), - of("Collections.singletonList()", - Collections.singletonList("a"), - Collections.singletonList("a")), + of("Collections.singletonList()", + Collections.singletonList("a"), + Collections.singletonList("a")), - of("Arrays.asList(...)", - Arrays.asList("a", "b", "c"), - Arrays.asList("a", "b", "c")) + of("Arrays.asList(...)", + Arrays.asList("a", "b", "c"), + Arrays.asList("a", "b", "c")) ).iterator(); } @@ -147,8 +147,8 @@ public class EnumerationAsIterator { @Test(dataProvider = "all") public void consumeByForEachRemaining(String description, - Supplier<Enumeration<?>> s, - Collection<?> exp) { + Supplier<Enumeration<?>> s, + Collection<?> exp) { Iterator<?> i = s.get().asIterator(); AtomicInteger ai = new AtomicInteger(); i.forEachRemaining(e -> ai.getAndIncrement()); @@ -167,8 +167,8 @@ public class EnumerationAsIterator { @Test(dataProvider = "all") public void consumeByNextThenForEachRemaining(String description, - Supplier<Enumeration<?>> s, - Collection<?> exp) { + Supplier<Enumeration<?>> s, + Collection<?> exp) { Iterator<?> i = s.get().asIterator(); AtomicInteger ai = new AtomicInteger(); if (i.hasNext()) { @@ -201,22 +201,22 @@ public class EnumerationAsIterator { } @Test(dataProvider = "unmodifiable", - expectedExceptions=UnsupportedOperationException.class) + expectedExceptions=UnsupportedOperationException.class) public void removeThrowsAfterAdvancingE(String description, - Supplier<Enumeration<?>> s, - Collection<?> exp) { + Supplier<Enumeration<?>> s, + Collection<?> exp) { Enumeration<?> e = s.get(); e.nextElement(); e.asIterator().remove(); } @Test(dataProvider = "unmodifiable", - expectedExceptions=UnsupportedOperationException.class) + expectedExceptions=UnsupportedOperationException.class) public void removeThrowsAfterAdvancingI(String description, - Supplier<Enumeration<?>> s, - Collection<?> exp) { + Supplier<Enumeration<?>> s, + Collection<?> exp) { Iterator<?> i = s.get().asIterator(); i.next(); i.remove(); } -}
\ No newline at end of file +} diff --git a/ojluni/src/test/java/util/Collections/EqualsTest.java b/ojluni/src/test/java/util/Collections/EqualsTest.java new file mode 100644 index 00000000000..ca1fd2f1246 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/EqualsTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2012, 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 7144488 + * @summary Infinite recursion for some equals tests in Collections + */ + +package test.java.util.Collections; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class EqualsTest { + public static void main(String[] args) { + boolean test; + + /* synchronizedList test */ + List list = Collections.synchronizedList(new ArrayList()); + list.add(list); + test = list.equals(list); + assertTrue(test); + list.remove(list); + + /* synchronizedSet test */ + Set s = Collections.synchronizedSet(new HashSet()); + s.add(s); + test = s.equals(s); + assertTrue(test); + + /* synchronizedMap test */ + Map m = Collections.synchronizedMap(new HashMap()); + test = m.equals(m); + assertTrue(test); + + } + + private static void assertTrue(boolean b) { + if (!b) + throw new RuntimeException("assertion failed"); + } +} + diff --git a/ojluni/src/test/java/util/Collections/FindSubList.java b/ojluni/src/test/java/util/Collections/FindSubList.java new file mode 100644 index 00000000000..eac53fcd47c --- /dev/null +++ b/ojluni/src/test/java/util/Collections/FindSubList.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2000, 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 4323074 + * @summary Basic test for Collections.indexOfSubList/lastIndexOfSubList + */ + +package test.java.util.Collections; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Vector; + +public class FindSubList { + public static void main(String[] args) throws Exception { + int N = 500; + List source = new ArrayList(3 * N); + List[] target = new List[N+1]; + int[] index = new int[N+1]; + for (int i=0; i<=N; i++) { + List t = new ArrayList(); + String s = Integer.toString(i, 2); + for (int j=0, len = s.length(); j<len; j++) + t.add(s.charAt(j)=='1' ? "1" : "0"); + target[i] = t; + if (i == N) { + index[i] = -1; + } else { + index[i] = source.size(); + source.addAll(t); + source.add("*"); + } + } + + List[] src = { + source, + new LinkedList(source), + new Vector(source), + Arrays.asList(source.toArray()) + }; + for (int j=0; j<src.length; j++) { + List s = src[j]; + + for (int i=0; i<=N; i++) { + int idx = Collections.indexOfSubList(s, target[i]); + if (idx != index[i]) + throw new Exception(s.getClass()+" indexOfSubList: " + i + + "is " + idx + ", should be "+index[i]); + } + + if (Collections.indexOfSubList(s,Collections.nCopies(2*s.size(), + "0")) != -1) + throw new Exception(s.getClass()+" indexOfSubList: big target"); + + } + + Collections.reverse(source); + int srcSize = source.size(); + for (int i=0; i<=N; i++) { + Collections.reverse(target[i]); + if (i != N) + index[i] = srcSize - index[i] - target[i].size(); + } + List[] src2 = { + source, + new LinkedList(source), + new Vector(source), + Arrays.asList(source.toArray()) + }; + for (int j=0; j<src2.length; j++) { + List s = src2[j]; + + for (int i=0; i<=N; i++) { + int idx = Collections.lastIndexOfSubList(s, target[i]); + if (idx != index[i]) + throw new Exception(s.getClass()+" lastIdexOfSubList: "+i + + "is " + idx + ", should be "+index[i]); + } + if (Collections.indexOfSubList(s,Collections.nCopies(2*s.size(), + "0")) != -1) + throw new Exception(s.getClass()+" lastIndexOfSubList: big tgt"); + } + } +} diff --git a/ojluni/src/test/java/util/Collections/Frequency.java b/ojluni/src/test/java/util/Collections/Frequency.java new file mode 100644 index 00000000000..fbf72fa77bc --- /dev/null +++ b/ojluni/src/test/java/util/Collections/Frequency.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003, 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 4193200 + * @summary Basic test for Collections.frequency + * @author Josh Bloch + */ + +package test.java.util.Collections; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +public class Frequency { + static final int N = 100; + public static void main(String[] args) { + test(new ArrayList<Integer>()); + test(new LinkedList<Integer>()); + } + + static void test(List<Integer> list) { + for (int i = 0; i < N; i++) + for (int j = 0; j < i; j++) + list.add(i); + Collections.shuffle(list); + + for (int i = 0; i < N; i++) + if (Collections.frequency(list, i) != i) + throw new RuntimeException(list.getClass() + ": " + i); + } +} diff --git a/ojluni/src/test/java/util/Collections/MinMax.java b/ojluni/src/test/java/util/Collections/MinMax.java new file mode 100644 index 00000000000..aa00345de22 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/MinMax.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2001, 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 4486049 + * @summary min and max methods fail if size changes in between a call to size + * and an attempt to iterate. + * @author Josh Bloch + */ + +package test.java.util.Collections; + +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; + +public class MinMax { + public static void main(String[] args) { + Set s = new LyingSet(); + s.add("x"); + if (!Collections.min(s).equals("x")) + throw new RuntimeException("1: " + Collections.min(s)); + if (!Collections.max(s).equals("x")) + throw new RuntimeException("2: " + Collections.max(s)); + + s.add("y"); + if (!Collections.min(s).equals("x")) + throw new RuntimeException("3: " + Collections.min(s)); + if (!Collections.max(s).equals("y")) + throw new RuntimeException("4: " + Collections.max(s)); + + s.add("w"); + if (!Collections.min(s).equals("w")) + throw new RuntimeException("5: " + Collections.min(s)); + if (!Collections.max(s).equals("y")) + throw new RuntimeException("6: " + Collections.max(s)); + + s.clear(); + s.add("x"); + if (!Collections.min(s, Collections.reverseOrder()).equals("x")) + throw new RuntimeException("1a: " + Collections.min(s)); + if (!Collections.max(s, Collections.reverseOrder()).equals("x")) + throw new RuntimeException("2a: " + Collections.max(s)); + + s.add("y"); + if (!Collections.min(s, Collections.reverseOrder()).equals("y")) + throw new RuntimeException("3a: " + Collections.min(s)); + if (!Collections.max(s, Collections.reverseOrder()).equals("x")) + throw new RuntimeException("4a: " + Collections.max(s)); + + s.add("w"); + if (!Collections.min(s, Collections.reverseOrder()).equals("y")) + throw new RuntimeException("5a: " + Collections.min(s)); + if (!Collections.max(s, Collections.reverseOrder()).equals("w")) + throw new RuntimeException("6a: " + Collections.max(s)); + } +} + +class LyingSet extends LinkedHashSet { + public int size() { + return super.size() + 1; // Lies, lies, all lies! + } +} diff --git a/ojluni/src/test/java/util/Collections/NullComparator.java b/ojluni/src/test/java/util/Collections/NullComparator.java new file mode 100644 index 00000000000..c1d29bbbfe0 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/NullComparator.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1999, 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 4224271 + * @summary A null Comparator is now specified to indicate natural ordering. + */ + +package test.java.util.Collections; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class NullComparator { + public static void main(String[] args) throws Exception { + List list = new ArrayList(100); + for (int i=0; i<100; i++) + list.add(new Integer(i)); + List sorted = new ArrayList(list); + Collections.shuffle(list); + + Object[] a = list.toArray(); + Arrays.sort(a, null); + if (!Arrays.asList(a).equals(sorted)) + throw new Exception("Arrays.sort"); + a = list.toArray(); + Arrays.sort(a, 0, 100, null); + if (!Arrays.asList(a).equals(sorted)) + throw new Exception("Arrays.sort(from, to)"); + if (Arrays.binarySearch(a, new Integer(69)) != 69) + throw new Exception("Arrays.binarySearch"); + + List tmp = new ArrayList(list); + Collections.sort(tmp, null); + if (!tmp.equals(sorted)) + throw new Exception("Collections.sort"); + if (Collections.binarySearch(tmp, new Integer(69)) != 69) + throw new Exception("Collections.binarySearch"); + if (!Collections.min(list, null).equals(new Integer(0))) + throw new Exception("Collections.min"); + if (!Collections.max(list, null).equals(new Integer(99))) + throw new Exception("Collections.max"); + } +} diff --git a/ojluni/src/test/java/util/Collections/RacingCollections.java b/ojluni/src/test/java/util/Collections/RacingCollections.java new file mode 100644 index 00000000000..0b39842b3bb --- /dev/null +++ b/ojluni/src/test/java/util/Collections/RacingCollections.java @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2006, 2010, 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 6360946 6360948 + * @summary Test various operations on concurrently mutating collections + * @author Martin Buchholz + */ + +package test.java.util.Collections; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.Vector; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.LinkedTransferQueue; + +import static java.util.Collections.asLifoQueue; +import static java.util.Collections.checkedList; +import static java.util.Collections.checkedMap; +import static java.util.Collections.checkedSet; +import static java.util.Collections.newSetFromMap; +import static java.util.Collections.synchronizedList; +import static java.util.Collections.synchronizedMap; +import static java.util.Collections.synchronizedSet; +import static java.util.Collections.unmodifiableList; +import static java.util.Collections.unmodifiableMap; +import static java.util.Collections.unmodifiableSet; + +public class RacingCollections { + /** + * How long to run each "race" (in milliseconds). + * Turn this up to some higher value like 1000 for stress testing: + * java -Dmillis=1000 RacingCollections + */ + static final long defaultWorkTimeMillis = Long.getLong("millis", 10L); + + /** + * Whether to print debug information. + */ + static final boolean debug = Boolean.getBoolean("debug"); + + static final Integer one = 1; + static final Integer two = 2; + + /** + * A thread that mutates an object forever, alternating between + * being empty and containing singleton "two" + */ + static class Frobber extends CheckedThread { + volatile boolean done = false; + boolean keepGoing(int i) { return (i % 128 != 0) || ! done; } + + final Object elLoco; + Frobber(Object elLoco) { + this.elLoco = elLoco; + this.start(); + } + + @SuppressWarnings("unchecked") + void clear(Object o) { + if (o instanceof Collection) + ((Collection<?>)o).clear(); + else + ((Map<?,?>)o).clear(); + } + + @SuppressWarnings("unchecked") + void realRun() { + // Mutate elLoco wildly forever, checking occasionally for "done" + clear(elLoco); + if (elLoco instanceof List) { + List<Integer> l = (List<Integer>) elLoco; + for (int i = 0; keepGoing(i); i++) { + switch (i%2) { + case 0: l.add(two); break; + case 1: l.add(0, two); break; + } + switch (i%2) { + case 0: l.remove(two); break; + case 1: l.remove(0); break; + }}} + else if (elLoco instanceof Deque) { + Deque<Integer> q = (Deque<Integer>) elLoco; + for (int i = 0; keepGoing(i); i++) { + switch (i%6) { + case 0: q.add(two); break; + case 1: q.addFirst(two); break; + case 2: q.addLast(two); break; + case 3: q.offer(two); break; + case 4: q.offerFirst(two); break; + case 5: q.offerLast(two); break; + } + switch (i%6) { + case 0: q.remove(two); break; + case 1: q.removeFirst(); break; + case 2: q.removeLast(); break; + case 3: q.poll(); break; + case 4: q.pollFirst(); break; + case 5: q.pollLast(); break; + }}} + else if (elLoco instanceof Queue) { + Queue<Integer> q = (Queue<Integer>) elLoco; + for (int i = 0; keepGoing(i); i++) { + switch (i%2) { + case 0: q.add(two); break; + case 1: q.offer(two); break; + } + switch (i%2) { + case 0: q.remove(two); break; + case 1: q.poll(); break; + }}} + else if (elLoco instanceof Map) { + Map<Integer, Boolean> m = (Map<Integer, Boolean>) elLoco; + for (int i = 0; keepGoing(i); i++) { + m.put(two, true); + m.remove(two); + }} + else if (elLoco instanceof Collection) { + Collection<Integer> c = (Collection<Integer>) elLoco; + for (int i = 0; keepGoing(i); i++) { + c.add(two); + c.remove(two); + }} + else { throw new Error("Huh? " + elLoco); } + } + + void enoughAlready() { + done = true; + try { join(); } catch (Throwable t) { unexpected(t); } + } + } + + private static void checkEqualSanity(Object theRock, Object elLoco) { + //equal(theRock, theRock); + equal(elLoco, elLoco); + + // It would be nice someday to have theRock and elLoco never "equal", + // although the meaning of "equal" for mutating collections + // is a bit fuzzy. Uncomment when/if we fix: + // 6374942: Improve thread safety of collection .equals() methods + //notEqual(theRock, elLoco); + //notEqual(elLoco, theRock); + + notEqual(theRock.toString(), elLoco.toString()); + } + + static class Looper { + final long quittingTime; + int i = 0; + Looper() { this(defaultWorkTimeMillis); } + Looper(long workTimeMillis) { + quittingTime = System.nanoTime() + workTimeMillis * 1024 * 1024; + } + boolean keepGoing() { + return (i++ % 128 != 0) || (System.nanoTime() - quittingTime < 0); + } + } + + private static void frob(Object theRock, Object elLoco) { + Frobber frobber = new Frobber(elLoco); + try { + if (theRock instanceof Collection) { + @SuppressWarnings("unchecked") + Collection<Integer> c = (Collection<Integer>) theRock; + if (! c.contains(one)) + c.add(one); + } else { + @SuppressWarnings("unchecked") + Map<Integer, Boolean> m = (Map<Integer, Boolean>) theRock; + if (! m.containsKey(one)) + m.put(one, true); + } + for (Looper looper = new Looper(); looper.keepGoing(); ) + checkEqualSanity(theRock, elLoco); + } + catch (Throwable t) { unexpected(t); } + finally { frobber.enoughAlready(); } + } + + private static List<Map<Integer, Boolean>> newConcurrentMaps() { + List<Map<Integer, Boolean>> list = new ArrayList<>(); + list.add(new ConcurrentHashMap<Integer, Boolean>()); + list.add(new ConcurrentSkipListMap<Integer, Boolean>()); + return list; + } + + private static List<Map<Integer, Boolean>> maps() { + List<Map<Integer, Boolean>> list = newConcurrentMaps(); + list.add(new Hashtable<Integer, Boolean>()); + list.add(new HashMap<Integer, Boolean>()); + list.add(new TreeMap<Integer, Boolean>()); + Comparator<Integer> cmp = new Comparator<>() { + public int compare(Integer x, Integer y) { + return x - y; + }}; + list.add(new TreeMap<Integer, Boolean>(Collections.reverseOrder(cmp))); + return list; + } + + private static List<Set<Integer>> newConcurrentSets() { + List<Set<Integer>> list = new ArrayList<>(); + list.add(new ConcurrentSkipListSet<Integer>()); + list.add(new CopyOnWriteArraySet<Integer>()); + return list; + } + + private static List<Set<Integer>> newSets() { + List<Set<Integer>> list = newConcurrentSets(); + list.add(new HashSet<Integer>()); + list.add(new TreeSet<Integer>()); + list.add(new TreeSet<Integer>(Collections.reverseOrder())); + return list; + } + + private static List<List<Integer>> newConcurrentLists() { + List<List<Integer>> list = new ArrayList<>(); + list.add(new CopyOnWriteArrayList<Integer>()); + return list; + } + + private static List<List<Integer>> newLists() { + List<List<Integer>> list = newConcurrentLists(); + list.add(new Vector<Integer>()); + list.add(new ArrayList<Integer>()); + return list; + } + + private static List<Queue<Integer>> newConcurrentQueues() { + List<Queue<Integer>> list = new ArrayList<>(newConcurrentDeques()); + list.add(new ArrayBlockingQueue<Integer>(10)); + list.add(new LinkedBlockingQueue<Integer>(10)); + list.add(new LinkedTransferQueue<Integer>()); + list.add(new ConcurrentLinkedQueue<Integer>()); + return list; + } + + private static List<Queue<Integer>> newQueues() { + List<Queue<Integer>> list = new ArrayList<>(newDeques()); + list.add(new LinkedBlockingQueue<Integer>(10)); + return list; + } + + private static List<Deque<Integer>> newConcurrentDeques() { + List<Deque<Integer>> list = new ArrayList<>(); + list.add(new LinkedBlockingDeque<Integer>(10)); + list.add(new ConcurrentLinkedDeque<Integer>()); + return list; + } + + private static List<Deque<Integer>> newDeques() { + List<Deque<Integer>> list = newConcurrentDeques(); + list.add(new ArrayDeque<Integer>()); + list.add(new LinkedList<Integer>()); + return list; + } + + private static void describe(Class<?> k, Object x, Object y) { + if (debug) + System.out.printf("%s: %s, %s%n", k.getSimpleName(), + x.getClass().getSimpleName(), + y.getClass().getSimpleName()); + } + + private static void realMain(String[] args) { + for (Map<Integer, Boolean> x : maps()) + for (Map<Integer, Boolean> y : newConcurrentMaps()) { + describe(Map.class, x, y); + x.put(one, true); + frob(x, y); + frob(unmodifiableMap(x), y); + frob(synchronizedMap(x), y); + frob(x, synchronizedMap(y)); + frob(checkedMap(x, Integer.class, Boolean.class), y); + frob(x, checkedMap(y, Integer.class, Boolean.class)); + x.clear(); + frob(newSetFromMap(x), newSetFromMap(y)); + frob(x.keySet(), newSetFromMap(y)); + } + + for (Set<Integer> x : newSets()) + for (Set<Integer> y : newConcurrentSets()) { + describe(Set.class, x, y); + frob(x, y); + frob(unmodifiableSet(x), y); + frob(synchronizedSet(x), y); + frob(x, synchronizedSet(y)); + frob(checkedSet(x, Integer.class), y); + frob(x, checkedSet(y, Integer.class)); + } + + for (List<Integer> x : newLists()) + for (List<Integer> y : newConcurrentLists()) { + describe(List.class, x, y); + frob(x, y); + frob(unmodifiableList(x), y); + frob(synchronizedList(x), y); + frob(x, synchronizedList(y)); + frob(checkedList(x, Integer.class), y); + frob(x, checkedList(y, Integer.class)); + } + + for (Queue<Integer> x : newQueues()) + for (Queue<Integer> y : newConcurrentQueues()) { + describe(Queue.class, x, y); + frob(x, y); + } + + for (Deque<Integer> x : newDeques()) + for (Deque<Integer> y : newConcurrentDeques()) { + describe(Deque.class, x, y); + frob(asLifoQueue(x), y); + frob(x, asLifoQueue(y)); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void check(boolean cond) {if (cond) pass(); else fail();} + static String toString(Object x) { + return ((x instanceof Collection) || (x instanceof Map)) ? + x.getClass().getName() : x.toString();} + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(toString(x) + " not equal to " + toString(y));} + static void notEqual(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) + fail(toString(x) + " equal to " + toString(y)); + else pass();} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + private abstract static class CheckedThread extends Thread { + abstract void realRun() throws Throwable; + public void run() { + try { realRun(); } catch (Throwable t) { unexpected(t); }}} +} diff --git a/ojluni/src/test/java/util/Collections/ReplaceAll.java b/ojluni/src/test/java/util/Collections/ReplaceAll.java new file mode 100644 index 00000000000..75ab1917be9 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/ReplaceAll.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2000, 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 4323074 + * @summary Basic test for new replaceAll algorithm + */ + +package test.java.util.Collections; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Vector; + +public class ReplaceAll { + static final int SIZE = 20; + + public static void main(String[] args) throws Exception { + List[] a = {new ArrayList(), new LinkedList(), new Vector()}; + + for (int i=0; i<a.length; i++) { + List lst = a[i]; + for (int j=1; j<=SIZE; j++) + lst.add(new Integer(j % 3)); + List goal = Collections.nCopies(SIZE, "*"); + + for (int j=0; j<3; j++) { + List before = new ArrayList(lst); + if (!Collections.replaceAll(lst, new Integer(j), "*")) + throw new Exception("False return value: "+i+", "+j); + if (lst.equals(before)) + throw new Exception("Unchanged: "+i+", "+j+", "+": "+lst); + if (lst.equals(goal) != (j==2)) + throw new Exception("Wrong change:"+i+", "+j); + } + if (Collections.replaceAll(lst, "love", "hate")) + throw new Exception("True return value: "+i); + } + } +} diff --git a/ojluni/src/test/java/util/Collections/ReverseOrder.java b/ojluni/src/test/java/util/Collections/ReverseOrder.java new file mode 100644 index 00000000000..c43abd13700 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/ReverseOrder.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2002, 2013, 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 4593209 8001667 + * @summary Reverse comparator was subtly broken + * @author Josh Bloch + */ + +package test.java.util.Collections; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class ReverseOrder { + static byte[] serialBytes(Object o) { + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(o); + oos.flush(); + oos.close(); + return bos.toByteArray(); + } catch (Throwable t) { + throw new Error(t); + } + } + + @SuppressWarnings("unchecked") + static <T> T serialClone(T o) { + try { + ObjectInputStream ois = new ObjectInputStream + (new ByteArrayInputStream(serialBytes(o))); + T clone = (T) ois.readObject(); + return clone; + } catch (Throwable t) { + throw new Error(t); + } + } + + public static void main(String[] args) throws Exception { + Foo[] a = { new Foo(2), new Foo(3), new Foo(1) }; + List list = Arrays.asList(a); + Comparator cmp = Collections.reverseOrder(); + Collections.sort(list, cmp); + + Foo[] golden = { new Foo(3), new Foo(2), new Foo(1) }; + List goldenList = Arrays.asList(golden); + if (!list.equals(goldenList)) + throw new Exception(list.toString()); + + Comparator clone = serialClone(cmp); + List list2 = Arrays.asList(a); + Collections.sort(list2, clone); + if (!list2.equals(goldenList)) + throw new Exception(list.toString()); + } +} + +class Foo implements Comparable { + int val; + Foo(int i) { val = i; } + + public int compareTo(Object o) { + Foo f = (Foo)o; + return (val < f.val ? Integer.MIN_VALUE : (val == f.val ? 0 : 1)); + } + + public boolean equals(Object o) { + return o instanceof Foo && ((Foo)o).val == val; + } + + public int hashCode() { return val; } + + public String toString() { return Integer.toString(val); } +} diff --git a/ojluni/src/test/java/util/Collections/ReverseOrder2.java b/ojluni/src/test/java/util/Collections/ReverseOrder2.java new file mode 100644 index 00000000000..ddfdb0018a2 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/ReverseOrder2.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2003, 2007, 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 4809442 6366832 4974878 6372554 4890211 6483125 + * @summary Basic test for Collections.reverseOrder + * @author Josh Bloch, Martin Buchholz + */ + +package test.java.util.Collections; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; + +public class ReverseOrder2 { + static final int N = 100; + + static void realMain(String[] args) throws Throwable { + check(Collections.reverseOrder() + == Collections.reverseOrder(null)); + + check(Collections.reverseOrder() + == reincarnate(Collections.reverseOrder())); + + check(Collections.reverseOrder(Collections.reverseOrder(cmp)) + == cmp); + + equal(Collections.reverseOrder(cmp), + Collections.reverseOrder(cmp)); + + equal(Collections.reverseOrder(cmp).hashCode(), + Collections.reverseOrder(cmp).hashCode()); + + check(Collections.reverseOrder(cmp).hashCode() != + cmp.hashCode()); + + test(new ArrayList<String>()); + test(new LinkedList<String>()); + test2(new ArrayList<Integer>()); + test2(new LinkedList<Integer>()); + } + + static void test(List<String> list) { + for (int i = 0; i < N; i++) + list.add(String.valueOf(i)); + Collections.shuffle(list); + Collections.sort(list, Collections.reverseOrder(cmp)); + equal(list, golden); + } + + private static Comparator<String> cmp = new Comparator<>() { + public int compare(String s1, String s2) { + int i1 = Integer.parseInt(s1); + int i2 = Integer.parseInt(s2); + return (i1 < i2 ? Integer.MIN_VALUE : (i1 == i2 ? 0 : 1)); + } + }; + + private static final List<String> golden = new ArrayList<>(N); + static { + for (int i = N-1; i >= 0; i--) + golden.add(String.valueOf(i)); + } + + static void test2(List<Integer> list) { + for (int i = 0; i < N; i++) + list.add(i); + Collections.shuffle(list); + Collections.sort(list, Collections.reverseOrder(null)); + equal(list, golden2); + } + + private static final List<Integer> golden2 = new ArrayList<>(N); + static { + for (int i = N-1; i >= 0; i--) + golden2.add(i); + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void check(boolean cond) {if (cond) pass(); else fail();} + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + static byte[] serializedForm(Object obj) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(obj); + return baos.toByteArray(); + } catch (IOException e) {throw new RuntimeException(e);}} + static Object readObject(byte[] bytes) + throws IOException, ClassNotFoundException { + InputStream is = new ByteArrayInputStream(bytes); + return new ObjectInputStream(is).readObject();} + @SuppressWarnings("unchecked") + static <T> T reincarnate(T obj) { + try {return (T) readObject(serializedForm(obj));} + catch (Exception e) {throw new RuntimeException(e);}} +} diff --git a/ojluni/src/test/java/util/Collections/Rotate.java b/ojluni/src/test/java/util/Collections/Rotate.java new file mode 100644 index 00000000000..77b2d45f0c2 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/Rotate.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2000, 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 4323074 + * @summary Basic test for new rotate algorithm + * @key randomness + */ + +package test.java.util.Collections; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; +import java.util.Vector; + +public class Rotate { + // Should have lots of distinct factors and be > ROTATE_THRESHOLD + static final int SIZE = 120; + + static Random rnd = new Random(); + + public static void main(String[] args) throws Exception { + List[] a = {new ArrayList(), new LinkedList(), new Vector()}; + + for (int i=0; i<a.length; i++) { + List lst = a[i]; + for (int j=0; j<SIZE; j++) + lst.add(new Integer(j)); + int totalDist = 0; + + for (int j=0; j<10000; j++) { + int dist = rnd.nextInt(200) - 100; + Collections.rotate(lst, dist); + + // Check that things are as they should be + totalDist = (totalDist + dist) % SIZE; + if (totalDist < 0) + totalDist += SIZE; + int index =0; + for (int k=totalDist; k<SIZE; k++, index++) + if (((Integer)lst.get(k)).intValue() != index) + throw new Exception("j: "+j+", lst["+k+"]="+lst.get(k)+ + ", should be "+index); + for (int k=0; k<totalDist; k++, index++) + if (((Integer)lst.get(k)).intValue() != index) + throw new Exception("j: "+j+", lst["+k+"]="+lst.get(k)+ + ", should be "+index); + } + } + } +} diff --git a/ojluni/src/test/java/util/Collections/RotateEmpty.java b/ojluni/src/test/java/util/Collections/RotateEmpty.java new file mode 100644 index 00000000000..eaf671946db --- /dev/null +++ b/ojluni/src/test/java/util/Collections/RotateEmpty.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2000, 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 4389747 + * @summary Collections.rotate(...) returns ArithmeticException + */ + +package test.java.util.Collections; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class RotateEmpty { + + public static void main(String[] args) throws Exception { + List l = new ArrayList(); + Collections.rotate(l, 1); + } +} diff --git a/ojluni/src/test/java/util/Collections/Ser.java b/ojluni/src/test/java/util/Collections/Ser.java new file mode 100644 index 00000000000..5ee8b0eb8ad --- /dev/null +++ b/ojluni/src/test/java/util/Collections/Ser.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1999, 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 4190323 + * @summary EMPTY_SET, EMPTY_LIST, and the collections returned by + * nCopies and singleton were spec'd to be serializable, but weren't. + */ + +package test.java.util.Collections; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +public class Ser { + public static void main(String[] args) throws Exception { + + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bos); + out.writeObject(Collections.EMPTY_SET); + out.flush(); + ObjectInputStream in = new ObjectInputStream( + new ByteArrayInputStream(bos.toByteArray())); + + if (!Collections.EMPTY_SET.equals(in.readObject())) + throw new RuntimeException("empty set Ser/Deser failure."); + } catch (Exception e) { + throw new RuntimeException("Failed to serialize empty set:" + e); + } + + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bos); + out.writeObject(Collections.EMPTY_LIST); + out.flush(); + ObjectInputStream in = new ObjectInputStream( + new ByteArrayInputStream(bos.toByteArray())); + + if (!Collections.EMPTY_LIST.equals(in.readObject())) + throw new RuntimeException("empty list Ser/Deser failure."); + } catch (Exception e) { + throw new RuntimeException("Failed to serialize empty list:" + e); + } + + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bos); + Set gumby = Collections.singleton("gumby"); + out.writeObject(gumby); + out.flush(); + ObjectInputStream in = new ObjectInputStream( + new ByteArrayInputStream(bos.toByteArray())); + + if (!gumby.equals(in.readObject())) + throw new RuntimeException("Singleton Ser/Deser failure."); + } catch (Exception e) { + throw new RuntimeException("Failed to serialize singleton:" + e); + } + + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bos); + List gumbies = Collections.nCopies(50, "gumby"); + out.writeObject(gumbies); + out.flush(); + ObjectInputStream in = new ObjectInputStream( + new ByteArrayInputStream(bos.toByteArray())); + + if (!gumbies.equals(in.readObject())) + throw new RuntimeException("nCopies Ser/Deser failure."); + } catch (Exception e) { + throw new RuntimeException("Failed to serialize nCopies:" + e); + } + } +} diff --git a/ojluni/src/test/java/util/Collections/SetFromMap.java b/ojluni/src/test/java/util/Collections/SetFromMap.java new file mode 100644 index 00000000000..651944b9508 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/SetFromMap.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2005, 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 6301089 + * @summary test Collections.newSetFromMap + * @author Martin Buchholz + */ + +package test.java.util.Collections; + +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Set; + +public class SetFromMap { + static volatile int passed = 0, failed = 0; + static void pass() { passed++; } + static void fail() { failed++; Thread.dumpStack(); } + static void unexpected(Throwable t) { failed++; t.printStackTrace(); } + static void check(boolean cond) { if (cond) pass(); else fail(); } + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else {System.out.println(x + " not equal to " + y); fail(); }} + + public static void main(String[] args) throws Throwable { + try { realMain(); } catch (Throwable t) { unexpected(t); } + + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new Exception("Some tests failed"); + } + + private static void realMain() throws Throwable { + try { + Map<String,Boolean> m = new IdentityHashMap<>(); + Set<String> s = Collections.newSetFromMap(m); + String foo1 = new String("foo"); + String foo2 = new String("foo"); + String bar = new String("bar"); + check(s.add(foo1)); + check(s.add(foo2)); + check(s.add(bar)); + equal(s.size(), 3); + check(s.contains(foo1)); + check(s.contains(foo2)); + check(! s.contains(new String(foo1))); + } catch (Throwable t) { unexpected(t); } + } +} diff --git a/ojluni/src/test/java/util/Collections/SingletonIterator.java b/ojluni/src/test/java/util/Collections/SingletonIterator.java new file mode 100644 index 00000000000..c38909cb64a --- /dev/null +++ b/ojluni/src/test/java/util/Collections/SingletonIterator.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016, 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 8024500 8166446 + * @run testng SingletonIterator + */ + +package test.java.util.Collections; + +import java.util.Collections; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.concurrent.atomic.AtomicInteger; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.fail; + +@Test(groups = "unit") +public class SingletonIterator { + static void assertIteratorExhausted(Iterator<?> it) { + assertFalse(it.hasNext()); + try { + it.next(); + fail("should have thrown NoSuchElementException"); + } catch (NoSuchElementException success) { } + it.forEachRemaining(e -> { throw new AssertionError("action called incorrectly"); }); + } + + public void testForEachRemaining() { + Iterator<String> it = Collections.singleton("TheOne").iterator(); + AtomicInteger cnt = new AtomicInteger(0); + + it.forEachRemaining(s -> { + assertEquals("TheOne", s); + cnt.incrementAndGet(); + }); + + assertEquals(cnt.get(), 1); + assertIteratorExhausted(it); + } + + static class SingletonException extends RuntimeException { } + + public void testThrowFromForEachRemaining() { + Iterator<String> it = Collections.singleton("TheOne").iterator(); + + try { + it.forEachRemaining(s -> { throw new SingletonException(); }); + } catch (SingletonException ignore) { } + + assertIteratorExhausted(it); + } +} diff --git a/ojluni/src/test/java/util/Collections/Swap.java b/ojluni/src/test/java/util/Collections/Swap.java new file mode 100644 index 00000000000..3beec42b800 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/Swap.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2000, 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 4323074 + * @summary Basic test for newly public swap algorithm + * @author Josh Bloch + */ + +package test.java.util.Collections; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Swap { + static final int SIZE = 100; + + public static void main(String[] args) throws Exception { + List l = new ArrayList(Collections.nCopies(100, Boolean.FALSE)); + l.set(0, Boolean.TRUE); + for (int i=0; i < SIZE-1; i++) + Collections.swap(l, i, i+1); + + List l2 = new ArrayList(Collections.nCopies(100, Boolean.FALSE)); + l2.set(SIZE-1, Boolean.TRUE); + if (!l.equals(l2)) + throw new RuntimeException("Wrong result"); + } +} diff --git a/ojluni/src/test/java/util/Collections/SyncSubMutexes.java b/ojluni/src/test/java/util/Collections/SyncSubMutexes.java new file mode 100644 index 00000000000..2fcd3d65c7a --- /dev/null +++ b/ojluni/src/test/java/util/Collections/SyncSubMutexes.java @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2014, 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. + */ + +package test.java.util.Collections; + +/** + * @test + * @bug 8048209 + * @summary Check that Collections.synchronizedNavigableSet().tailSet() is using + * the same lock object as it's source. + * @modules java.base/java.util:open + * @run testng SyncSubMutexes + */ +import java.lang.reflect.Field; +import java.util.*; +import java.util.Set; +import java.util.Arrays; + +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; +import static org.testng.Assert.assertSame; + +public class SyncSubMutexes { + + @Test(dataProvider = "Collections") + public void testCollections(Collection<String> instance) { + // nothing to test, no subset methods + } + + @Test(dataProvider = "Lists") + public void testLists(List<String> instance) { + assertSame(getSyncCollectionMutex(instance.subList(0, 1)), getSyncCollectionMutex(instance)); + } + + @Test(dataProvider = "Sets") + public void testSets(Set<String> instance) { + // nothing to test, no subset methods + + } + + @Test(dataProvider = "SortedSets") + public void testSortedSets(SortedSet<String> instance) { + assertSame(getSyncCollectionMutex(instance.headSet("Echo")), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.tailSet("Charlie")), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.subSet("Charlie", "Echo")), getSyncCollectionMutex(instance)); + + } + + @Test(dataProvider = "NavigableSets") + public void testNavigableSets(NavigableSet<String> instance) { + assertSame(getSyncCollectionMutex(instance.descendingSet()), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.headSet("Echo")), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.headSet("Echo", true)), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.tailSet("Charlie")), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.tailSet("Charlie", true)), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.subSet("Charlie", "Echo")), getSyncCollectionMutex(instance)); + assertSame(getSyncCollectionMutex(instance.subSet("Charlie", true, "Echo", true)), getSyncCollectionMutex(instance)); + } + + @Test(dataProvider = "Maps") + public void testMaps(Map<String, String> instance) { + assertSame(getSyncCollectionMutex(instance.entrySet()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.keySet()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.values()), getSyncMapMutex(instance)); + } + + @Test(dataProvider = "SortedMaps") + public void testSortedMaps(SortedMap<String, String> instance) { + assertSame(getSyncCollectionMutex(instance.entrySet()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.keySet()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.values()), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.headMap("Echo")), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.tailMap("Charlie")), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.subMap("Charlie", "Echo")), getSyncMapMutex(instance)); + } + + @Test(dataProvider = "NavigableMaps") + public void testNavigableMaps(NavigableMap<String, String> instance) { + assertSame(getSyncMapMutex(instance.descendingMap()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.entrySet()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.keySet()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.descendingKeySet()), getSyncMapMutex(instance)); + assertSame(getSyncCollectionMutex(instance.values()), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.headMap("Echo")), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.headMap("Echo", true)), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.tailMap("Charlie")), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.tailMap("Charlie", true)), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.subMap("Charlie", true, "Echo", true)), getSyncMapMutex(instance)); + assertSame(getSyncMapMutex(instance.subMap("Charlie", true, "Echo", true)), getSyncMapMutex(instance)); + } + + @DataProvider(name = "Collections", parallel = true) + public static Iterator<Object[]> collectionProvider() { + return makeCollections().iterator(); + } + + @DataProvider(name = "Lists", parallel = true) + public static Iterator<Object[]> listProvider() { + return makeLists().iterator(); + } + + @DataProvider(name = "Sets", parallel = true) + public static Iterator<Object[]> setProvider() { + return makeSets().iterator(); + } + + @DataProvider(name = "SortedSets", parallel = true) + public static Iterator<Object[]> sortedsetProvider() { + return makeSortedSets().iterator(); + } + + @DataProvider(name = "NavigableSets", parallel = true) + public static Iterator<Object[]> navigablesetProvider() { + return makeNavigableSets().iterator(); + } + + @DataProvider(name = "Maps", parallel = true) + public static Iterator<Object[]> mapProvider() { + return makeMaps().iterator(); + } + + @DataProvider(name = "SortedMaps", parallel = true) + public static Iterator<Object[]> sortedmapProvider() { + return makeSortedMaps().iterator(); + } + + @DataProvider(name = "NavigableMaps", parallel = true) + public static Iterator<Object[]> navigablemapProvider() { + return makeNavigableMaps().iterator(); + } + + private static final Collection<String> BASE_COLLECTION = Collections.unmodifiableCollection( + Arrays.asList("Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf") + ); + private static final Map<String, String> BASE_MAP; + + static { + Map<String, String> map = new HashMap<>(); + for(String each : BASE_COLLECTION) { + map.put(each, "*" + each + "*"); + } + BASE_MAP = Collections.unmodifiableMap(map); + } + + public static Collection<Object[]> makeCollections() { + Collection<Object[]> instances = new ArrayList<>(); + instances.add(new Object[] {Collections.synchronizedCollection(new ArrayList<>(BASE_COLLECTION))}); + instances.addAll(makeLists()); + + return instances; + } + + public static Collection<Object[]> makeLists() { + Collection<Object[]> instances = new ArrayList<>(); + instances.add(new Object[] {Collections.synchronizedList(new ArrayList<>(BASE_COLLECTION))}); + instances.add(new Object[] {Collections.synchronizedList(new ArrayList<>(BASE_COLLECTION)).subList(1, 2)}); + + return instances; + } + + public static Collection<Object[]> makeSets() { + Collection<Object[]> instances = new ArrayList<>(); + + instances.add(new Object[] {Collections.synchronizedSet(new TreeSet<>(BASE_COLLECTION))}); + instances.addAll(makeSortedSets()); + return instances; + } + + public static Collection<Object[]> makeSortedSets() { + Collection<Object[]> instances = new ArrayList<>(); + instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION))}); + instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION)).headSet("Foxtrot")}); + instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION)).tailSet("Bravo")}); + instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION)).subSet("Bravo", "Foxtrot")}); + instances.addAll(makeNavigableSets()); + + return instances; + } + + public static Collection<Object[]> makeNavigableSets() { + Collection<Object[]> instances = new ArrayList<>(); + + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION))}); + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).descendingSet().descendingSet()}); + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).headSet("Foxtrot")}); + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).headSet("Foxtrot", true)}); + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).tailSet("Bravo")}); + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).tailSet("Bravo", true)}); + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).subSet("Bravo", "Foxtrot")}); + instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).subSet("Bravo", true, "Foxtrot", true)}); + + return instances; + } + + public static Collection<Object[]> makeMaps() { + Collection<Object[]> instances = new ArrayList<>(); + + instances.add(new Object[] {Collections.synchronizedMap(new HashMap<>(BASE_MAP))}); + instances.addAll(makeSortedMaps()); + + return instances; + } + + public static Collection<Object[]> makeSortedMaps() { + Collection<Object[]> instances = new ArrayList<>(); + + instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP))}); + instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP)).headMap("Foxtrot")}); + instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP)).tailMap("Bravo")}); + instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP)).subMap("Bravo", "Foxtrot")}); + instances.addAll(makeNavigableMaps()); + + return instances; + } + + public static Collection<Object[]> makeNavigableMaps() { + Collection<Object[]> instances = new ArrayList<>(); + + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP))}); + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP).descendingMap().descendingMap())}); + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).headMap("Foxtrot")}); + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).headMap("Foxtrot", true)}); + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).tailMap("Bravo")}); + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).tailMap("Bravo", true)}); + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).subMap("Bravo", "Foxtrot")}); + instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).subMap("Bravo", true, "Foxtrot", true)}); + + return instances; + } + + private static Object getSyncCollectionMutex(Collection<?> from) { + try { + Class<?> synchronizedCollectionClazz = Class.forName("java.util.Collections$SynchronizedCollection"); + Field f = synchronizedCollectionClazz.getDeclaredField("mutex"); + f.setAccessible(true); + return f.get(from); + } catch ( ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException("Unable to get mutex field.", e); + } + } + + private static Object getSyncMapMutex(Map<?,?> from) { + try { + Class<?> synchronizedMapClazz = Class.forName("java.util.Collections$SynchronizedMap"); + Field f = synchronizedMapClazz.getDeclaredField("mutex"); + f.setAccessible(true); + return f.get(from); + } catch ( ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException("Unable to get mutex field.", e); + } + } + +} diff --git a/ojluni/src/test/java/util/Collections/T6433170.java b/ojluni/src/test/java/util/Collections/T6433170.java new file mode 100644 index 00000000000..df54c8b32b3 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/T6433170.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2007, 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 6433170 + * @summary CheckedCollection.addAll should be all-or-nothing + */ + +package test.java.util.Collections; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Vector; + +import static java.util.Collections.checkedCollection; +import static java.util.Collections.checkedList; +import static java.util.Collections.checkedSet; + +@SuppressWarnings("unchecked") +public class T6433170 { + private void checkEmpty(Collection x) { + check(x.isEmpty()); + check(x.size() == 0); + check(x.toArray().length == 0); + } + + void test(String[] args) throws Throwable { + test(checkedList( + checkedList(new ArrayList(), String.class), + Object.class)); + test(checkedSet( + checkedSet(new HashSet(), String.class), + Object.class)); + test(checkedCollection( + checkedCollection(new Vector(), String.class), + Object.class)); + } + + void test(final Collection checked) { + checkEmpty(checked); + final List mixedList = Arrays.asList("1", 2, "3"); + THROWS(ClassCastException.class, + new F(){void f(){ checked.addAll(mixedList); }}); + checkEmpty(checked); + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new T6433170().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + abstract class F {abstract void f() throws Throwable;} + void THROWS(Class<? extends Throwable> k, F... fs) { + for (F f : fs) + try {f.f(); fail("Expected " + k.getName() + " not thrown");} + catch (Throwable t) { + if (k.isAssignableFrom(t.getClass())) pass(); + else unexpected(t);}} +} diff --git a/ojluni/src/test/java/util/Collections/UnmodifiableMapEntrySet.java b/ojluni/src/test/java/util/Collections/UnmodifiableMapEntrySet.java new file mode 100644 index 00000000000..36940a118e9 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/UnmodifiableMapEntrySet.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2013, 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 + * @run testng UnmodifiableMapEntrySet + * @summary Unit tests for wrapping classes should delegate to default methods + */ + +package test.java.util.Collections; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Spliterator; +import java.util.TreeMap; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; + +import static org.testng.Assert.assertEquals; + +@Test(groups = "unit") +public class UnmodifiableMapEntrySet { + static Object[][] collections; + + static <M extends Map<Integer, Integer>> M fillMap(int size, M m) { + for (int i = 0; i < size; i++) { + m.put(i, i); + } + return m; + } + + @DataProvider(name="maps") + static Object[][] mapCases() { + if (collections != null) { + return collections; + } + + List<Object[]> cases = new ArrayList<>(); + for (int size : new int[] {1, 2, 16}) { + cases.add(new Object[] { + String.format("new HashMap(%d)", size), + (Supplier<Map<Integer, Integer>>) + () -> Collections.unmodifiableMap(fillMap(size, new HashMap<>())) }); + cases.add(new Object[] { + String.format("new TreeMap(%d)", size), + (Supplier<Map<Integer, Integer>>) + () -> Collections.unmodifiableSortedMap(fillMap(size, new TreeMap<>())) }); + } + + return cases.toArray(new Object[0][]); + } + + static class EntryConsumer implements Consumer<Map.Entry<Integer, Integer>> { + int updates; + @Override + public void accept(Map.Entry<Integer, Integer> me) { + try { + me.setValue(Integer.MAX_VALUE); + updates++; + } catch (UnsupportedOperationException e) { + } + } + + void assertNoUpdates() { + assertEquals(updates, 0, "Updates to entries"); + } + } + + void testWithEntryConsumer(Consumer<EntryConsumer> c) { + EntryConsumer ec = new EntryConsumer(); + c.accept(ec); + ec.assertNoUpdates(); + } + + @Test(dataProvider = "maps") + public void testForEach(String d, Supplier<Map<Integer, Integer>> ms) { + testWithEntryConsumer( + ec -> ms.get().entrySet().forEach(ec)); + } + + @Test(dataProvider = "maps") + public void testIteratorForEachRemaining(String d, Supplier<Map<Integer, Integer>> ms) { + testWithEntryConsumer( + ec -> ms.get().entrySet().iterator().forEachRemaining(ec)); + } + + @Test(dataProvider = "maps") + public void testIteratorNext(String d, Supplier<Map<Integer, Integer>> ms) { + testWithEntryConsumer(ec -> { + for (Map.Entry<Integer, Integer> me : ms.get().entrySet()) { + ec.accept(me); + } + }); + } + + @Test(dataProvider = "maps") + public void testSpliteratorForEachRemaining(String d, Supplier<Map<Integer, Integer>> ms) { + testSpliterator( + ms.get().entrySet()::spliterator, + // Higher order function returning a consumer that + // traverses all spliterator elements using an EntryConsumer + s -> ec -> s.forEachRemaining(ec)); + } + + @Test(dataProvider = "maps") + public void testSpliteratorTryAdvance(String d, Supplier<Map<Integer, Integer>> ms) { + testSpliterator( + ms.get().entrySet()::spliterator, + // Higher order function returning a consumer that + // traverses all spliterator elements using an EntryConsumer + s -> ec -> { while (s.tryAdvance(ec)); }); + } + + void testSpliterator(Supplier<Spliterator<Map.Entry<Integer, Integer>>> ss, + // Higher order function that given a spliterator returns a + // consumer for that spliterator which traverses elements + // using an EntryConsumer + Function<Spliterator<Map.Entry<Integer, Integer>>, Consumer<EntryConsumer>> sc) { + testWithEntryConsumer(sc.apply(ss.get())); + + Spliterator<Map.Entry<Integer, Integer>> s = ss.get(); + Spliterator<Map.Entry<Integer, Integer>> split = s.trySplit(); + if (split != null) { + testWithEntryConsumer(sc.apply(split)); + testWithEntryConsumer(sc.apply(s)); + } + } + + @Test(dataProvider = "maps") + public void testStreamForEach(String d, Supplier<Map<Integer, Integer>> ms) { + testWithEntryConsumer(ec -> ms.get().entrySet().stream().forEach(ec)); + } + + @Test(dataProvider = "maps") + public void testParallelStreamForEach(String d, Supplier<Map<Integer, Integer>> ms) { + testWithEntryConsumer(ec -> ms.get().entrySet().parallelStream().forEach(ec)); + } +} + diff --git a/ojluni/src/test/java/util/Collections/ViewSynch.java b/ojluni/src/test/java/util/Collections/ViewSynch.java new file mode 100644 index 00000000000..9c7b3ae3b9e --- /dev/null +++ b/ojluni/src/test/java/util/Collections/ViewSynch.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 1999, 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 4268780 + * @summary Collection-views of submap-views of synchronized-views of + * SortedMap objects do not synchronize on the correct object. + * (Got that?) + */ + +package test.java.util.Collections; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +public class ViewSynch { + static final Integer ZERO = new Integer(0); + static final Int INT_ZERO = new Int(0); + static final Int INT_ONE = new Int(1); + static SortedMap m = Collections.synchronizedSortedMap(new TreeMap()); + static Map m2 = m.tailMap(ZERO); + static Collection c = m2.values(); + + public static void main(String[] args) { + for (int i=0; i<10000; i++) + m.put(new Integer(i), INT_ZERO); + + new Thread() { + public void run() { + for (int i=0; i<100; i++) { + Thread.yield(); + m.remove(ZERO); + m.put(ZERO, INT_ZERO); + } + } + }.start(); + + c.contains(INT_ONE); + } +} + +/** + * Like Integer, except yields while doing equals comparison, to allow + * for interleaving. + */ +class Int { + Integer x; + Int(int i) {x = new Integer(i);} + + public boolean equals(Object o) { + Thread.yield(); + Int i = (Int)o; + return x.equals(i.x); + } + + public int hashCode() {return x.hashCode();} +} diff --git a/ojluni/src/test/java/util/Collections/WrappedNull.java b/ojluni/src/test/java/util/Collections/WrappedNull.java new file mode 100644 index 00000000000..418412e9cd5 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/WrappedNull.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 1999, 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 4189641 + * @summary Wrapping a null collection/array should blow up sooner + * rather than later + */ + +package test.java.util.Collections; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; + +public class WrappedNull { + public static void main(String[] args) throws Exception { + boolean testSucceeded = false; + try { + List l = Arrays.asList(null); + } + catch (NullPointerException e) { + testSucceeded = true; + } + if (!testSucceeded) + throw new Exception("Arrays.asList"); + + testSucceeded = false; + try { + Collection c = Collections.unmodifiableCollection(null); + } + catch (NullPointerException e) { + testSucceeded = true; + } + if (!testSucceeded) + throw new Exception("unmodifiableCollection"); + + testSucceeded = false; + try { + Set c = Collections.unmodifiableSet(null); + } + catch (NullPointerException e) { + testSucceeded = true; + } + if (!testSucceeded) + throw new Exception("unmodifiableSet"); + + testSucceeded = false; + try { + List c = Collections.unmodifiableList(null); + } + catch (NullPointerException e) { + testSucceeded = true; + } + if (!testSucceeded) + throw new Exception("unmodifiableList"); + + testSucceeded = false; + try { + Map c = Collections.unmodifiableMap(null); + } + catch (NullPointerException e) { + testSucceeded = true; + } + if (!testSucceeded) + throw new Exception("unmodifiableMap"); + + testSucceeded = false; + try { + SortedSet c = Collections.unmodifiableSortedSet(null); + } + catch (NullPointerException e) { + testSucceeded = true; + } + if (!testSucceeded) + throw new Exception("unmodifiableSortedSet"); + + testSucceeded = false; + try { + SortedMap c = Collections.unmodifiableSortedMap(null); + } + catch (NullPointerException e) { + testSucceeded = true; + } + if (!testSucceeded) + throw new Exception("unmodifiableSortedMap"); + + testSucceeded = false; + try { + Collection c = Collections.synchronizedCollection(null); + } + catch (NullPointerException e) { + testSucceeded = true; + } + if (!testSucceeded) + throw new Exception("synchronizedCollection"); + + testSucceeded = false; + try { + Set c = Collections.synchronizedSet(null); + } + catch (NullPointerException e) { + testSucceeded = true; + } + if (!testSucceeded) + throw new Exception("synchronizedSet"); + + testSucceeded = false; + try { + List c = Collections.synchronizedList(null); + } + catch (NullPointerException e) { + testSucceeded = true; + } + if (!testSucceeded) + throw new Exception("synchronizedList"); + + testSucceeded = false; + try { + Map c = Collections.synchronizedMap(null); + } + catch (NullPointerException e) { + testSucceeded = true; + } + if (!testSucceeded) + throw new Exception("synchronizedMap"); + + testSucceeded = false; + try { + SortedSet c = Collections.synchronizedSortedSet(null); + } + catch (NullPointerException e) { + testSucceeded = true; + } + if (!testSucceeded) + throw new Exception("synchronizedSortedSet"); + + testSucceeded = false; + try { + SortedMap c = Collections.synchronizedSortedMap(null); + } + catch (NullPointerException e) { + testSucceeded = true; + } + if (!testSucceeded) + throw new Exception("synchronizedSortedMap"); + + // Make sure that non-null arguments don't throw exc. + List l = Arrays.asList(new Object[0]); + Collection c = Collections.unmodifiableCollection( + Collections.EMPTY_SET); + Set s = Collections.unmodifiableSet(Collections.EMPTY_SET); + l = Collections.unmodifiableList(Collections.EMPTY_LIST); + Map m = Collections.unmodifiableMap(Collections.EMPTY_MAP); + SortedSet ss = Collections.unmodifiableSortedSet(new TreeSet()); + SortedMap sm = Collections.unmodifiableSortedMap(new TreeMap()); + + c = Collections.synchronizedCollection(Collections.EMPTY_SET); + s = Collections.synchronizedSet(Collections.EMPTY_SET); + l = Collections.synchronizedList(Collections.EMPTY_LIST); + m = Collections.synchronizedMap(Collections.EMPTY_MAP); + ss = Collections.synchronizedSortedSet(new TreeSet()); + sm = Collections.synchronizedSortedMap(new TreeMap()); + } +} diff --git a/ojluni/src/test/java/util/Collections/WrappedUnmodifiableCollections.java b/ojluni/src/test/java/util/Collections/WrappedUnmodifiableCollections.java new file mode 100644 index 00000000000..b991d0b6c57 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/WrappedUnmodifiableCollections.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2021, 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 6323374 + * @run testng WrappedUnmodifiableCollections + */ + +package test.java.util.Collections; + +import java.util.*; +import java.util.function.Function; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + + +@Test +public class WrappedUnmodifiableCollections { + + private static <T,E extends T> void testWrapping(T collection, Function<T,E> wrapper) { + var collection1 = wrapper.apply(collection); + var collection2 = wrapper.apply(collection1); + assertNotSame(collection, collection2); + assertSame(collection1, collection2); + } + + public void testUnmodifiableListsDontWrap() { + List<List<?>> lists = List.of(List.of(), List.of(1,2,3), List.of(1), + List.of(1,2,3,4,5,6), + List.of(1,2,3).subList(0,1), + new LinkedList<>(List.of(1,2,3)), + new ArrayList<>(List.of(1,2,3))); + + for(List<?> list : lists) { + testWrapping(list, Collections::unmodifiableList); + } + } + + public void testUnmodifiableCollectionsDontWrap() { + Collection<?> list = List.of(); + testWrapping(list, Collections::unmodifiableCollection); + } + + public void testUnmodifiableSetsDontWrap() { + + List<Set<?>> sets = List.of(new TreeSet<>(), + Set.of(1, 2), + Set.of(1,2,3,4,5,6)); + + for (Set<?> set : sets) { + testWrapping(set, Collections::unmodifiableSet); + } + + TreeSet<?> treeSet = new TreeSet<>(); + + //Collections.UnmodifiableSortedSet + testWrapping((SortedSet<?>) treeSet, Collections::unmodifiableSortedSet); + + //Collections.UnmodifiableNavigableSet + testWrapping((NavigableSet<?>) treeSet, Collections::unmodifiableNavigableSet); + + } + + public void testUnmodifiableMapsDontWrap() { + TreeMap<?,?> treeMap = new TreeMap<>(); + + List<Map<?,?>> maps = List.of(treeMap, + Map.of(1,1), + Map.of(1, 1, 2, 2, 3, 3, 4, 4)); + + for (Map<?,?> map : maps) { + testWrapping(map, Collections::unmodifiableMap); + } + + //Collections.UnModifiableSortedMap + testWrapping((SortedMap<?,?>) treeMap, Collections::unmodifiableSortedMap); + + //Collections.UnModifiableNavigableMap + testWrapping((NavigableMap<?,?>) treeMap, Collections::unmodifiableNavigableMap); + + } + +} diff --git a/ojluni/src/test/java/util/Collections/Wrappers.java b/ojluni/src/test/java/util/Collections/Wrappers.java new file mode 100644 index 00000000000..5b8aff4d3f7 --- /dev/null +++ b/ojluni/src/test/java/util/Collections/Wrappers.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2013, 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 + * @run testng Wrappers + * @summary Ensure Collections wrapping classes provide non-default implementations + */ + +package test.java.util.Collections; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.TreeMap; +import java.util.TreeSet; + +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; + +import static org.testng.Assert.assertFalse; + +@Test(groups = "unit") +public class Wrappers { + static Object[][] collections; + + @DataProvider(name="collections") + public static Object[][] collectionCases() { + if (collections != null) { + return collections; + } + + List<Object[]> cases = new ArrayList<>(); + LinkedList<Integer> seedList = new LinkedList<>(); + ArrayList<Integer> seedRandomAccess = new ArrayList<>(); + TreeSet<Integer> seedSet = new TreeSet<>(); + TreeMap<Integer, Integer> seedMap = new TreeMap<>(); + + for (int i = 1; i <= 10; i++) { + seedList.add(i); + seedRandomAccess.add(i); + seedSet.add(i); + seedMap.put(i, i); + } + + cases.add(new Object[] { Collections.unmodifiableCollection(seedList) }); + cases.add(new Object[] { Collections.unmodifiableList(seedList) }); + cases.add(new Object[] { Collections.unmodifiableList(seedRandomAccess) }); + cases.add(new Object[] { Collections.unmodifiableSet(seedSet) }); + cases.add(new Object[] { Collections.unmodifiableSortedSet(seedSet) }); + cases.add(new Object[] { Collections.unmodifiableNavigableSet(seedSet) }); + + // As sets from map also need to be unmodifiable, thus a wrapping + // layer exist and should not have default methods + cases.add(new Object[] { Collections.unmodifiableMap(seedMap).entrySet() }); + cases.add(new Object[] { Collections.unmodifiableMap(seedMap).keySet() }); + cases.add(new Object[] { Collections.unmodifiableMap(seedMap).values() }); + cases.add(new Object[] { Collections.unmodifiableSortedMap(seedMap).entrySet() }); + cases.add(new Object[] { Collections.unmodifiableSortedMap(seedMap).keySet() }); + cases.add(new Object[] { Collections.unmodifiableSortedMap(seedMap).values() }); + cases.add(new Object[] { Collections.unmodifiableNavigableMap(seedMap).entrySet() }); + cases.add(new Object[] { Collections.unmodifiableNavigableMap(seedMap).keySet() }); + cases.add(new Object[] { Collections.unmodifiableNavigableMap(seedMap).values() }); + + // Synchronized + cases.add(new Object[] { Collections.synchronizedCollection(seedList) }); + cases.add(new Object[] { Collections.synchronizedList(seedList) }); + cases.add(new Object[] { Collections.synchronizedList(seedRandomAccess) }); + cases.add(new Object[] { Collections.synchronizedSet(seedSet) }); + cases.add(new Object[] { Collections.synchronizedSortedSet(seedSet) }); + cases.add(new Object[] { Collections.synchronizedNavigableSet(seedSet) }); + + // As sets from map also need to be synchronized on the map, thus a + // wrapping layer exist and should not have default methods + cases.add(new Object[] { Collections.synchronizedMap(seedMap).entrySet() }); + cases.add(new Object[] { Collections.synchronizedMap(seedMap).keySet() }); + cases.add(new Object[] { Collections.synchronizedMap(seedMap).values() }); + cases.add(new Object[] { Collections.synchronizedSortedMap(seedMap).entrySet() }); + cases.add(new Object[] { Collections.synchronizedSortedMap(seedMap).keySet() }); + cases.add(new Object[] { Collections.synchronizedSortedMap(seedMap).values() }); + cases.add(new Object[] { Collections.synchronizedNavigableMap(seedMap).entrySet() }); + cases.add(new Object[] { Collections.synchronizedNavigableMap(seedMap).keySet() }); + cases.add(new Object[] { Collections.synchronizedNavigableMap(seedMap).values() }); + + // Checked + cases.add(new Object[] { Collections.checkedCollection(seedList, Integer.class) }); + cases.add(new Object[] { Collections.checkedList(seedList, Integer.class) }); + cases.add(new Object[] { Collections.checkedList(seedRandomAccess, Integer.class) }); + cases.add(new Object[] { Collections.checkedSet(seedSet, Integer.class) }); + cases.add(new Object[] { Collections.checkedSortedSet(seedSet, Integer.class) }); + cases.add(new Object[] { Collections.checkedNavigableSet(seedSet, Integer.class) }); + cases.add(new Object[] { Collections.checkedQueue(seedList, Integer.class) }); + + // asLifoQueue is another wrapper + cases.add(new Object[] { Collections.asLifoQueue(seedList) }); + + collections = cases.toArray(new Object[0][]); + return collections; + } + + static Method[] defaultMethods; + + static { + List<Method> list = new ArrayList<>(); + Method[] methods = Collection.class.getMethods(); + for (Method m: methods) { + if (m.isDefault()) { + list.add(m); + } + } + defaultMethods = list.toArray(new Method[0]); + } + + @Test(dataProvider = "collections") + public static void testAllDefaultMethodsOverridden(Collection c) throws NoSuchMethodException { + Class cls = c.getClass(); + for (Method m: defaultMethods) { + Method m2 = cls.getMethod(m.getName(), m.getParameterTypes()); + // default had been override + assertFalse(m2.isDefault(), cls.getCanonicalName()); + } + } +} + diff --git a/ojluni/src/test/java/util/HexFormat/HexFormatTest.java b/ojluni/src/test/java/util/HexFormat/HexFormatTest.java index ce9dc42375e..4009a9f9fac 100644 --- a/ojluni/src/test/java/util/HexFormat/HexFormatTest.java +++ b/ojluni/src/test/java/util/HexFormat/HexFormatTest.java @@ -48,6 +48,8 @@ import static org.testng.Assert.expectThrows; */ @Test +// Android-changed: test methods are changed to public. static package private methods +// are not picked by the test runner. public class HexFormatTest { static final Class<NullPointerException> NPE = NullPointerException.class; @@ -140,7 +142,7 @@ public class HexFormatTest { } @Test - static void testToHex() { + public void testToHex() { HexFormat hex = HexFormat.of(); for (int i = 0; i < 32; i++) { char c = hex.toLowHexDigit((byte)i); @@ -150,7 +152,7 @@ public class HexFormatTest { } @Test - static void testToHexDigits() { + public void testToHexDigits() { HexFormat hex = HexFormat.of(); for (int i = 0; i < 256; i++) { String actual = hex.toHexDigits((byte)i); @@ -164,7 +166,7 @@ public class HexFormatTest { } @Test - static void testIsHexDigit() { + public void testIsHexDigit() { for (int i = 0; i < 0x3ff; i++) { boolean actual = HexFormat.isHexDigit(i); boolean expected = Character.digit(i, 16) >= 0; @@ -173,7 +175,7 @@ public class HexFormatTest { } @Test - static void testFromHexDigit() { + public void testFromHexDigit() { String chars = "0123456789ABCDEF0123456789abcdef"; for (int i = 0; i < chars.length(); i++) { int v = HexFormat.fromHexDigit(chars.charAt(i)); @@ -182,7 +184,7 @@ public class HexFormatTest { } @Test - static void testFromHexInvalid() { + public void testFromHexInvalid() { for (int i = 0; i < 65536; i++) { char ch = (char)i; if (ch > 0xff || Character.digit(ch, 16) < 0) { @@ -195,7 +197,7 @@ public class HexFormatTest { } @Test - static void testAppendHexByteWithStringBuilder() { + public void testAppendHexByteWithStringBuilder() { HexFormat hex = HexFormat.of(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 256; i++) { @@ -223,7 +225,7 @@ public class HexFormatTest { } @Test - static void testAppendHexByteWithCharArrayWriter() { + public void testAppendHexByteWithCharArrayWriter() { HexFormat hex = HexFormat.of(); CharArrayWriter caw = new CharArrayWriter(); for (int i = 1; i <= 128; i++) { @@ -234,7 +236,7 @@ public class HexFormatTest { } @Test - static void testFromHexPairInvalid() { + public void testFromHexPairInvalid() { HexFormat hex = HexFormat.of(); // An assortment of invalid characters @@ -248,7 +250,7 @@ public class HexFormatTest { } @Test(dataProvider = "HexStringsThrowing") - static void testToBytesThrowing(String value, String sep, String prefix, String suffix) { + public void testToBytesThrowing(String value, String sep, String prefix, String suffix) { HexFormat hex = HexFormat.ofDelimiter(sep).withPrefix(prefix).withSuffix(suffix); Throwable ex = expectThrows(IllegalArgumentException.class, () -> { @@ -260,7 +262,7 @@ public class HexFormatTest { } @Test - static void testFactoryNPE() { + public void testFactoryNPE() { assertThrows(NPE, () -> HexFormat.ofDelimiter(null)); assertThrows(NPE, () -> HexFormat.of().withDelimiter(null)); assertThrows(NPE, () -> HexFormat.of().withPrefix(null)); @@ -268,7 +270,7 @@ public class HexFormatTest { } @Test - static void testFormatHexNPE() { + public void testFormatHexNPE() { assertThrows(NPE, () -> HexFormat.of().formatHex(null)); assertThrows(NPE, () -> HexFormat.of().formatHex(null, 0, 1)); assertThrows(NPE, () -> HexFormat.of().formatHex(null, null)); @@ -279,14 +281,14 @@ public class HexFormatTest { } @Test - static void testParseHexNPE() { + public void testParseHexNPE() { assertThrows(NPE, () -> HexFormat.of().parseHex(null)); assertThrows(NPE, () -> HexFormat.of().parseHex((String)null, 0, 0)); assertThrows(NPE, () -> HexFormat.of().parseHex((char[])null, 0, 0)); } @Test - static void testFromHexNPE() { + public void testFromHexNPE() { assertThrows(NPE, () -> HexFormat.fromHexDigits(null)); assertThrows(NPE, () -> HexFormat.fromHexDigits(null, 0, 0)); assertThrows(NPE, () -> HexFormat.fromHexDigitsToLong(null)); @@ -294,12 +296,12 @@ public class HexFormatTest { } @Test - static void testToHexDigitsNPE() { + public void testToHexDigitsNPE() { assertThrows(NPE, () -> HexFormat.of().toHexDigits(null, (byte)0)); } @Test(dataProvider = "BadParseHexThrowing") - static void badParseHex(String string, int offset, int length, + public void badParseHex(String string, int offset, int length, Class<? extends Throwable> exClass) { assertThrows(exClass, () -> HexFormat.of().parseHex(string, offset, length)); @@ -309,7 +311,7 @@ public class HexFormatTest { } @Test(dataProvider = "BadFromHexDigitsThrowing") - static void badFromHexDigits(String string, int fromIndex, int toIndex, + public void badFromHexDigits(String string, int fromIndex, int toIndex, Class<? extends Throwable> exClass) { assertThrows(exClass, () -> HexFormat.fromHexDigits(string, fromIndex, toIndex)); @@ -320,7 +322,7 @@ public class HexFormatTest { // Verify IAE for strings that are too long for the target primitive type // or the number of requested digits is too large. @Test - static void wrongNumberDigits() { + public void wrongNumberDigits() { assertThrows(IllegalArgumentException.class, () -> HexFormat.fromHexDigits("9876543210")); assertThrows(IllegalArgumentException.class, @@ -332,7 +334,7 @@ public class HexFormatTest { } @Test(dataProvider="HexFormattersParsers") - static void testFormatter(String delimiter, String prefix, String suffix, + public void testFormatter(String delimiter, String prefix, String suffix, boolean uppercase, HexFormat hex) { byte[] expected = genBytes('A', 15); @@ -367,7 +369,7 @@ public class HexFormatTest { } @Test(dataProvider="HexFormattersParsers") - static void testFormatHexString(String unused1, String unused2, String unused3, + public void testFormatHexString(String unused1, String unused2, String unused3, boolean unused4, HexFormat hex) { byte[] expected = genBytes('A', 15); String s = hex.formatHex(expected); @@ -380,7 +382,7 @@ public class HexFormatTest { } @Test(dataProvider="HexFormattersParsers") - static void testParseHexStringRange(String delimiter, String prefix, String suffix, + public void testParseHexStringRange(String delimiter, String prefix, String suffix, boolean unused4, HexFormat hex) { byte[] expected = genBytes('A', 15); String s = hex.formatHex(expected); @@ -401,7 +403,7 @@ public class HexFormatTest { } @Test(dataProvider="HexFormattersParsers") - static void testParseHexEmptyString(String delimiter, String prefix, String suffix, + public void testParseHexEmptyString(String delimiter, String prefix, String suffix, boolean unused4, HexFormat hex) { byte[] actual = hex.parseHex(""); assertEquals(actual.length, 0, "empty string parse"); @@ -412,7 +414,7 @@ public class HexFormatTest { } @Test(dataProvider="HexFormattersParsers") - static void testFormatHexRangeString(String unused1, String unused2, String unused3, + public void testFormatHexRangeString(String unused1, String unused2, String unused3, boolean unused4, HexFormat hex) { byte[] expected = genBytes('A', 15); int low = 1; @@ -427,7 +429,7 @@ public class HexFormatTest { } @Test(dataProvider="HexFormattersParsers") - static void testFormatHexAppendable(String unused1, String unused2, String unused3, + public void testFormatHexAppendable(String unused1, String unused2, String unused3, boolean unused4, HexFormat hex) { byte[] expected = genBytes('A', 15); StringBuilder sb = new StringBuilder(); @@ -442,7 +444,7 @@ public class HexFormatTest { } @Test(dataProvider="HexFormattersParsers") - static void testFormatHexRangeAppendable(String unused1, String unused2, String unused3, + public void testFormatHexRangeAppendable(String unused1, String unused2, String unused3, boolean unused4, HexFormat hex) { byte[] expected = genBytes('A', 15); int low = 1; @@ -464,7 +466,7 @@ public class HexFormatTest { } @Test(dataProvider="HexFormattersParsers") - static void testFormatHexCharArray(String unused1, String unused2, String unused3, + public void testFormatHexCharArray(String unused1, String unused2, String unused3, boolean unused4, HexFormat hex) { byte[] expected = genBytes('A', 15); String s = hex.formatHex(expected); @@ -478,7 +480,7 @@ public class HexFormatTest { } @Test(dataProvider="HexFormattersParsers") - static void testFormatHexCharArrayIndexed(String delimiter, String prefix, String suffix, + public void testFormatHexCharArrayIndexed(String delimiter, String prefix, String suffix, boolean unused4, HexFormat hex) { byte[] expected = genBytes('A', 15); String s = hex.formatHex(expected); @@ -502,7 +504,7 @@ public class HexFormatTest { } @Test(dataProvider="HexFormattersParsers") - static void testFormatterToString(String delimiter, String prefix, String suffix, + public void testFormatterToString(String delimiter, String prefix, String suffix, boolean uppercase, HexFormat hex) { String actual = String.format( @@ -513,7 +515,7 @@ public class HexFormatTest { } @Test(dataProvider="HexFormattersParsers") - static void testFormatterParameterMethods(String delimiter, String prefix, String suffix, + public void testFormatterParameterMethods(String delimiter, String prefix, String suffix, boolean uppercase, HexFormat hex) { assertEquals(hex.delimiter(), delimiter); @@ -523,7 +525,7 @@ public class HexFormatTest { } @Test(dataProvider="HexFormattersParsers") - static void testFormatterTestEquals(String delimiter, String prefix, String suffix, + public void testFormatterTestEquals(String delimiter, String prefix, String suffix, boolean uppercase, HexFormat expected) { HexFormat actual = HexFormat.of() @@ -544,7 +546,7 @@ public class HexFormatTest { } @Test(dataProvider="HexFormattersParsers") - static void testZeroLength(String delimiter, String prefix, String suffix, boolean uppercase, + public void testZeroLength(String delimiter, String prefix, String suffix, boolean uppercase, HexFormat hex) { // Test formatting of zero length byte arrays, should produce no output StringBuilder sb = new StringBuilder(); @@ -563,7 +565,7 @@ public class HexFormatTest { } @Test - static void testfromHexDigitsToInt() { + public void testfromHexDigitsToInt() { HexFormat hex = HexFormat.of(); String allHex = "76543210"; @@ -580,7 +582,7 @@ public class HexFormatTest { } @Test - static void testfromHexDigitsToLong() { + public void testfromHexDigitsToLong() { HexFormat hex = HexFormat.of(); String allHex = "fedcba9876543210"; @@ -597,7 +599,7 @@ public class HexFormatTest { } @Test - static void testToHexDigitsLong() { + public void testToHexDigitsLong() { HexFormat hex = HexFormat.of(); String allHex = "fedcba9876543210"; @@ -610,7 +612,7 @@ public class HexFormatTest { } @Test(dataProvider="HexFormattersParsers") - static void testIOException(String delimiter, String prefix, String suffix, boolean uppercase, + public void testIOException(String delimiter, String prefix, String suffix, boolean uppercase, HexFormat hex) { Appendable throwingAppendable = new ThrowingAppendable(); assertThrows(UncheckedIOException.class, @@ -622,7 +624,7 @@ public class HexFormatTest { } @Test(dataProvider="HexFormattersParsers") - static void testOOME(String delimiter, String prefix, String suffix, boolean uppercase, + public void testOOME(String delimiter, String prefix, String suffix, boolean uppercase, HexFormat hex) { // compute the size of byte array that will exceed the buffer long valueChars = prefix.length() + 2 + suffix.length(); @@ -656,7 +658,7 @@ public class HexFormatTest { * The additional TestNG asserts verify the correctness of the same code. */ @Test - private static void samples() { + public void samples() { { // Primitive formatting and parsing. HexFormat hex = HexFormat.of(); diff --git a/ojluni/src/test/java/util/PriorityQueue/AddNonComparable.java b/ojluni/src/test/java/util/PriorityQueue/AddNonComparable.java index 3adf7f3255e..1b22ac0f74e 100644 --- a/ojluni/src/test/java/util/PriorityQueue/AddNonComparable.java +++ b/ojluni/src/test/java/util/PriorityQueue/AddNonComparable.java @@ -46,6 +46,11 @@ import java.util.function.Supplier; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; +import android.compat.Compatibility; + +import dalvik.annotation.compat.VersionCodes; +import dalvik.system.VMRuntime; + public class AddNonComparable { static <E> void test(Queue<E> queue, Supplier<E> supplier, @@ -58,11 +63,23 @@ public class AddNonComparable { @Test public void queues() { - test(new PriorityQueue<>(), NonComparable::new, - (q, e) -> { - assertEquals(q.size(), 0); - assertTrue(e instanceof ClassCastException); - }); + // Android-added: test old behavior in < U. + boolean testPreAndroidUBehavior = VMRuntime.getSdkVersion() < VersionCodes.UPSIDE_DOWN_CAKE + || !Compatibility.isChangeEnabled(PriorityQueue.PRIORITY_QUEUE_OFFER_NON_COMPARABLE_ONE_ELEMENT); + + if (testPreAndroidUBehavior) { + test(new PriorityQueue<>(), NonComparable::new, + (q, e) -> { + assertEquals(q.size(), 1); + assertTrue(e == null); + }); + } else { + test(new PriorityQueue<>(), NonComparable::new, + (q, e) -> { + assertEquals(q.size(), 0); + assertTrue(e instanceof ClassCastException); + }); + } test(new PriorityQueue<>(), AComparable::new, (q, e) -> { assertEquals(q.size(), 1); diff --git a/ojluni/src/test/java/util/WeakHashMap/GCDuringIteration.java b/ojluni/src/test/java/util/WeakHashMap/GCDuringIteration.java new file mode 100644 index 00000000000..ad9a55ba1d7 --- /dev/null +++ b/ojluni/src/test/java/util/WeakHashMap/GCDuringIteration.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2007, 2017, 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 6499848 + * @library /test/lib + * @build jdk.test.lib.RandomFactory + * @run main GCDuringIteration + * @summary Check that iterators work properly in the presence of + * concurrent finalization and removal of elements. + * @key randomness + */ + +package test.java.util.WeakHashMap; + +import jdk.test.lib.RandomFactory; + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Random; +import java.util.WeakHashMap; +import java.util.concurrent.CountDownLatch; +import java.util.function.BooleanSupplier; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +public class GCDuringIteration { + + /** No guarantees, but effective in practice. */ + static void forceFullGc() { + long timeoutMillis = 1000L; + CountDownLatch finalized = new CountDownLatch(1); + ReferenceQueue<Object> queue = new ReferenceQueue<>(); + WeakReference<Object> ref = new WeakReference<>( + new Object() { protected void finalize() { finalized.countDown(); }}, + queue); + try { + for (int tries = 3; tries--> 0; ) { + // Android-changed: Runtime.getRuntime().gc() requires more iterations and + // takes significantly longer to finish. + // System.gc(); + Runtime.getRuntime().gc(); + if (finalized.await(timeoutMillis, MILLISECONDS) + && queue.remove(timeoutMillis) != null + && ref.get() == null) { + System.runFinalization(); // try to pick up stragglers + return; + } + timeoutMillis *= 4; + } + } catch (InterruptedException unexpected) { + throw new AssertionError("unexpected InterruptedException"); + } + throw new AssertionError("failed to do a \"full\" gc"); + } + + static void gcAwait(BooleanSupplier s) { + for (int i = 0; i < 10; i++) { + if (s.getAsBoolean()) + return; + forceFullGc(); + } + throw new AssertionError("failed to satisfy condition"); + } + + // A class with the traditional pessimal hashCode implementation, + // to ensure that all instances end up in the same bucket. + static class Foo { public int hashCode() { return 42; }} + + <K,V> void put(Map<K,V> map, K k, V v) { + check(! map.containsKey(k)); + equal(map.get(k), null); + equal(map.put(k, v), null); + equal(map.get(k), v); + check(map.containsKey(k)); + equal(map.put(k, v), v); + equal(map.get(k), v); + check(map.containsKey(k)); + check(! map.isEmpty()); + equal(map.keySet().iterator().next(), k); + equal(map.values().iterator().next(), v); + } + + static final Random rnd = RandomFactory.getRandom(); + + void checkIterator(final Iterator<Map.Entry<Foo, Integer>> it, int first) { + for (int i = first; i >= 0; --i) { + if (rnd.nextBoolean()) check(it.hasNext()); + equal(it.next().getValue(), i); + } + if (rnd.nextBoolean()) { + try { + it.next(); + throw new AssertionError("should throw"); + } catch (NoSuchElementException success) {} + } + + if (rnd.nextBoolean()) + check(! it.hasNext()); + } + + <K,V> V firstValue(Map<K,V> map) { + return map.values().iterator().next(); + } + + void test(String[] args) throws Throwable { + final int n = 10; + // Create array of strong refs + final Foo[] foos = new Foo[2*n]; + final Map<Foo,Integer> map = new WeakHashMap<>(foos.length); + check(map.isEmpty()); + equal(map.size(), 0); + + for (int i = 0; i < foos.length; i++) { + Foo foo = new Foo(); + foos[i] = foo; + put(map, foo, i); + } + equal(map.size(), foos.length); + + { + int first = firstValue(map); + final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator(); + foos[first] = null; + gcAwait(() -> map.size() == first); + checkIterator(it, first-1); + equal(map.size(), first); + equal(firstValue(map), first-1); + } + + { + int first = firstValue(map); + final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator(); + it.next(); // protects first entry + System.out.println(map.values()); + int oldSize = map.size(); + foos[first] = null; + forceFullGc(); + equal(map.size(), oldSize); + System.out.println(map.values()); + checkIterator(it, first-1); + // first entry no longer protected + gcAwait(() -> map.size() == first); + equal(firstValue(map), first-1); + } + + { + int first = firstValue(map); + final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator(); + it.next(); // protects first entry + System.out.println(map.values()); + foos[first] = foos[first-1] = null; + gcAwait(() -> map.size() == first); + equal(firstValue(map), first); + System.out.println(map.values()); + checkIterator(it, first-2); + // first entry no longer protected + gcAwait(() -> map.size() == first-1); + equal(firstValue(map), first-2); + } + + { + int first = firstValue(map); + final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator(); + it.next(); // protects first entry + it.hasNext(); // protects second entry + System.out.println(map.values()); + int oldSize = map.size(); + foos[first] = foos[first-1] = null; + forceFullGc(); + equal(map.size(), oldSize); + equal(firstValue(map), first); + System.out.println(map.values()); + checkIterator(it, first-1); + // first entry no longer protected + gcAwait(() -> map.size() == first-1); + equal(firstValue(map), first-2); + } + + { + int first = firstValue(map); + final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator(); + it.next(); // protects first entry + System.out.println(map.values()); + equal(map.size(), first+1); + foos[first] = foos[first-1] = null; + gcAwait(() -> map.size() == first); + it.remove(); + equal(firstValue(map), first-2); + equal(map.size(), first-1); + System.out.println(map.values()); + checkIterator(it, first-2); + // first entry no longer protected + gcAwait(() -> map.size() == first-1); + equal(firstValue(map), first-2); + } + + { + int first = firstValue(map); + final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator(); + it.next(); // protects first entry + it.remove(); + it.hasNext(); // protects second entry + System.out.println(map.values()); + equal(map.size(), first); + foos[first] = foos[first-1] = null; + forceFullGc(); + equal(firstValue(map), first-1); + equal(map.size(), first); + System.out.println(map.values()); + checkIterator(it, first-1); + gcAwait(() -> map.size() == first-1); + equal(firstValue(map), first-2); + } + + { + int first = firstValue(map); + final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator(); + it.hasNext(); // protects first entry + Arrays.fill(foos, null); + gcAwait(() -> map.size() == 1); + System.out.println(map.values()); + equal(it.next().getValue(), first); + check(! it.hasNext()); + gcAwait(() -> map.size() == 0); + check(map.isEmpty()); + } + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new GCDuringIteration().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/ojluni/src/test/java/util/WeakHashMap/Iteration.java b/ojluni/src/test/java/util/WeakHashMap/Iteration.java new file mode 100644 index 00000000000..309e7cd15c5 --- /dev/null +++ b/ojluni/src/test/java/util/WeakHashMap/Iteration.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2001, 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 4236533 4416923 + * @summary Tests to see that memory leak no longer exists. + * @author Josh Bloch + */ + +package test.java.util.WeakHashMap; + +import java.util.Iterator; +import java.util.Map; +import java.util.WeakHashMap; + +public class Iteration { + public static void main(String[] args) { + String s = "iatrogenic"; + Map m = new WeakHashMap(); + m.put(s, "cucumber"); + Iterator i = m.keySet().iterator(); + if (i.hasNext() != i.hasNext()) + throw new RuntimeException("hasNext advances iterator"); + } +} diff --git a/ojluni/src/test/java/util/WeakHashMap/ZeroInitCap.java b/ojluni/src/test/java/util/WeakHashMap/ZeroInitCap.java new file mode 100644 index 00000000000..92b4ebdec18 --- /dev/null +++ b/ojluni/src/test/java/util/WeakHashMap/ZeroInitCap.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2001, 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. + */ + +package test.java.util.WeakHashMap; + +import java.util.Map; +import java.util.WeakHashMap; + +/* + * @test + * @bug 4503146 + * @summary Zero initial capacity should be legal + * @author Josh Bloch + */ + +public class ZeroInitCap { + public static void main(String[] args) { + Map map = new WeakHashMap(0); + map.put("a","b"); + } +} diff --git a/ojluni/src/test/java/util/concurrent/tck/CollectionTest.java b/ojluni/src/test/java/util/concurrent/tck/CollectionTest.java index 2f3943ab7bd..8ec9b01afa5 100644 --- a/ojluni/src/test/java/util/concurrent/tck/CollectionTest.java +++ b/ojluni/src/test/java/util/concurrent/tck/CollectionTest.java @@ -48,6 +48,10 @@ public class CollectionTest extends JSR166TestCase { } public static Test testSuite(CollectionImplementation impl) { + // Android-changed: Ignore CollectionTest. http://b/285113029 + // This method apparently creates a new test suite without a test case, + // e.g. testCollectionDebugFail() is commented out. + /* return newTestSuite (parameterizedTestSuite(CollectionTest.class, CollectionImplementation.class, @@ -55,6 +59,9 @@ public class CollectionTest extends JSR166TestCase { jdk8ParameterizedTestSuite(CollectionTest.class, CollectionImplementation.class, impl)); + + */ + return null; } // public void testCollectionDebugFail() { diff --git a/ojluni/src/test/java/util/concurrent/tck/JSR166TestCase.java b/ojluni/src/test/java/util/concurrent/tck/JSR166TestCase.java index 475edf9b871..62d293cc87b 100644 --- a/ojluni/src/test/java/util/concurrent/tck/JSR166TestCase.java +++ b/ojluni/src/test/java/util/concurrent/tck/JSR166TestCase.java @@ -426,6 +426,11 @@ public class JSR166TestCase extends TestCase { public static TestSuite newTestSuite(Object... suiteOrClasses) { TestSuite suite = new TestSuite(); for (Object suiteOrClass : suiteOrClasses) { + // Android-added: Ignore null and CollectionTest. http://b/285113029 + if (suiteOrClass == null) { + continue; + } + if (suiteOrClass instanceof TestSuite) suite.addTest((TestSuite) suiteOrClass); else if (suiteOrClass instanceof Class) diff --git a/ojluni/src/test/java/util/concurrent/tck/PriorityQueueTest.java b/ojluni/src/test/java/util/concurrent/tck/PriorityQueueTest.java index 072abac2188..b7f2e9fc23c 100644 --- a/ojluni/src/test/java/util/concurrent/tck/PriorityQueueTest.java +++ b/ojluni/src/test/java/util/concurrent/tck/PriorityQueueTest.java @@ -45,6 +45,11 @@ import java.util.Queue; import junit.framework.Test; import junit.framework.TestSuite; +import android.compat.Compatibility; + +import dalvik.annotation.compat.VersionCodes; +import dalvik.system.VMRuntime; + public class PriorityQueueTest extends JSR166TestCase { public static void main(String[] args) { main(suite(), args); @@ -226,10 +231,16 @@ public class PriorityQueueTest extends JSR166TestCase { */ public void testOfferNonComparable() { PriorityQueue q = new PriorityQueue(1); + // Android-added: test old behavior in < U. + boolean preAndroidUBehavior = VMRuntime.getSdkVersion() < VersionCodes.UPSIDE_DOWN_CAKE + || !Compatibility.isChangeEnabled(PriorityQueue.PRIORITY_QUEUE_OFFER_NON_COMPARABLE_ONE_ELEMENT); try { q.offer(new Object()); - shouldThrow(); + if (!preAndroidUBehavior) { + shouldThrow(); + } } catch (ClassCastException success) { + assertFalse(preAndroidUBehavior); assertTrue(q.isEmpty()); assertEquals(0, q.size()); assertNull(q.poll()); diff --git a/ojluni/src/test/java/util/regex/PatternStreamTest.java b/ojluni/src/test/java/util/regex/PatternStreamTest.java index edbd0541c98..5a6d06b3dbb 100644 --- a/ojluni/src/test/java/util/regex/PatternStreamTest.java +++ b/ojluni/src/test/java/util/regex/PatternStreamTest.java @@ -32,9 +32,11 @@ package test.java.util.regex; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static org.testng.Assert.*; +import android.compat.Compatibility; +import dalvik.annotation.compat.VersionCodes; +import dalvik.system.VMRuntime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -50,15 +52,8 @@ import java.util.stream.Stream; import org.openjdk.testlib.java.util.stream.LambdaTestHelpers; import org.openjdk.testlib.java.util.stream.OpTestCase; import org.openjdk.testlib.java.util.stream.TestData; - -import static org.testng.Assert.*; - -import static java.util.regex.Pattern.SPLIT_AS_STREAM_RETURNS_SINGLE_EMPTY_STRING; - -import android.compat.Compatibility; - -import dalvik.annotation.compat.VersionCodes; -import dalvik.system.VMRuntime; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; @Test public class PatternStreamTest extends OpTestCase { @@ -147,11 +142,11 @@ public class PatternStreamTest extends OpTestCase { // Derive expected result from pattern.split List<String> expected = Arrays.asList(pattern.split(input)); - // Android-added: Keep old behavior on Android 13 or below. http://b/286499139 - if(input.isEmpty() - && !(VMRuntime.getSdkVersion() >= VersionCodes.UPSIDE_DOWN_CAKE - && Compatibility.isChangeEnabled( - Pattern.SPLIT_AS_STREAM_RETURNS_SINGLE_EMPTY_STRING))) { + // Android-added: Keep old behavior on Android 13 or below. http://b/286499139 + if (input.isEmpty() + && !(VMRuntime.getSdkVersion() > VersionCodes.TIRAMISU + && Compatibility.isChangeEnabled( + Pattern.SPLIT_AS_STREAM_RETURNS_SINGLE_EMPTY_STRING))) { expected = Collections.emptyList(); } diff --git a/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/SpliteratorOfIntDataBuilder.java b/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/SpliteratorOfIntDataBuilder.java new file mode 100644 index 00000000000..9c1866c737f --- /dev/null +++ b/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/SpliteratorOfIntDataBuilder.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017, 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. + */ + +package org.openjdk.testlib.java.util; + +import java.util.function.Supplier; +import java.util.*; + +public class SpliteratorOfIntDataBuilder { + List<Object[]> data; + + List<Integer> exp; + + public SpliteratorOfIntDataBuilder(List<Object[]> data, List<Integer> exp) { + this.data = data; + this.exp = exp; + } + + public void add(String description, List<Integer> expected, Supplier<Spliterator.OfInt> s) { + description = joiner(description).toString(); + data.add(new Object[]{description, expected, s}); + } + + public void add(String description, Supplier<Spliterator.OfInt> s) { + add(description, exp, s); + } + + StringBuilder joiner(String description) { + return new StringBuilder(description). + append(" {"). + append("size=").append(exp.size()). + append("}"); + } + } + diff --git a/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/SpliteratorTestHelper.java b/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/SpliteratorTestHelper.java new file mode 100644 index 00000000000..fd3f0b2e2fe --- /dev/null +++ b/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/SpliteratorTestHelper.java @@ -0,0 +1,755 @@ +/* + * Copyright (c) 2012, 2017, 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. + */ +package org.openjdk.testlib.java.util; + +import java.util.function.*; +import org.openjdk.testlib.java.util.stream.LambdaTestHelpers; +import java.util.*; + +import static org.testng.Assert.*; + +/** + * Assertion methods for spliterators, to be called from other tests + */ +public class SpliteratorTestHelper { + + public interface ContentAsserter<T> { + void assertContents(Collection<T> actual, Collection<T> expected, boolean isOrdered); + } + + private static ContentAsserter<Object> DEFAULT_CONTENT_ASSERTER + = SpliteratorTestHelper::assertContents; + + @SuppressWarnings("unchecked") + private static <T> ContentAsserter<T> defaultContentAsserter() { + return (ContentAsserter<T>) DEFAULT_CONTENT_ASSERTER; + } + + public static void testSpliterator(Supplier<Spliterator<Integer>> supplier) { + testSpliterator(supplier, defaultContentAsserter()); + } + + public static void testSpliterator(Supplier<Spliterator<Integer>> supplier, + ContentAsserter<Integer> asserter) { + testSpliterator(supplier, (Consumer<Integer> b) -> b, asserter); + } + + public static void testIntSpliterator(Supplier<Spliterator.OfInt> supplier) { + testIntSpliterator(supplier, defaultContentAsserter()); + } + + public static void testIntSpliterator(Supplier<Spliterator.OfInt> supplier, + ContentAsserter<Integer> asserter) { + testSpliterator(supplier, intBoxingConsumer(), asserter); + } + + public static void testLongSpliterator(Supplier<Spliterator.OfLong> supplier) { + testLongSpliterator(supplier, defaultContentAsserter()); + } + + public static void testLongSpliterator(Supplier<Spliterator.OfLong> supplier, + ContentAsserter<Long> asserter) { + testSpliterator(supplier, longBoxingConsumer(), asserter); + } + + public static void testDoubleSpliterator(Supplier<Spliterator.OfDouble> supplier) { + testDoubleSpliterator(supplier, defaultContentAsserter()); + } + + public static void testDoubleSpliterator(Supplier<Spliterator.OfDouble> supplier, + ContentAsserter<Double> asserter) { + testSpliterator(supplier, doubleBoxingConsumer(), asserter); + } + + public static UnaryOperator<Consumer<Integer>> intBoxingConsumer() { + class BoxingAdapter implements Consumer<Integer>, IntConsumer { + private final Consumer<Integer> b; + + BoxingAdapter(Consumer<Integer> b) { + this.b = b; + } + + @Override + public void accept(Integer value) { + throw new IllegalStateException(); + } + + @Override + public void accept(int value) { + b.accept(value); + } + } + + return b -> new BoxingAdapter(b); + } + + public static UnaryOperator<Consumer<Long>> longBoxingConsumer() { + class BoxingAdapter implements Consumer<Long>, LongConsumer { + private final Consumer<Long> b; + + BoxingAdapter(Consumer<Long> b) { + this.b = b; + } + + @Override + public void accept(Long value) { + throw new IllegalStateException(); + } + + @Override + public void accept(long value) { + b.accept(value); + } + } + + return b -> new BoxingAdapter(b); + } + + public static UnaryOperator<Consumer<Double>> doubleBoxingConsumer() { + class BoxingAdapter implements Consumer<Double>, DoubleConsumer { + private final Consumer<Double> b; + + BoxingAdapter(Consumer<Double> b) { + this.b = b; + } + + @Override + public void accept(Double value) { + throw new IllegalStateException(); + } + + @Override + public void accept(double value) { + b.accept(value); + } + } + + return b -> new BoxingAdapter(b); + } + + public static <T, S extends Spliterator<T>> void testSpliterator(Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter, + ContentAsserter<T> asserter) { + ArrayList<T> fromForEach = new ArrayList<>(); + Spliterator<T> spliterator = supplier.get(); + Consumer<T> addToFromForEach = boxingAdapter.apply(fromForEach::add); + spliterator.forEachRemaining(addToFromForEach); + + Collection<T> exp = Collections.unmodifiableList(fromForEach); + + testNullPointerException(supplier); + testForEach(exp, supplier, boxingAdapter, asserter); + testTryAdvance(exp, supplier, boxingAdapter, asserter); + testMixedTryAdvanceForEach(exp, supplier, boxingAdapter, asserter); + testMixedTraverseAndSplit(exp, supplier, boxingAdapter, asserter); + testSplitAfterFullTraversal(supplier, boxingAdapter); + testSplitOnce(exp, supplier, boxingAdapter, asserter); + testSplitSixDeep(exp, supplier, boxingAdapter, asserter); + testSplitUntilNull(exp, supplier, boxingAdapter, asserter); + } + + public static <T, S extends Spliterator<T>> void testForEach( + Collection<T> exp, + Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter) { + testForEach(exp, supplier, boxingAdapter, defaultContentAsserter()); + } + + public static <T, S extends Spliterator<T>> void testTryAdvance( + Collection<T> exp, + Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter) { + testTryAdvance(exp, supplier, boxingAdapter, defaultContentAsserter()); + } + + public static <T, S extends Spliterator<T>> void testMixedTryAdvanceForEach( + Collection<T> exp, + Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter) { + testMixedTryAdvanceForEach(exp, supplier, boxingAdapter, defaultContentAsserter()); + } + + public static <T, S extends Spliterator<T>> void testMixedTraverseAndSplit( + Collection<T> exp, + Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter) { + testMixedTraverseAndSplit(exp, supplier, boxingAdapter, defaultContentAsserter()); + } + + public static <T, S extends Spliterator<T>> void testSplitOnce( + Collection<T> exp, + Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter) { + testSplitOnce(exp, supplier, boxingAdapter, defaultContentAsserter()); + } + + public static <T, S extends Spliterator<T>> void testSplitSixDeep( + Collection<T> exp, + Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter) { + testSplitSixDeep(exp, supplier, boxingAdapter, defaultContentAsserter()); + } + + public static <T, S extends Spliterator<T>> void testSplitUntilNull( + Collection<T> exp, + Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter) { + testSplitUntilNull(exp, supplier, boxingAdapter, defaultContentAsserter()); + } + + private static <T, S extends Spliterator<T>> void testNullPointerException(Supplier<S> s) { + S sp = s.get(); + // Have to check instances and use casts to avoid tripwire messages and + // directly test the primitive methods + if (sp instanceof Spliterator.OfInt) { + Spliterator.OfInt psp = (Spliterator.OfInt) sp; + assertThrowsNPE(() -> psp.forEachRemaining((IntConsumer) null)); + assertThrowsNPE(() -> psp.tryAdvance((IntConsumer) null)); + } + else if (sp instanceof Spliterator.OfLong) { + Spliterator.OfLong psp = (Spliterator.OfLong) sp; + assertThrowsNPE(() -> psp.forEachRemaining((LongConsumer) null)); + assertThrowsNPE(() -> psp.tryAdvance((LongConsumer) null)); + } + else if (sp instanceof Spliterator.OfDouble) { + Spliterator.OfDouble psp = (Spliterator.OfDouble) sp; + assertThrowsNPE(() -> psp.forEachRemaining((DoubleConsumer) null)); + assertThrowsNPE(() -> psp.tryAdvance((DoubleConsumer) null)); + } + else { + assertThrowsNPE(() -> sp.forEachRemaining(null)); + assertThrowsNPE(() -> sp.tryAdvance(null)); + } + } + + private static <T, S extends Spliterator<T>> void testForEach( + Collection<T> exp, + Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter, + ContentAsserter<T> asserter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + ArrayList<T> fromForEach = new ArrayList<>(); + spliterator = supplier.get(); + Consumer<T> addToFromForEach = boxingAdapter.apply(fromForEach::add); + spliterator.forEachRemaining(addToFromForEach); + + // Assert that forEach now produces no elements + spliterator.forEachRemaining(boxingAdapter.apply( + e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); + // Assert that tryAdvance now produce no elements + spliterator.tryAdvance(boxingAdapter.apply( + e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); + + // assert that size, tryAdvance, and forEach are consistent + if (sizeIfKnown >= 0) { + assertEquals(sizeIfKnown, exp.size()); + } + if (exp.contains(null)) { + assertTrue(fromForEach.contains(null)); + } + assertEquals(fromForEach.size(), exp.size()); + + asserter.assertContents(fromForEach, exp, isOrdered); + } + + private static <T, S extends Spliterator<T>> void testTryAdvance( + Collection<T> exp, + Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter, + ContentAsserter<T> asserter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + spliterator = supplier.get(); + ArrayList<T> fromTryAdvance = new ArrayList<>(); + Consumer<T> addToFromTryAdvance = boxingAdapter.apply(fromTryAdvance::add); + while (spliterator.tryAdvance(addToFromTryAdvance)) { } + + // Assert that forEach now produces no elements + spliterator.forEachRemaining(boxingAdapter.apply( + e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); + // Assert that tryAdvance now produce no elements + spliterator.tryAdvance(boxingAdapter.apply( + e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); + + // assert that size, tryAdvance, and forEach are consistent + if (sizeIfKnown >= 0) { + assertEquals(sizeIfKnown, exp.size()); + } + assertEquals(fromTryAdvance.size(), exp.size()); + + asserter.assertContents(fromTryAdvance, exp, isOrdered); + } + + private static <T, S extends Spliterator<T>> void testMixedTryAdvanceForEach( + Collection<T> exp, + Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter, + ContentAsserter<T> asserter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + // tryAdvance first few elements, then forEach rest + ArrayList<T> dest = new ArrayList<>(); + spliterator = supplier.get(); + Consumer<T> addToDest = boxingAdapter.apply(dest::add); + for (int i = 0; i < 10 && spliterator.tryAdvance(addToDest); i++) { } + spliterator.forEachRemaining(addToDest); + + // Assert that forEach now produces no elements + spliterator.forEachRemaining(boxingAdapter.apply( + e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); + // Assert that tryAdvance now produce no elements + spliterator.tryAdvance(boxingAdapter.apply( + e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); + + if (sizeIfKnown >= 0) { + assertEquals(sizeIfKnown, dest.size()); + } + assertEquals(dest.size(), exp.size()); + + asserter.assertContents(dest, exp, isOrdered); + } + + private static <T, S extends Spliterator<T>> void testMixedTraverseAndSplit( + Collection<T> exp, + Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter, + ContentAsserter<T> asserter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + // tryAdvance first few elements, then forEach rest + ArrayList<T> dest = new ArrayList<>(); + spliterator = supplier.get(); + Consumer<T> b = boxingAdapter.apply(dest::add); + + Spliterator<T> spl1, spl2, spl3; + spliterator.tryAdvance(b); + spl2 = spliterator.trySplit(); + if (spl2 != null) { + spl2.tryAdvance(b); + spl1 = spl2.trySplit(); + if (spl1 != null) { + spl1.tryAdvance(b); + spl1.forEachRemaining(b); + } + spl2.tryAdvance(b); + spl2.forEachRemaining(b); + } + spliterator.tryAdvance(b); + spl3 = spliterator.trySplit(); + if (spl3 != null) { + spl3.tryAdvance(b); + spl3.forEachRemaining(b); + } + spliterator.tryAdvance(b); + spliterator.forEachRemaining(b); + + if (sizeIfKnown >= 0) { + assertEquals(sizeIfKnown, dest.size()); + } + assertEquals(dest.size(), exp.size()); + + asserter.assertContents(dest, exp, isOrdered); + } + + public static <T, S extends Spliterator<T>> void testSplitAfterFullTraversal( + Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter) { + // Full traversal using tryAdvance + Spliterator<T> spliterator = supplier.get(); + while (spliterator.tryAdvance(boxingAdapter.apply(e -> { }))) { } + Spliterator<T> split = spliterator.trySplit(); + assertNull(split); + + // Full traversal using forEach + spliterator = supplier.get(); + spliterator.forEachRemaining(boxingAdapter.apply(e -> { })); + split = spliterator.trySplit(); + assertNull(split); + + // Full traversal using tryAdvance then forEach + spliterator = supplier.get(); + spliterator.tryAdvance(boxingAdapter.apply(e -> { })); + spliterator.forEachRemaining(boxingAdapter.apply(e -> { })); + split = spliterator.trySplit(); + assertNull(split); + } + + private static <T, S extends Spliterator<T>> void testSplitOnce( + Collection<T> exp, + Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter, + ContentAsserter<T> asserter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + ArrayList<T> fromSplit = new ArrayList<>(); + Spliterator<T> s1 = supplier.get(); + Spliterator<T> s2 = s1.trySplit(); + long s1Size = s1.getExactSizeIfKnown(); + long s2Size = (s2 != null) ? s2.getExactSizeIfKnown() : 0; + Consumer<T> addToFromSplit = boxingAdapter.apply(fromSplit::add); + if (s2 != null) + s2.forEachRemaining(addToFromSplit); + s1.forEachRemaining(addToFromSplit); + + if (sizeIfKnown >= 0) { + assertEquals(sizeIfKnown, fromSplit.size()); + if (s1Size >= 0 && s2Size >= 0) + assertEquals(sizeIfKnown, s1Size + s2Size); + } + + asserter.assertContents(fromSplit, exp, isOrdered); + } + + private static <T, S extends Spliterator<T>> void testSplitSixDeep( + Collection<T> exp, + Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter, + ContentAsserter<T> asserter) { + S spliterator = supplier.get(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + for (int depth=0; depth < 6; depth++) { + List<T> dest = new ArrayList<>(); + spliterator = supplier.get(); + + assertSpliterator(spliterator); + + // verify splitting with forEach + splitSixDeepVisitor(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), false); + asserter.assertContents(dest, exp, isOrdered); + + // verify splitting with tryAdvance + dest.clear(); + spliterator = supplier.get(); + splitSixDeepVisitor(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), true); + asserter.assertContents(dest, exp, isOrdered); + } + } + + private static <T, S extends Spliterator<T>> + void splitSixDeepVisitor(int depth, int curLevel, + List<T> dest, S spliterator, UnaryOperator<Consumer<T>> boxingAdapter, + int rootCharacteristics, boolean useTryAdvance) { + if (curLevel < depth) { + long beforeSize = spliterator.getExactSizeIfKnown(); + Spliterator<T> split = spliterator.trySplit(); + if (split != null) { + assertSpliterator(split, rootCharacteristics); + assertSpliterator(spliterator, rootCharacteristics); + + if ((rootCharacteristics & Spliterator.SUBSIZED) != 0 && + (rootCharacteristics & Spliterator.SIZED) != 0) { + assertEquals(beforeSize, split.estimateSize() + spliterator.estimateSize()); + } + splitSixDeepVisitor(depth, curLevel + 1, dest, split, boxingAdapter, rootCharacteristics, useTryAdvance); + } + splitSixDeepVisitor(depth, curLevel + 1, dest, spliterator, boxingAdapter, rootCharacteristics, useTryAdvance); + } + else { + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + if (useTryAdvance) { + Consumer<T> addToDest = boxingAdapter.apply(dest::add); + int count = 0; + while (spliterator.tryAdvance(addToDest)) { + ++count; + } + + if (sizeIfKnown >= 0) + assertEquals(sizeIfKnown, count); + + // Assert that forEach now produces no elements + spliterator.forEachRemaining(boxingAdapter.apply( + e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); + + Spliterator<T> split = spliterator.trySplit(); + assertNull(split); + } + else { + List<T> leafDest = new ArrayList<>(); + Consumer<T> addToLeafDest = boxingAdapter.apply(leafDest::add); + spliterator.forEachRemaining(addToLeafDest); + + if (sizeIfKnown >= 0) + assertEquals(sizeIfKnown, leafDest.size()); + + // Assert that forEach now produces no elements + spliterator.tryAdvance(boxingAdapter.apply( + e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); + + Spliterator<T> split = spliterator.trySplit(); + assertNull(split); + + dest.addAll(leafDest); + } + } + } + + private static <T, S extends Spliterator<T>> void testSplitUntilNull( + Collection<T> exp, + Supplier<S> supplier, + UnaryOperator<Consumer<T>> boxingAdapter, + ContentAsserter<T> asserter) { + Spliterator<T> s = supplier.get(); + boolean isOrdered = s.hasCharacteristics(Spliterator.ORDERED); + assertSpliterator(s); + + List<T> splits = new ArrayList<>(); + Consumer<T> c = boxingAdapter.apply(splits::add); + + testSplitUntilNull(new SplitNode<T>(c, s)); + asserter.assertContents(splits, exp, isOrdered); + } + + private static class SplitNode<T> { + // Constant for every node + final Consumer<T> c; + final int rootCharacteristics; + + final Spliterator<T> s; + + SplitNode(Consumer<T> c, Spliterator<T> s) { + this(c, s.characteristics(), s); + } + + private SplitNode(Consumer<T> c, int rootCharacteristics, Spliterator<T> s) { + this.c = c; + this.rootCharacteristics = rootCharacteristics; + this.s = s; + } + + SplitNode<T> fromSplit(Spliterator<T> split) { + return new SplitNode<>(c, rootCharacteristics, split); + } + } + + /** + * Set the maximum stack capacity to 0.25MB. This should be more than enough to detect a bad spliterator + * while not unduly disrupting test infrastructure given the test data sizes that are used are small. + * Note that j.u.c.ForkJoinPool sets the max queue size to 64M (1 << 26). + */ + private static final int MAXIMUM_STACK_CAPACITY = 1 << 18; // 0.25MB + + private static <T> void testSplitUntilNull(SplitNode<T> e) { + // Use an explicit stack to avoid a StackOverflowException when testing a Spliterator + // that when repeatedly split produces a right-balanced (and maybe degenerate) tree, or + // for a spliterator that is badly behaved. + Deque<SplitNode<T>> stack = new ArrayDeque<>(); + stack.push(e); + + int iteration = 0; + while (!stack.isEmpty()) { + assertTrue(iteration++ < MAXIMUM_STACK_CAPACITY, "Exceeded maximum stack modification count of 1 << 18"); + + e = stack.pop(); + Spliterator<T> parentAndRightSplit = e.s; + + long parentEstimateSize = parentAndRightSplit.estimateSize(); + assertTrue(parentEstimateSize >= 0, + String.format("Split size estimate %d < 0", parentEstimateSize)); + + long parentSize = parentAndRightSplit.getExactSizeIfKnown(); + Spliterator<T> leftSplit = parentAndRightSplit.trySplit(); + if (leftSplit == null) { + parentAndRightSplit.forEachRemaining(e.c); + continue; + } + + assertSpliterator(leftSplit, e.rootCharacteristics); + assertSpliterator(parentAndRightSplit, e.rootCharacteristics); + + if (parentEstimateSize != Long.MAX_VALUE && leftSplit.estimateSize() > 0 + && parentAndRightSplit.estimateSize() > 0) { + assertTrue(leftSplit.estimateSize() < parentEstimateSize, + String.format("Left split size estimate %d >= parent split size estimate %d", + leftSplit.estimateSize(), parentEstimateSize)); + assertTrue(parentAndRightSplit.estimateSize() < parentEstimateSize, + String.format("Right split size estimate %d >= parent split size estimate %d", + leftSplit.estimateSize(), parentEstimateSize)); + } + else { + assertTrue(leftSplit.estimateSize() <= parentEstimateSize, + String.format("Left split size estimate %d > parent split size estimate %d", + leftSplit.estimateSize(), parentEstimateSize)); + assertTrue(parentAndRightSplit.estimateSize() <= parentEstimateSize, + String.format("Right split size estimate %d > parent split size estimate %d", + leftSplit.estimateSize(), parentEstimateSize)); + } + + long leftSize = leftSplit.getExactSizeIfKnown(); + long rightSize = parentAndRightSplit.getExactSizeIfKnown(); + if (parentSize >= 0 && leftSize >= 0 && rightSize >= 0) + assertEquals(parentSize, leftSize + rightSize, + String.format("exact left split size %d + exact right split size %d != parent exact split size %d", + leftSize, rightSize, parentSize)); + + // Add right side to stack first so left side is popped off first + stack.push(e.fromSplit(parentAndRightSplit)); + stack.push(e.fromSplit(leftSplit)); + } + } + + private static void assertSpliterator(Spliterator<?> s, int rootCharacteristics) { + if ((rootCharacteristics & Spliterator.SUBSIZED) != 0) { + assertTrue(s.hasCharacteristics(Spliterator.SUBSIZED), + "Child split is not SUBSIZED when root split is SUBSIZED"); + } + assertSpliterator(s); + } + + private static void assertSpliterator(Spliterator<?> s) { + if (s.hasCharacteristics(Spliterator.SUBSIZED)) { + assertTrue(s.hasCharacteristics(Spliterator.SIZED)); + } + if (s.hasCharacteristics(Spliterator.SIZED)) { + assertTrue(s.estimateSize() != Long.MAX_VALUE); + assertTrue(s.getExactSizeIfKnown() >= 0); + } + try { + s.getComparator(); + assertTrue(s.hasCharacteristics(Spliterator.SORTED)); + } catch (IllegalStateException e) { + assertFalse(s.hasCharacteristics(Spliterator.SORTED)); + } + } + + private static<T> void assertContents(Collection<T> actual, Collection<T> expected, boolean isOrdered) { + if (isOrdered) { + assertEquals(actual, expected); + } + else { + LambdaTestHelpers.assertContentsUnordered(actual, expected); + } + } + + public static void assertThrowsNPE(ThrowingRunnable r) { + assertThrows(NullPointerException.class, r); + } + + public static<U> void mixedTraverseAndSplit(Consumer<U> b, Spliterator<U> splTop) { + Spliterator<U> spl1, spl2, spl3; + splTop.tryAdvance(b); + spl2 = splTop.trySplit(); + if (spl2 != null) { + spl2.tryAdvance(b); + spl1 = spl2.trySplit(); + if (spl1 != null) { + spl1.tryAdvance(b); + spl1.forEachRemaining(b); + } + spl2.tryAdvance(b); + spl2.forEachRemaining(b); + } + splTop.tryAdvance(b); + spl3 = splTop.trySplit(); + if (spl3 != null) { + spl3.tryAdvance(b); + spl3.forEachRemaining(b); + } + splTop.tryAdvance(b); + splTop.forEachRemaining(b); + } + + public static void mixedTraverseAndSplit(IntConsumer b, Spliterator.OfInt splTop) { + Spliterator.OfInt spl1, spl2, spl3; + splTop.tryAdvance(b); + spl2 = splTop.trySplit(); + if (spl2 != null) { + spl2.tryAdvance(b); + spl1 = spl2.trySplit(); + if (spl1 != null) { + spl1.tryAdvance(b); + spl1.forEachRemaining(b); + } + spl2.tryAdvance(b); + spl2.forEachRemaining(b); + } + splTop.tryAdvance(b); + spl3 = splTop.trySplit(); + if (spl3 != null) { + spl3.tryAdvance(b); + spl3.forEachRemaining(b); + } + splTop.tryAdvance(b); + splTop.forEachRemaining(b); + } + + public static void mixedTraverseAndSplit(LongConsumer b, Spliterator.OfLong splTop) { + Spliterator.OfLong spl1, spl2, spl3; + splTop.tryAdvance(b); + spl2 = splTop.trySplit(); + if (spl2 != null) { + spl2.tryAdvance(b); + spl1 = spl2.trySplit(); + if (spl1 != null) { + spl1.tryAdvance(b); + spl1.forEachRemaining(b); + } + spl2.tryAdvance(b); + spl2.forEachRemaining(b); + } + splTop.tryAdvance(b); + spl3 = splTop.trySplit(); + if (spl3 != null) { + spl3.tryAdvance(b); + spl3.forEachRemaining(b); + } + splTop.tryAdvance(b); + splTop.forEachRemaining(b); + } + + public static void mixedTraverseAndSplit(DoubleConsumer b, Spliterator.OfDouble splTop) { + Spliterator.OfDouble spl1, spl2, spl3; + splTop.tryAdvance(b); + spl2 = splTop.trySplit(); + if (spl2 != null) { + spl2.tryAdvance(b); + spl1 = spl2.trySplit(); + if (spl1 != null) { + spl1.tryAdvance(b); + spl1.forEachRemaining(b); + } + spl2.tryAdvance(b); + spl2.forEachRemaining(b); + } + splTop.tryAdvance(b); + spl3 = splTop.trySplit(); + if (spl3 != null) { + spl3.tryAdvance(b); + spl3.forEachRemaining(b); + } + splTop.tryAdvance(b); + splTop.forEachRemaining(b); + } + +} diff --git a/openjdk_java_files.bp b/openjdk_java_files.bp index 804da6b1d70..ababa26682e 100644 --- a/openjdk_java_files.bp +++ b/openjdk_java_files.bp @@ -799,13 +799,11 @@ filegroup { "ojluni/src/main/java/java/text/EntryPair.java", "ojluni/src/main/java/java/text/FieldPosition.java", "ojluni/src/main/java/java/text/Format.java", - "ojluni/src/main/java/java/text/MergeCollation.java", "ojluni/src/main/java/java/text/MessageFormat.java", "ojluni/src/main/java/java/text/Normalizer.java", "ojluni/src/main/java/java/text/NumberFormat.java", "ojluni/src/main/java/java/text/ParseException.java", "ojluni/src/main/java/java/text/ParsePosition.java", - "ojluni/src/main/java/java/text/PatternEntry.java", "ojluni/src/main/java/java/text/IcuIteratorWrapper.java", "ojluni/src/main/java/java/text/RuleBasedCollator.java", "ojluni/src/main/java/java/text/SimpleDateFormat.java", diff --git a/test-rules/src/main/java/libcore/test/reasons/NonMtsReasons.java b/test-rules/src/main/java/libcore/test/reasons/NonMtsReasons.java new file mode 100644 index 00000000000..cbe9f40bc7c --- /dev/null +++ b/test-rules/src/main/java/libcore/test/reasons/NonMtsReasons.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * 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 libcore.test.reasons; + +/** + * Reasons for {@link libcore.test.annotation.NonMts}. + */ +public class NonMtsReasons { + + /** + * If the test depends on a new API from ICU, and version-specific API behavior or locale data, + * you can use this reason. + */ + public static final String ICU_VERSION_DEPENDENCY = "The test depends on a " + + "specific ICU version."; + + /** + * If the test asserts a new behavior not tested in CTS, OEMs have the right to customize the + * behavior, but impossible to revert the behavior without system image OTA. Thus, we disable + * the test in MTS until it's tested in the dessert CTS. + */ + public static final String OEM_CUSTOMIZATION = "The test doesn't pass with certain " + + "customizations from AOSP."; + + private NonMtsReasons() {} +} diff --git a/tools/checkstyle/ojluni-src-test-header.xml b/tools/checkstyle/ojluni-src-test-header.xml index 58832e2e3e5..6ba83969123 100644 --- a/tools/checkstyle/ojluni-src-test-header.xml +++ b/tools/checkstyle/ojluni-src-test-header.xml @@ -22,19 +22,6 @@ <property name="multiLines" value="1,2,3,9,10" /> </module> - <!-- Google contributed OpenJDK tests --> - <module name="BeforeExecutionExclusionFileFilter"> - <property name="fileNamePattern" - value="ojluni/src/test/java/lang/StringBuffer/Capacity.java" /> - </module> - <module name="BeforeExecutionExclusionFileFilter"> - <property name="fileNamePattern" - value="ojluni/src/test/java/util/ArrayList/ArrayManagement.java" /> - </module> - <module name="BeforeExecutionExclusionFileFilter"> - <property name="fileNamePattern" - value="ojluni/src/test/java/util/Vector/ArrayManagement.java"/> - </module> <!-- One-off Android test that is present for MTS reasons (see https://r.android.com/1987987). --> <module name="BeforeExecutionExclusionFileFilter"> <property name="fileNamePattern" diff --git a/tools/checkstyle/openjdk-gplv2-copyright.pattern b/tools/checkstyle/openjdk-gplv2-copyright.pattern index 9a61d2314b9..03fffea89a9 100644 --- a/tools/checkstyle/openjdk-gplv2-copyright.pattern +++ b/tools/checkstyle/openjdk-gplv2-copyright.pattern @@ -1,5 +1,5 @@ ^(/\*)?$ -/* Copyright.*Android.* +/* Copyright.*(Android|Google|Red Hat|SAP SE|Azul Systems|Goldman Sachs).* [ /][*o] Copyright \(c\) \d\d\d\d,( ?\d\d\d\d,?)? Oracle and/or its affiliates\. All rights reserved\. \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER\. \* diff --git a/tools/checkstyle/openjdk-gplv2-plus-classpath-copyright.pattern b/tools/checkstyle/openjdk-gplv2-plus-classpath-copyright.pattern index de71d8e9d83..b73521a5dc4 100644 --- a/tools/checkstyle/openjdk-gplv2-plus-classpath-copyright.pattern +++ b/tools/checkstyle/openjdk-gplv2-plus-classpath-copyright.pattern @@ -1,7 +1,7 @@ /\*.* \*.*Android.* \* Copyright \(c\) \d\d\d\d,( ?\d\d\d\d,?)? Oracle and/or its affiliates\. All rights reserved\. - \*.*(Android|Google|Red Hat|SAP SE).* + \*.*(Android|Google|Red Hat|SAP SE|Azul Systems).* \*$ \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER\. \* |