1 /*
   2  * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /* @test
  25  * @bug 4173528 5068772 8148936 8216407
  26  * @summary Unit tests for java.util.UUID
  27  * @key randomness
  28  * @run main/othervm -XX:+CompactStrings UUIDTest
  29  * @run main/othervm -XX:-CompactStrings UUIDTest
  30  */
  31 
  32 import java.util.*;
  33 
  34 public class UUIDTest {
  35 
  36     static Random generator = new Random();
  37 
  38     public static void main(String[] args) throws Exception {
  39         containsTest();
  40         randomUUIDTest();
  41         nameUUIDFromBytesTest();
  42         stringTest();
  43         versionTest();
  44         variantTest();
  45         timestampTest();
  46         clockSequenceTest();
  47         nodeTest();
  48         hashCodeEqualsTest();
  49         compareTo();
  50     }
  51 
  52     // Verify that list.contains detects UUID collisons
  53     private static void containsTest() throws Exception {
  54         List list = new LinkedList();
  55         list.add(new UUID(4,4));
  56         if (!list.contains(new UUID(4,4)))
  57             throw new Exception("contains test did not work as expected");
  58     }
  59 
  60     private static void randomUUIDTest() throws Exception {
  61         List list = new LinkedList();
  62         for (int i=0; i<100; i++) {
  63             UUID u1 = UUID.randomUUID();
  64             if (4 != u1.version()) {
  65                 throw new Exception("bad version");
  66             }
  67             if (2 != u1.variant()) {
  68                 throw new Exception("bad variant");
  69             }
  70             if (list.contains(u1))
  71                 throw new Exception("random UUID collision very unlikely");
  72             list.add(u1);
  73         }
  74     }
  75 
  76     private static void nameUUIDFromBytesTest() throws Exception {
  77         Random byteSource = new Random();
  78         byte[] someBytes = new byte[12];
  79         List list = new LinkedList();
  80         for (int i=0; i<100; i++) {
  81             byteSource.nextBytes(someBytes);
  82             UUID u1 = UUID.nameUUIDFromBytes(someBytes);
  83             if (3 != u1.version()) {
  84                 throw new Exception("bad version");
  85             }
  86             if (2 != u1.variant()) {
  87                 throw new Exception("bad variant");
  88             }
  89             if (list.contains(u1))
  90                 throw new Exception("byte UUID collision very unlikely");
  91             list.add(u1);
  92         }
  93     }
  94 
  95     private static void stringTest() throws Exception {
  96         for (int i=0; i<100; i++) {
  97             UUID u1 = UUID.randomUUID();
  98             UUID u2 = UUID.fromString(u1.toString());
  99             if (!u1.equals(u2))
 100                 throw new Exception("UUID -> string -> UUID failed");
 101         }
 102 
 103         testFromStringError("-0");
 104         testFromStringError("x");
 105         testFromStringError("----");
 106         testFromStringError("-0-0-0-0");
 107         testFromStringError("0-0-0-0-");
 108         testFromStringError("0-0-0-0-0-");
 109         testFromStringError("0-0-0-0-x");
 110         testFromStringError("123456789-0-0-0-0");
 111         testFromStringError("0-1abcd-0-0-0");
 112         testFromStringError("0-0-1ef01-0-0");
 113         testFromStringError("0-0-0-12345-0");
 114         testFromStringError("0-0-0-0-f1234567890ab");
 115     }
 116 
 117     private static void testFromStringError(String str) {
 118         try {
 119             UUID test = UUID.fromString(str);
 120             throw new RuntimeException("Should have thrown IAE");
 121         } catch (IllegalArgumentException iae) {
 122             // pass
 123         }
 124     }
 125 
 126     private static void versionTest() throws Exception {
 127         UUID test = UUID.randomUUID();
 128         if (test.version() != 4)
 129             throw new Exception("randomUUID not type 4");
 130         Random byteSource = new Random();
 131         byte[] someBytes = new byte[12];
 132         byteSource.nextBytes(someBytes);
 133         test = UUID.nameUUIDFromBytes(someBytes);
 134         if (test.version() != 3)
 135             throw new Exception("nameUUIDFromBytes not type 3");
 136         test = UUID.fromString("9835451d-e2e0-1e41-8a5a-be785f17dcda");
 137         if (test.version() != 1)
 138             throw new Exception("wrong version fromString 1");
 139         test = UUID.fromString("9835451d-e2e0-2e41-8a5a-be785f17dcda");
 140         if (test.version() != 2)
 141             throw new Exception("wrong version fromString 2");
 142         test = UUID.fromString("9835451d-e2e0-3e41-8a5a-be785f17dcda");
 143         if (test.version() != 3)
 144             throw new Exception("wrong version fromString 3");
 145         test = UUID.fromString("9835451d-e2e0-4e41-8a5a-be785f17dcda");
 146         if (test.version() != 4)
 147             throw new Exception("wrong version fromString 4");
 148         test = new UUID(0x0000000000001000L, 55L);
 149         if (test.version() != 1)
 150             throw new Exception("wrong version from bit set to 1");
 151         test = new UUID(0x0000000000002000L, 55L);
 152         if (test.version() != 2)
 153             throw new Exception("wrong version from bit set to 2");
 154         test = new UUID(0x0000000000003000L, 55L);
 155         if (test.version() != 3)
 156             throw new Exception("wrong version from bit set to 3");
 157         test = new UUID(0x0000000000004000L, 55L);
 158         if (test.version() != 4)
 159             throw new Exception("wrong version from bit set to 4");
 160     }
 161 
 162     private static void variantTest() throws Exception {
 163         UUID test = UUID.randomUUID();
 164         if (test.variant() != 2)
 165             throw new Exception("randomUUID not variant 2");
 166         Random byteSource = new Random();
 167         byte[] someBytes = new byte[12];
 168         byteSource.nextBytes(someBytes);
 169         test = UUID.nameUUIDFromBytes(someBytes);
 170         if (test.variant() != 2)
 171             throw new Exception("nameUUIDFromBytes not variant 2");
 172         test = new UUID(55L, 0x0000000000001000L);
 173         if (test.variant() != 0)
 174             throw new Exception("wrong variant from bit set to 0");
 175         test = new UUID(55L, 0x8000000000001000L);
 176         if (test.variant() != 2)
 177             throw new Exception("wrong variant from bit set to 2");
 178        test = new UUID(55L, 0xc000000000001000L);
 179         if (test.variant() != 6)
 180             throw new Exception("wrong variant from bit set to 6");
 181        test = new UUID(55L, 0xe000000000001000L);
 182         if (test.variant() != 7)
 183             throw new Exception("wrong variant from bit set to 7");
 184     }
 185 
 186     private static void timestampTest() throws Exception {
 187         UUID test = UUID.randomUUID();
 188         try {
 189             test.timestamp();
 190             throw new Exception("Expected exception not thrown");
 191         } catch (UnsupportedOperationException uoe) {
 192             // Correct result
 193         }
 194         test = UUID.fromString("00000001-0000-1000-8a5a-be785f17dcda");
 195         if (test.timestamp() != 1)
 196             throw new Exception("Incorrect timestamp");
 197         test = UUID.fromString("00000400-0000-1000-8a5a-be785f17dcda");
 198         if (test.timestamp() != 1024)
 199             throw new Exception("Incorrect timestamp");
 200         test = UUID.fromString("FFFFFFFF-FFFF-1FFF-8a5a-be785f17dcda");
 201         if (test.timestamp() != Long.MAX_VALUE>>3)
 202             throw new Exception("Incorrect timestamp");
 203     }
 204 
 205     private static void clockSequenceTest() throws Exception {
 206         UUID test = UUID.randomUUID();
 207         try {
 208             test.clockSequence();
 209             throw new Exception("Expected exception not thrown");
 210         } catch (UnsupportedOperationException uoe) {
 211             // Correct result
 212         }
 213         test = UUID.fromString("00000001-0000-1000-8001-be785f17dcda");
 214         if (test.clockSequence() != 1)
 215             throw new Exception("Incorrect sequence");
 216         test = UUID.fromString("00000001-0000-1000-8002-be785f17dcda");
 217         if (test.clockSequence() != 2)
 218             throw new Exception("Incorrect sequence");
 219         test = UUID.fromString("00000001-0000-1000-8010-be785f17dcda");
 220         if (test.clockSequence() != 16)
 221             throw new Exception("Incorrect sequence");
 222         test = UUID.fromString("00000001-0000-1000-bFFF-be785f17dcda");
 223         if (test.clockSequence() != ((2L<<13)-1)) // 2^14 - 1
 224             throw new Exception("Incorrect sequence");
 225     }
 226 
 227     private static void nodeTest() throws Exception {
 228         UUID test = UUID.randomUUID();
 229         try {
 230             test.node();
 231             throw new Exception("Expected exception not thrown");
 232         } catch (UnsupportedOperationException uoe) {
 233             // Correct result
 234         }
 235         test = UUID.fromString("00000001-0000-1000-8001-000000000001");
 236         if (test.node() != 1)
 237             throw new Exception("Incorrect node");
 238         test = UUID.fromString("00000001-0000-1000-8002-FFFFFFFFFFFF");
 239         if (test.node() != ((2L<<47)-1)) // 2^48 - 1
 240             throw new Exception("Incorrect node");
 241     }
 242 
 243     private static void hashCodeEqualsTest() throws Exception {
 244         // If two UUIDs are equal they must have the same hashCode
 245         for (int i=0; i<100; i++) {
 246             UUID u1 = UUID.randomUUID();
 247             UUID u2 = UUID.fromString(u1.toString());
 248             if (u1.hashCode() != u2.hashCode())
 249                 throw new Exception("Equal UUIDs with different hashcodes");
 250         }
 251         // Test equality of UUIDs with tampered bits
 252         for (int i=0; i<1000; i++) {
 253             long l = generator.nextLong();
 254             long l2 = generator.nextLong();
 255             int position = generator.nextInt(64);
 256             UUID u1 = new UUID(l, l2);
 257             l = l ^ (1L << position);
 258             UUID u2 = new UUID(l, l2);
 259             if (u1.equals(u2))
 260                 throw new Exception("UUIDs with different bits equal");
 261         }
 262     }
 263 
 264     private static void compareTo() throws Exception {
 265         UUID id = new UUID(33L, 63L);
 266         UUID id2 = new UUID(34L, 62L);
 267         UUID id3 = new UUID(34L, 63L);
 268         UUID id4 = new UUID(34L, 64L);
 269         UUID id5 = new UUID(35L, 63L);
 270 
 271         if ((id.compareTo(id2) >= 0) ||
 272             (id2.compareTo(id3) >= 0) ||
 273             (id3.compareTo(id4) >= 0) ||
 274             (id4.compareTo(id5) >= 0))
 275             throw new RuntimeException("compareTo failure");
 276 
 277         if ((id5.compareTo(id4) <= 0) ||
 278             (id4.compareTo(id3) <= 0) ||
 279             (id3.compareTo(id2) <= 0) ||
 280             (id2.compareTo(id) <= 0))
 281             throw new RuntimeException("compareTo failure");
 282 
 283         if (id.compareTo(id) != 0)
 284             throw new RuntimeException("compareTo failure");
 285 
 286     }
 287 
 288 }