/*
* Copyright (c) 2014 the original author or authors
*
* 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 io.werval.util;
import java.util.Arrays;
import org.junit.Test;
import static io.werval.util.Hashids.DEFAULT_ALPHABET;
import static io.werval.util.Hashids.DEFAULT_SEPARATORS;
import static io.werval.util.Strings.hasText;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Hashids Test.
*/
public class HashidsTest
{
@Test
public void oneNumber()
{
Hashids hashids = new Hashids( "this is my salt" );
long number = 12_345L;
String expected = "NkK9";
assertThat( hashids.encodeToString( number ), equalTo( expected ) );
long[] decoded = hashids.decodeLongs( expected );
assertThat( decoded.length, is( 1 ) );
assertThat( decoded[0], is( number ) );
}
@Test
public void severalNumbers()
{
Hashids hashids = new Hashids( "this is my salt" );
long[] numbers =
{
683L, 94_108L, 123L, 5L
};
String expected = "aBMswoO2UB3Sj";
assertThat( hashids.encodeToString( numbers ), equalTo( expected ) );
long[] decoded = hashids.decodeLongs( expected );
assertThat( decoded.length, is( numbers.length ) );
assertTrue( Arrays.equals( decoded, numbers ) );
}
@Test
public void customHashLength()
{
Hashids hashids = new Hashids( "this is my salt", 8 );
long number = 1L;
String expected = "gB0NV05e";
assertThat( hashids.encodeToString( number ), equalTo( expected ) );
long[] decoded = hashids.decodeLongs( expected );
assertThat( decoded.length, is( 1 ) );
assertThat( decoded[0], is( number ) );
}
@Test
public void randomness()
{
Hashids hashids = new Hashids( "this is my salt" );
long[] numbers =
{
5L, 5L, 5L, 5L
};
String expected = "1Wc8cwcE";
assertThat( hashids.encodeToString( numbers ), equalTo( expected ) );
long[] decoded = hashids.decodeLongs( expected );
assertThat( decoded.length, is( numbers.length ) );
assertTrue( Arrays.equals( decoded, numbers ) );
}
@Test
public void randomnessForIncrementingNumbers()
{
Hashids hashids = new Hashids( "this is my salt" );
long[] numbers =
{
1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L
};
String expected = "kRHnurhptKcjIDTWC3sx";
assertThat( hashids.encodeToString( numbers ), equalTo( expected ) );
long[] decoded = hashids.decodeLongs( expected );
assertThat( decoded.length, is( numbers.length ) );
assertTrue( Arrays.equals( decoded, numbers ) );
}
@Test
public void randomnessForIncrementing()
{
Hashids hashids = new Hashids( "this is my salt" );
assertEquals( hashids.encodeToString( 1L ), "NV" );
assertEquals( hashids.encodeToString( 2L ), "6m" );
assertEquals( hashids.encodeToString( 3L ), "yD" );
assertEquals( hashids.encodeToString( 4L ), "2l" );
assertEquals( hashids.encodeToString( 5L ), "rD" );
}
@Test
public void valuesGreaterIntMaxValue()
{
assertThat( new Hashids( "this is my salt" ).encodeToString( 9_876_543_210_123L ), equalTo( "Y8r7W1kNN" ) );
}
@Test
public void maxNumberValue()
throws Exception
{
try
{
new Hashids( "this is my salt" ).encodeToString( Hashids.MAX_NUMBER_VALUE + 1 );
fail( "Hashids shoud not allow encoding number greater or equal to 2^53." );
}
catch( IllegalArgumentException expected )
{
assertThat( expected.getMessage(), equalTo( "Number out of range" ) );
}
}
@Test( expected = IllegalArgumentException.class )
public void wrongDecoding()
{
new Hashids( "this is my pepper" ).decode( "NkK9" );
}
@Test
public void hexString()
{
Hashids hashids = new Hashids( "this is my salt" );
String hex = "507f1f77bcf86cd799439011";
String hash = hashids.encodeToString( hex );
String returnedHex = hashids.decodeHex( hash );
assertTrue( hasText( hash ) );
assertThat( returnedHex, equalTo( hex ) );
}
@Test
public void hexStringWithMinHashLength()
{
int minHashLength = 23;
Hashids hashids = new Hashids( "", minHashLength );
String hex = "507f1f77bcf86cd799439011";
String hash = hashids.encodeToString( hex );
String returnedHex = hashids.decodeHex( hash );
assertTrue( hasText( hash ) );
assertThat( returnedHex, equalTo( hex ) );
assertThat( hash.length(), equalTo( minHashLength ) );
}
@Test
public void longHexString()
{
Hashids hashids = new Hashids( "this is my salt" );
String hex = "f000000000000000000000000000000000000000000000000000000000000000000000000000000000000f";
String hash = hashids.encodeToString( hex );
String returnedHex = hashids.decodeHex( hash );
assertTrue( hasText( hash ) );
assertThat( returnedHex, equalTo( hex ) );
}
@Test
public void bigMinHashLength()
{
int minHashLength = 1000;
Hashids hashids = new Hashids( "this is my salt", minHashLength );
long[] numbers = new long[]
{
1, 2, 3, 4, 5
};
String hash = hashids.encodeToString( numbers );
long[] returnedNumbers = hashids.decodeLongs( hash );
assertTrue( hasText( hash ) );
assertThat( returnedNumbers, equalTo( numbers ) );
assertThat( hash.length(), equalTo( minHashLength ) );
}
@Test
public void saltMinHashLengthAndCustomAlphabet()
{
int minHashLength = 23;
String customAlphabet = "0123456789abcdef";
Hashids hashids = new Hashids( "this is my salt", minHashLength, customAlphabet );
long[] numbers = new long[]
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};
String hash = hashids.encodeToString( numbers );
long[] returnedNumbers = hashids.decodeLongs( hash );
assertTrue( hasText( hash ) );
assertThat( returnedNumbers, equalTo( numbers ) );
assertThat( hash.length(), equalTo( minHashLength ) );
assertThat( hash.matches( "^[0-9a-f]+$" ), is( true ) );
}
@Test
public void negativeValues()
{
try
{
new Hashids( "this is my salt" ).encodeToString( -1 );
fail( "Hashids shoud not allow encoding negative numbers." );
}
catch( IllegalArgumentException expected )
{
assertThat( expected.getMessage(), equalTo( "Number out of range" ) );
}
}
@Test
public void builder()
{
// No salt, use an empty one
new Hashids.Builder().build();
// Still no salt, use an empty one
new Hashids.Builder()
.alphabet( DEFAULT_ALPHABET )
.minimumLength( 16 )
.separators( DEFAULT_SEPARATORS )
.build();
}
@Test
public void noSeparators()
{
Hashids hashids = new Hashids.Builder().separators( null ).build();
long[] numbers = new long[]
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};
String hashid = hashids.encodeToString( numbers );
long[] decoded = hashids.decodeLongs( hashid );
assertTrue( Arrays.equals( numbers, decoded ) );
}
@Test
public void customSeparators()
{
Hashids hashids = new Hashids.Builder().separators( "abcdABCD" ).build();
long[] numbers = new long[]
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};
String hashid = hashids.encodeToString( numbers );
long[] decoded = hashids.decodeLongs( hashid );
assertTrue( Arrays.equals( numbers, decoded ) );
}
@Test
public void integers()
{
Hashids hashids = new Hashids.Builder().separators( "abcdABCD" ).build();
int[] numbers = new int[]
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};
String hashid = hashids.encodeToString( numbers );
int[] decoded = hashids.decodeInts( hashid );
assertTrue( Arrays.equals( numbers, decoded ) );
}
}