summaryrefslogtreecommitdiff
path: root/srv/pow/pow_test.go
blob: 4bc41418538d6b98806e83835dc0496234cb9f8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package pow

import (
	"encoding/hex"
	"strconv"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/tilinna/clock"
)

func TestChallengeParams(t *testing.T) {
	tests := []challengeParams{
		{},
		{
			Target:    1,
			ExpiresAt: 3,
		},
		{
			Target:    2,
			ExpiresAt: -10,
			Random:    []byte{0, 1, 2},
		},
		{
			Random: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
		},
	}

	t.Run("marshal_unmarshal", func(t *testing.T) {
		for i, test := range tests {
			t.Run(strconv.Itoa(i), func(t *testing.T) {
				b, err := test.MarshalBinary()
				assert.NoError(t, err)

				var c2 challengeParams
				assert.NoError(t, c2.UnmarshalBinary(b))
				assert.Equal(t, test, c2)

				b2, err := c2.MarshalBinary()
				assert.NoError(t, err)
				assert.Equal(t, b, b2)
			})
		}
	})

	secret := []byte("shhh")

	t.Run("to_from_seed", func(t *testing.T) {

		for i, test := range tests {
			t.Run(strconv.Itoa(i), func(t *testing.T) {
				seed, err := newSeed(test, secret)
				assert.NoError(t, err)

				// generating seed should be deterministic
				seed2, err := newSeed(test, secret)
				assert.NoError(t, err)
				assert.Equal(t, seed, seed2)

				c, err := challengeParamsFromSeed(seed, secret)
				assert.NoError(t, err)
				assert.Equal(t, test, c)
			})
		}
	})

	t.Run("malformed_seed", func(t *testing.T) {
		tests := []string{
			"",
			"01",
			"0000",
			"00374a1ad84d6b7a93e68042c1f850cbb100000000000000000000000000000102030405060708A0", // changed one byte from a good seed
		}

		for i, test := range tests {
			t.Run(strconv.Itoa(i), func(t *testing.T) {
				seed, err := hex.DecodeString(test)
				if err != nil {
					panic(err)
				}

				_, err = challengeParamsFromSeed(seed, secret)
				assert.ErrorIs(t, errMalformedSeed, err)
			})
		}
	})
}

func TestManager(t *testing.T) {
	clock := clock.NewMock(time.Now().Truncate(time.Hour))

	store := NewMemoryStore(clock)
	defer store.Close()

	mgr := NewManager(ManagerParams{
		Clock:            clock,
		Store:            store,
		Secret:           []byte("shhhh"),
		Target:           0x00FFFFFF,
		ChallengeTimeout: 1 * time.Second,
	})

	{
		c := mgr.NewChallenge()
		solution := Solve(c)
		assert.NoError(t, mgr.CheckSolution(c.Seed, solution))

		// doing again should fail, the seed should already be marked as solved
		assert.ErrorIs(t, mgr.CheckSolution(c.Seed, solution), ErrSeedSolved)
	}

	{
		c := mgr.NewChallenge()
		solution := Solve(c)
		clock.Add(2 * time.Second)
		assert.ErrorIs(t, mgr.CheckSolution(c.Seed, solution), ErrExpiredSolution)
	}

}