code: package net.openhft.chronicle.map;
  
  import net.openhft.chronicle.hash.serialization.SizeMarshaller;
  import org.jetbrains.annotations.NotNull;
  import org.junit.Assert;
  import org.junit.Test;
  import org.junit.runner.RunWith;
  import org.junit.runners.Parameterized;
  
  import java.io.File;
  import java.io.IOException;
  import java.nio.charset.StandardCharsets;
  import java.nio.file.Files;
  import java.util.Arrays;
  import java.util.Collection;
  import java.util.Random;
  
  import static java.nio.charset.StandardCharsets.ISO_8859_1;
  
  @RunWith(Parameterized.class)
  public class ValueAlignmentRelocationTest {
  
      private final boolean persisted;
      private final int alignment;
      private final int chunk;
  
      public ValueAlignmentRelocationTest(String name, boolean persisted, int alignment, int chunk) {
          this.persisted = persisted;
          this.alignment = alignment;
          this.chunk = chunk;
      }
  
      @Parameterized.Parameters(name = "{0}")
      public static Collection<Object[]> data() {
          return Arrays.asList(new Object[][]{
                  {"Volatile a=1, c=1", false, 1, 1},
                  {"Volatile a=1, c=2", false, 1, 2},
                  {"Volatile a=4, c=4", false, 4, 4},
                  {"Volatile a=4, c=8", false, 4, 8},
                  {"Persisted a=1, c=1", true, 1, 1},
                  {"Persisted a=4, c=8", true, 4, 8}
          });
      }
  
      @NotNull
      private static String toString(final byte[] value) {
          return new String(value, StandardCharsets.UTF_8);
      }
  
      @Test
      public void testValueAlignmentRelocation() throws IOException {
  
          File file = Files.createTempFile("test", ".cm3").toFile();
          file.deleteOnExit();
  
          ChronicleMapBuilder<byte[], byte[]> builder = ChronicleMapBuilder
                  .of(byte[].class, byte[].class)
                  .averageKeySize(5)
                  .averageValueSize(5)
                  .keySizeMarshaller(SizeMarshaller.stopBit())
                  .valueSizeMarshaller(SizeMarshaller.stopBit())
                  .entryAndValueOffsetAlignment(alignment)
                  .actualSegments(1)
                  .actualChunkSize(chunk)
                  .entries(10);
          ChronicleMap<byte[], byte[]> map = persisted ? builder.createPersistedTo(file) : builder.create();
          Random r = new Random(0);
  
          for (int firstKeySize = 1; firstKeySize < 10; firstKeySize++) {
              byte[] firstKey = new byte[firstKeySize];
              byte[] firstValue = new byte[8];
              r.nextBytes(firstKey);
              r.nextBytes(firstValue);
              for (int secondKeySize = 1; secondKeySize < 10; secondKeySize++) {
                  byte[] secondKey = new byte[secondKeySize];
                  r.nextBytes(secondKey);
                  while (Arrays.equals(secondKey, firstKey)) {
                      r.nextBytes(secondKey);
                  }
                  byte[] secondValue = new byte[1];
                  r.nextBytes(secondValue);
                  map.clear();
                  map.put(firstKey, firstValue);
                  map.put(secondKey, secondValue);
                  byte[] thirdValue = new byte[16];
                  r.nextBytes(thirdValue);
                  map.put(firstKey, thirdValue);
                  for (int i = 0; i < 10; i++) {
                      map.put(new byte[]{(byte) i}, new byte[]{(byte) i});
                      map.put(("Hello" + i).getBytes(), "world".getBytes());
                  }
  //                System.out.println("firstKeySize=" + firstKeySize + ",second key=" + secondKeySize);
                  Assert.assertEquals(Arrays.toString(map.get(firstKey)), Arrays.toString(thirdValue));
                  Assert.assertTrue(Arrays.equals(map.get(firstKey), thirdValue));
              }
          }
      }
  
      @Test
      public void testValueAlignmentRelocationNoRandomTest() throws IOException {
          File file = Files.createTempFile("test", ".cm3").toFile();
          file.deleteOnExit();
  
          ChronicleMapBuilder<byte[], byte[]> builder = ChronicleMapBuilder
                  .of(byte[].class, byte[].class)
                  .averageKeySize(5)
                  .averageValueSize(5)
                  .keySizeMarshaller(SizeMarshaller.stopBit())
                  .valueSizeMarshaller(SizeMarshaller.stopBit())
                  .entryAndValueOffsetAlignment(alignment)
                  .actualSegments(1)
                  .actualChunkSize(chunk)
                  .entries(10);
          ChronicleMap<byte[], byte[]> map = persisted ? builder.createPersistedTo(file) : builder.create();
  
          for (int k = 1; k <= 16; k++) {
              for (int i = 1; i < 10; i++) {
                  for (int j = i + 1; j <= i + 10; j++) {
                      map.clear();
  
                      byte[] _austi = "abcdefghijklmnopqrstuvwxyz".substring(0, k).getBytes(ISO_8859_1);
                      byte[] _shorter = "1234567890".substring(0, i).getBytes(ISO_8859_1);
                      byte[] _h = "h".getBytes(ISO_8859_1);
                      byte[] _a = "a".getBytes(ISO_8859_1);
                      String expected = "abcdefghijklmnopqrstuvwxyz".substring(0, j);
                      byte[] _longer = expected.getBytes(ISO_8859_1);
                      byte[] _Hello = "Hello".getBytes(ISO_8859_1);
                      byte[] _world = "world".getBytes(ISO_8859_1);
  
                      map.put(_austi, _shorter);
                      map.put(_h, _a);
  
                      map.put(_austi, _longer);
                      String actual0 = toString(map.get(_austi));
                      Assert.assertEquals(expected, actual0);
  
                      map.put(_Hello, _world);
                      String actual = toString(map.get(_austi));
  
                      if (expected.equals(actual))
                          Assert.assertEquals(expected, actual);
                      else
                          System.out.println("k= " + k + ", i= " + i + ", j=" + j);
                  }
              }
          }
      }
  }
  