test/hotspot/jtreg/runtime/appcds/SharedArchiveConsistency.java
changeset 54927 1512d88b24c6
parent 54838 d7819bedfaaf
child 55694 7b7df2be6219
--- a/test/hotspot/jtreg/runtime/appcds/SharedArchiveConsistency.java	Fri May 17 10:48:02 2019 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/SharedArchiveConsistency.java	Fri May 17 08:29:55 2019 -0700
@@ -71,7 +71,18 @@
 
     public static File jsa;        // will be updated during test
     public static File orgJsaFile; // kept the original file not touched.
-    public static String[] shared_region_name = {"MiscCode", "ReadWrite", "ReadOnly", "MiscData"};
+    // The following should be consistent with the enum in the C++ MetaspaceShared class
+    public static String[] shared_region_name = {
+        "mc",          // MiscCode
+        "rw",          // ReadWrite
+        "ro",          // ReadOnly
+        "md",          // MiscData
+        "first_closed_archive",
+        "last_closed_archive",
+        "first_open_archive",
+        "last_open_archive"
+    };
+
     public static int num_regions = shared_region_name.length;
     public static String[] matchMessages = {
         "Unable to use shared archive",
@@ -102,10 +113,11 @@
             return file_header_size;
         }
         // this is not real header size, it is struct size
+        int int_size = wb.getOffsetForName("int_size");
         file_header_size = wb.getOffsetForName("file_header_size");
         int offset_path_misc_info = wb.getOffsetForName("FileMapHeader::_paths_misc_info_size") -
             offset_magic;
-        int path_misc_info_size   = (int)readInt(fc, offset_path_misc_info, size_t_size);
+        int path_misc_info_size   = (int)readInt(fc, offset_path_misc_info, int_size);
         file_header_size += path_misc_info_size; //readInt(fc, offset_path_misc_info, size_t_size);
         System.out.println("offset_path_misc_info = " + offset_path_misc_info);
         System.out.println("path_misc_info_size   = " + path_misc_info_size);
@@ -157,25 +169,26 @@
 
     public static void modifyJsaContentRandomly() throws Exception {
         FileChannel fc = getFileChannel();
-        // corrupt random area in the data areas (MiscCode, ReadWrite, ReadOnly, MiscData)
+        // corrupt random area in the data areas
         long[] used    = new long[num_regions];       // record used bytes
         long start0, start, end, off;
         int used_offset, path_info_size;
 
         int bufSize;
-        System.out.printf("%-12s%-12s%-12s%-12s%-12s\n", "Space Name", "Offset", "Used bytes", "Reg Start", "Random Offset");
+        System.out.printf("%-24s%12s%12s%16s\n", "Space Name", "Used bytes", "Reg Start", "Random Offset");
         start0 = getFileHeaderSize(fc);
         for (int i = 0; i < num_regions; i++) {
-            used_offset = sp_offset + CDSFileMapRegion_size * i + sp_used_offset;
-            // read 'used'
-            used[i] = readInt(fc, used_offset, size_t_size);
+            used[i] = get_region_used_size_aligned(fc, i);
             start = start0;
             for (int j = 0; j < i; j++) {
                 start += align_up_page(used[j]);
             }
             end = start + used[i];
+            if (start == end) {
+                continue; // Ignore empty regions
+            }
             off = getRandomBetween(start, end);
-            System.out.printf("%-12s%-12d%-12d%-12d%-12d\n", shared_region_name[i], used_offset, used[i], start, off);
+            System.out.printf("%-24s%12d%12d%16d\n", shared_region_name[i], used[i], start, off);
             if (end - off < 1024) {
                 bufSize = (int)(end - off + 1);
             } else {
@@ -189,34 +202,50 @@
         }
     }
 
-    public static void modifyJsaContent() throws Exception {
+    static long get_region_used_size_aligned(FileChannel fc, int region) throws Exception {
+        long n = sp_offset + CDSFileMapRegion_size * region + sp_used_offset;
+        long alignment = WhiteBox.getWhiteBox().metaspaceReserveAlignment();
+        long used = readInt(fc, n, size_t_size);
+        used = (used + alignment - 1) & ~(alignment - 1);
+        return used;
+    }
+
+    public static boolean modifyJsaContent(int region) throws Exception {
         FileChannel fc = getFileChannel();
         byte[] buf = new byte[4096];
         ByteBuffer bbuf = ByteBuffer.wrap(buf);
 
         long total = 0L;
-        long used_offset = 0L;
         long[] used = new long[num_regions];
-        System.out.printf("%-12s%-12s\n", "Space name", "Used bytes");
+        System.out.printf("%-24s%12s\n", "Space name", "Used bytes");
         for (int i = 0; i < num_regions; i++) {
-            used_offset = sp_offset + CDSFileMapRegion_size* i + sp_used_offset;
-            // read 'used'
-            used[i] = readInt(fc, used_offset, size_t_size);
-            System.out.printf("%-12s%-12d\n", shared_region_name[i], used[i]);
+            used[i] = get_region_used_size_aligned(fc, i);
+            System.out.printf("%-24s%12d\n", shared_region_name[i], used[i]);
             total += used[i];
         }
-        System.out.printf("%-12s%-12d\n", "Total: ", total);
-        long corrupt_used_offset =  getFileHeaderSize(fc);
-        System.out.println("Corrupt RO section, offset = " + corrupt_used_offset);
-        while (used_offset < used[0]) {
-            writeData(fc, corrupt_used_offset, bbuf);
+        System.out.printf("%-24s%12d\n", "Total: ", total);
+        long header_size = getFileHeaderSize(fc);
+        long region_start_offset = header_size;
+        for (int i=0; i<region; i++) {
+            region_start_offset += used[i];
+        }
+        if (used[region] == 0) {
+            System.out.println("Region " + shared_region_name[region] + " is empty. Nothing to corrupt.");
+            return false;
+        }
+        System.out.println("Corrupt " + shared_region_name[region] + " section, start = " + region_start_offset
+                           + " (header_size + 0x" + Long.toHexString(region_start_offset-header_size) + ")");
+        long bytes_written = 0L;
+        while (bytes_written < used[region]) {
+            writeData(fc, region_start_offset + bytes_written, bbuf);
             bbuf.clear();
-            used_offset += 4096;
+            bytes_written += 4096;
         }
         fc.force(true);
         if (fc.isOpen()) {
             fc.close();
         }
+        return true;
     }
 
     public static void modifyJsaHeader() throws Exception {
@@ -299,11 +328,11 @@
     // read the jsa file
     //   1) run normal
     //   2) modify header
-    //   3) keep header correct but modify content
+    //   3) keep header correct but modify content in each region specified by shared_region_name[]
     //   4) update both header and content, test
     //   5) delete bytes in data begining
     //   6) insert bytes in data begining
-    //   7) randomly corrupt data in four areas: RO, RW. MISC DATA, MISC CODE
+    //   7) randomly corrupt data in each region specified by shared_region_name[]
     public static void main(String... args) throws Exception {
         // must call to get offset info first!!!
         getFileOffsetInfo();
@@ -352,18 +381,23 @@
         output.shouldContain("The shared archive file has the wrong version");
         output.shouldNotContain("Checksum verification failed");
 
+        File newJsaFile = null;
         // modify content
         System.out.println("\n3. Corrupt Content, should fail\n");
-
-        copyFile(orgJsaFile, jsa);
-        modifyJsaContent();
-        testAndCheck(verifyExecArgs);
+        for (int i=0; i<num_regions; i++) {
+            newJsaFile = new File(TestCommon.getNewArchiveName(shared_region_name[i]));
+            copyFile(orgJsaFile, newJsaFile);
+            if (modifyJsaContent(i)) {
+                testAndCheck(execArgs);
+            }
+        }
 
         // modify both header and content, test should fail
         System.out.println("\n4. Corrupt Header and Content, should fail\n");
-        copyFile(orgJsaFile, jsa);
+        newJsaFile = new File(TestCommon.getNewArchiveName("header-and-content"));
+        copyFile(orgJsaFile, newJsaFile);
         modifyJsaHeader();
-        modifyJsaContent();  // this will not be reached since failed on header change first
+        modifyJsaContent(0);  // this will not be reached since failed on header change first
         output = TestCommon.execCommon(execArgs);
         output.shouldContain("The shared archive file has the wrong version");
         output.shouldNotContain("Checksum verification failed");
@@ -379,7 +413,8 @@
         testAndCheck(verifyExecArgs);
 
         System.out.println("\n7. modify Content in random areas, should fail\n");
-        copyFile(orgJsaFile, jsa);
+        newJsaFile = new File(TestCommon.getNewArchiveName("random-areas"));
+        copyFile(orgJsaFile, newJsaFile);
         modifyJsaContentRandomly();
         testAndCheck(verifyExecArgs);
     }