Hashid: Upgrading Elixir from 1.6 to 1.7 changed results

Hi guys,

I recently upgraded an app I’m working on from Elixir 1.6 to 1.7 and we use a package called Hashids for some SMS stuff (https://github.com/alco/hashids-elixir). When upgrading, the encoded and decoded values changed and thus my tests failed.

  1. test decoding to a number (Cipher.TokenTest)
    test/token_test.exs:18
    Assertion with == failed
    code: assert decoded == @number
    left: 4837
    right: 1276
    stacktrace:
    test/token_test.exs:20: (test)

  2. test encoding a number (Cipher.TokenTest)
    test/token_test.exs:13
    Assertion with == failed
    code: assert encoded == @hash
    left: “5d44”
    right: “9kn7”
    stacktrace:
    test/token_test.exs:15: (test)

I was just wondering why that might’ve happened?

Nothing that I’m immediately seeing as an issue, and it’s own tests are passing on 1.7, so I think we’d need a reproduceable example then? :slight_smile:

Please show us your test code so that we have something to work with. Also which exact Erlang and Elixir versions are you running?

1 Like

Elixir 1.6 and 1.7

As an example:

alphabet = "123456789abcdefghijklmnopqrstuvwxyz"
min_length =  4
hasher = Hashids.new(alphabet: alphabet, min_len: min_length)

Hashids.encode(hasher, 1276)
= "9kn7" # in 1.6

Hashids.encode(hasher, 1276)
= "5d44" # in 1.7

I’m mostly curious as to what part of 1.7 caused this change. If you try this yourself you might get different string values.

1.7.0-otp-21.0.1

iex(1)> alphabet = "123456789abcdefghijklmnopqrstuvwxyz"
"123456789abcdefghijklmnopqrstuvwxyz"
iex(2)> min_length =  4
4
iex(3)> hasher = Hashids.new(alphabet: alphabet, min_len: min_length)
%Hashids{
  a_len: 24,
  alphabet: '56789abdegjklmnopqrvwxyz',
  g_len: 3,
  guards: '234',
  min_len: 4,
  s_len: 8,
  salt: [],
  seps: 'cfhistu1'
} 
iex(4)> Hashids.encode(hasher, 1276)
"9kn7"
2 Likes

1.7.3-otp-21.0.1

iex(1)> alphabet = "123456789abcdefghijklmnopqrstuvwxyz"
"123456789abcdefghijklmnopqrstuvwxyz"
iex(2)> min_length =  4
4
iex(3)> hasher = Hashids.new(alphabet: alphabet, min_len: min_length)
%Hashids{
  a_len: 24,
  alphabet: '56789abdegjklmnopqrvwxyz',
  g_len: 3,
  guards: '234',
  min_len: 4,
  s_len: 8,
  salt: [],
  seps: 'cfhistu1'
} 
iex(4)> Hashids.encode(hasher, 1276)
"9kn7"
2 Likes

1.6.6-otp-21.0.1

iex(1)> alphabet = "123456789abcdefghijklmnopqrstuvwxyz"
"123456789abcdefghijklmnopqrstuvwxyz"
iex(2)> min_length =  4
4
iex(3)> hasher = Hashids.new(alphabet: alphabet, min_len: min_length)
%Hashids{
  a_len: 24,
  alphabet: '56789abdegjklmnopqrvwxyz',
  g_len: 3,
  guards: '234',
  min_len: 4,
  s_len: 8,
  salt: [],
  seps: 'cfhistu1'
} 
iex(4)> Hashids.encode(hasher, 1276)
"9kn7"

EDIT: /me is still compiling OTP 21.1.1, hold on…

2 Likes

1.7.3-otp-21.1.1

iex(1)> alphabet = "123456789abcdefghijklmnopqrstuvwxyz"
"123456789abcdefghijklmnopqrstuvwxyz"
iex(2)> min_length =  4
4
iex(3)> hasher = Hashids.new(alphabet: alphabet, min_len: min_length)
%Hashids{
  a_len: 24,
  alphabet: '56789abdegjklmnopqrvwxyz',
  g_len: 3,
  guards: '234',
  min_len: 4,
  s_len: 8,
  salt: [],
  seps: 'cfhistu1'
} 
iex(4)> Hashids.encode(hasher, 1276)
"9kn7"

So nope, doesn’t seem I can replicate what you are seeing having tried 3 different elixir versions as well as 2 OTP versions.

What is your OS? Are you able to replicate it in a docker image (please share it if so!)? What specific versions of Elixir and OTP?

4 Likes