|  | @@ -0,0 +1,152 @@
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 | 
	
		
			
				|  |  | + * or more contributor license agreements. Licensed under the "Elastic License
 | 
	
		
			
				|  |  | + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
 | 
	
		
			
				|  |  | + * Public License v 1"; you may not use this file except in compliance with, at
 | 
	
		
			
				|  |  | + * your election, the "Elastic License 2.0", the "GNU Affero General Public
 | 
	
		
			
				|  |  | + * License v3.0 only", or the "Server Side Public License, v 1".
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +package org.elasticsearch.common.hash;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import org.apache.lucene.util.BytesRef;
 | 
	
		
			
				|  |  | +import org.elasticsearch.common.util.ByteUtils;
 | 
	
		
			
				|  |  | +import org.elasticsearch.test.ESTestCase;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +public class BufferedMurmur3HasherTests extends ESTestCase {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private final BufferedMurmur3Hasher bufferedHasher = new BufferedMurmur3Hasher(0, randomIntBetween(32, 128));
 | 
	
		
			
				|  |  | +    private final Murmur3Hasher hasher = new Murmur3Hasher(0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testAddString() {
 | 
	
		
			
				|  |  | +        String testString = randomUnicodeOfLengthBetween(0, 1024);
 | 
	
		
			
				|  |  | +        bufferedHasher.addString(testString);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        BytesRef bytesRef = new BytesRef(testString);
 | 
	
		
			
				|  |  | +        hasher.update(bytesRef.bytes, bytesRef.offset, bytesRef.length);
 | 
	
		
			
				|  |  | +        assertEquals(hasher.digestHash(), bufferedHasher.digestHash());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testConstructorWithInvalidBufferSize() {
 | 
	
		
			
				|  |  | +        IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> new BufferedMurmur3Hasher(0, 31));
 | 
	
		
			
				|  |  | +        assertEquals("Buffer size must be at least 32 bytes", exception.getMessage());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testAddLong() {
 | 
	
		
			
				|  |  | +        long value = randomLong();
 | 
	
		
			
				|  |  | +        bufferedHasher.addLong(value);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        hasher.update(toBytes(value), 0, Long.BYTES);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertEquals(hasher.digestHash(), bufferedHasher.digestHash());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testAddLongs() {
 | 
	
		
			
				|  |  | +        long value1 = randomLong();
 | 
	
		
			
				|  |  | +        long value2 = randomLong();
 | 
	
		
			
				|  |  | +        long value3 = randomLong();
 | 
	
		
			
				|  |  | +        long value4 = randomLong();
 | 
	
		
			
				|  |  | +        bufferedHasher.addLong(value1);
 | 
	
		
			
				|  |  | +        bufferedHasher.addLongs(value1, value2);
 | 
	
		
			
				|  |  | +        bufferedHasher.addLongs(value1, value2, value3, value4);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        hasher.update(toBytes(value1));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        hasher.update(toBytes(value1));
 | 
	
		
			
				|  |  | +        hasher.update(toBytes(value2));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        hasher.update(toBytes(value1));
 | 
	
		
			
				|  |  | +        hasher.update(toBytes(value2));
 | 
	
		
			
				|  |  | +        hasher.update(toBytes(value3));
 | 
	
		
			
				|  |  | +        hasher.update(toBytes(value4));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertEquals(hasher.digestHash(), bufferedHasher.digestHash());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testAddTwoLongs() {
 | 
	
		
			
				|  |  | +        long value1 = randomLong();
 | 
	
		
			
				|  |  | +        long value2 = randomLong();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        bufferedHasher.addLongs(value1, value2);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        hasher.update(toBytes(value1));
 | 
	
		
			
				|  |  | +        hasher.update(toBytes(value2));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertEquals(hasher.digestHash(), bufferedHasher.digestHash());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testAddFourLongs() {
 | 
	
		
			
				|  |  | +        long value1 = randomLong();
 | 
	
		
			
				|  |  | +        long value2 = randomLong();
 | 
	
		
			
				|  |  | +        long value3 = randomLong();
 | 
	
		
			
				|  |  | +        long value4 = randomLong();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        bufferedHasher.addLongs(value1, value2, value3, value4);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        hasher.update(toBytes(value1));
 | 
	
		
			
				|  |  | +        hasher.update(toBytes(value2));
 | 
	
		
			
				|  |  | +        hasher.update(toBytes(value3));
 | 
	
		
			
				|  |  | +        hasher.update(toBytes(value4));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertEquals(hasher.digestHash(), bufferedHasher.digestHash());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testRandomAdds() {
 | 
	
		
			
				|  |  | +        int numAdds = randomIntBetween(128, 1024);
 | 
	
		
			
				|  |  | +        for (int i = 0; i < numAdds; i++) {
 | 
	
		
			
				|  |  | +            switch (randomIntBetween(0, 4)) {
 | 
	
		
			
				|  |  | +                case 0 -> {
 | 
	
		
			
				|  |  | +                    String randomString = randomUnicodeOfLengthBetween(0, 64);
 | 
	
		
			
				|  |  | +                    bufferedHasher.addString(randomString);
 | 
	
		
			
				|  |  | +                    BytesRef bytesRef = new BytesRef(randomString);
 | 
	
		
			
				|  |  | +                    hasher.update(bytesRef.bytes, bytesRef.offset, bytesRef.length);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                case 1 -> {
 | 
	
		
			
				|  |  | +                    String emptyString = "";
 | 
	
		
			
				|  |  | +                    bufferedHasher.addString(emptyString);
 | 
	
		
			
				|  |  | +                    BytesRef bytesRef = new BytesRef(emptyString);
 | 
	
		
			
				|  |  | +                    hasher.update(bytesRef.bytes, bytesRef.offset, bytesRef.length);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                case 2 -> {
 | 
	
		
			
				|  |  | +                    long randomLong = randomLong();
 | 
	
		
			
				|  |  | +                    bufferedHasher.addLong(randomLong);
 | 
	
		
			
				|  |  | +                    hasher.update(toBytes(randomLong));
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                case 3 -> {
 | 
	
		
			
				|  |  | +                    long randomLong1 = randomLong();
 | 
	
		
			
				|  |  | +                    long randomLong2 = randomLong();
 | 
	
		
			
				|  |  | +                    bufferedHasher.addLongs(randomLong1, randomLong2);
 | 
	
		
			
				|  |  | +                    hasher.update(toBytes(randomLong1));
 | 
	
		
			
				|  |  | +                    hasher.update(toBytes(randomLong2));
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                case 4 -> {
 | 
	
		
			
				|  |  | +                    long randomLong1 = randomLong();
 | 
	
		
			
				|  |  | +                    long randomLong2 = randomLong();
 | 
	
		
			
				|  |  | +                    long randomLong3 = randomLong();
 | 
	
		
			
				|  |  | +                    long randomLong4 = randomLong();
 | 
	
		
			
				|  |  | +                    bufferedHasher.addLongs(randomLong1, randomLong2, randomLong3, randomLong4);
 | 
	
		
			
				|  |  | +                    hasher.update(toBytes(randomLong1));
 | 
	
		
			
				|  |  | +                    hasher.update(toBytes(randomLong2));
 | 
	
		
			
				|  |  | +                    hasher.update(toBytes(randomLong3));
 | 
	
		
			
				|  |  | +                    hasher.update(toBytes(randomLong4));
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        assertEquals(hasher.digestHash(), bufferedHasher.digestHash());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testReset() {
 | 
	
		
			
				|  |  | +        bufferedHasher.addString(randomUnicodeOfLengthBetween(0, 1024));
 | 
	
		
			
				|  |  | +        bufferedHasher.addLong(randomLong());
 | 
	
		
			
				|  |  | +        bufferedHasher.addLongs(randomLong(), randomLong());
 | 
	
		
			
				|  |  | +        bufferedHasher.addLongs(randomLong(), randomLong(), randomLong(), randomLong());
 | 
	
		
			
				|  |  | +        bufferedHasher.reset();
 | 
	
		
			
				|  |  | +        assertEquals(new MurmurHash3.Hash128(0, 0), bufferedHasher.digestHash());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private byte[] toBytes(long value) {
 | 
	
		
			
				|  |  | +        byte[] bytes = new byte[Long.BYTES];
 | 
	
		
			
				|  |  | +        ByteUtils.writeLongLE(value, bytes, 0);
 | 
	
		
			
				|  |  | +        return bytes;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 |