github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/fs/hash/hash_test.go (about)

     1  package hash_test
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"log"
     7  	"testing"
     8  
     9  	"github.com/rclone/rclone/fs/hash"
    10  	"github.com/spf13/pflag"
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  // Check it satisfies the interface
    16  var _ pflag.Value = (*hash.Type)(nil)
    17  
    18  func TestHashSet(t *testing.T) {
    19  	var h hash.Set
    20  
    21  	assert.Equal(t, 0, h.Count())
    22  
    23  	a := h.Array()
    24  	assert.Len(t, a, 0)
    25  
    26  	h = h.Add(hash.MD5)
    27  	log.Println(h)
    28  	assert.Equal(t, 1, h.Count())
    29  	assert.Equal(t, hash.MD5, h.GetOne())
    30  	a = h.Array()
    31  	assert.Len(t, a, 1)
    32  	assert.Equal(t, a[0], hash.MD5)
    33  
    34  	// Test overlap, with all hashes
    35  	h = h.Overlap(hash.Supported())
    36  	assert.Equal(t, 1, h.Count())
    37  	assert.Equal(t, hash.MD5, h.GetOne())
    38  	assert.True(t, h.SubsetOf(hash.Supported()))
    39  	assert.True(t, h.SubsetOf(hash.NewHashSet(hash.MD5)))
    40  
    41  	h = h.Add(hash.SHA1)
    42  	assert.Equal(t, 2, h.Count())
    43  	one := h.GetOne()
    44  	if !(one == hash.MD5 || one == hash.SHA1) {
    45  		t.Fatalf("expected to be either MD5 or SHA1, got %v", one)
    46  	}
    47  	assert.True(t, h.SubsetOf(hash.Supported()))
    48  	assert.False(t, h.SubsetOf(hash.NewHashSet(hash.MD5)))
    49  	assert.False(t, h.SubsetOf(hash.NewHashSet(hash.SHA1)))
    50  	assert.True(t, h.SubsetOf(hash.NewHashSet(hash.MD5, hash.SHA1)))
    51  	a = h.Array()
    52  	assert.Len(t, a, 2)
    53  
    54  	ol := h.Overlap(hash.NewHashSet(hash.MD5))
    55  	assert.Equal(t, 1, ol.Count())
    56  	assert.True(t, ol.Contains(hash.MD5))
    57  	assert.False(t, ol.Contains(hash.SHA1))
    58  
    59  	ol = h.Overlap(hash.NewHashSet(hash.MD5, hash.SHA1))
    60  	assert.Equal(t, 2, ol.Count())
    61  	assert.True(t, ol.Contains(hash.MD5))
    62  	assert.True(t, ol.Contains(hash.SHA1))
    63  }
    64  
    65  type hashTest struct {
    66  	input  []byte
    67  	output map[hash.Type]string
    68  }
    69  
    70  var hashTestSet = []hashTest{
    71  	{
    72  		input: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
    73  		output: map[hash.Type]string{
    74  			hash.MD5:       "bf13fc19e5151ac57d4252e0e0f87abe",
    75  			hash.SHA1:      "3ab6543c08a75f292a5ecedac87ec41642d12166",
    76  			hash.Whirlpool: "eddf52133d4566d763f716e853d6e4efbabd29e2c2e63f56747b1596172851d34c2df9944beb6640dbdbe3d9b4eb61180720a79e3d15baff31c91e43d63869a4",
    77  			hash.CRC32:     "a6041d7e",
    78  			hash.SHA256:    "c839e57675862af5c21bd0a15413c3ec579e0d5522dab600bc6c3489b05b8f54",
    79  		},
    80  	},
    81  	// Empty data set
    82  	{
    83  		input: []byte{},
    84  		output: map[hash.Type]string{
    85  			hash.MD5:       "d41d8cd98f00b204e9800998ecf8427e",
    86  			hash.SHA1:      "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    87  			hash.Whirlpool: "19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3",
    88  			hash.CRC32:     "00000000",
    89  			hash.SHA256:    "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    90  		},
    91  	},
    92  }
    93  
    94  func TestMultiHasher(t *testing.T) {
    95  	for _, test := range hashTestSet {
    96  		mh := hash.NewMultiHasher()
    97  		n, err := io.Copy(mh, bytes.NewBuffer(test.input))
    98  		require.NoError(t, err)
    99  		assert.Len(t, test.input, int(n))
   100  		sums := mh.Sums()
   101  		for k, v := range sums {
   102  			expect, ok := test.output[k]
   103  			require.True(t, ok, "test output for hash not found")
   104  			assert.Equal(t, expect, v)
   105  		}
   106  		// Test that all are present
   107  		for k, v := range test.output {
   108  			expect, ok := sums[k]
   109  			require.True(t, ok, "test output for hash not found")
   110  			assert.Equal(t, expect, v)
   111  		}
   112  	}
   113  }
   114  
   115  func TestMultiHasherTypes(t *testing.T) {
   116  	h := hash.SHA1
   117  	for _, test := range hashTestSet {
   118  		mh, err := hash.NewMultiHasherTypes(hash.NewHashSet(h))
   119  		if err != nil {
   120  			t.Fatal(err)
   121  		}
   122  		n, err := io.Copy(mh, bytes.NewBuffer(test.input))
   123  		require.NoError(t, err)
   124  		assert.Len(t, test.input, int(n))
   125  		sums := mh.Sums()
   126  		assert.Len(t, sums, 1)
   127  		assert.Equal(t, sums[h], test.output[h])
   128  	}
   129  }
   130  
   131  func TestHashStream(t *testing.T) {
   132  	for _, test := range hashTestSet {
   133  		sums, err := hash.Stream(bytes.NewBuffer(test.input))
   134  		require.NoError(t, err)
   135  		for k, v := range sums {
   136  			expect, ok := test.output[k]
   137  			require.True(t, ok)
   138  			assert.Equal(t, v, expect)
   139  		}
   140  		// Test that all are present
   141  		for k, v := range test.output {
   142  			expect, ok := sums[k]
   143  			require.True(t, ok)
   144  			assert.Equal(t, v, expect)
   145  		}
   146  	}
   147  }
   148  
   149  func TestHashStreamTypes(t *testing.T) {
   150  	h := hash.SHA1
   151  	for _, test := range hashTestSet {
   152  		sums, err := hash.StreamTypes(bytes.NewBuffer(test.input), hash.NewHashSet(h))
   153  		require.NoError(t, err)
   154  		assert.Len(t, sums, 1)
   155  		assert.Equal(t, sums[h], test.output[h])
   156  	}
   157  }
   158  
   159  func TestHashSetStringer(t *testing.T) {
   160  	h := hash.NewHashSet(hash.SHA1, hash.MD5)
   161  	assert.Equal(t, "[md5, sha1]", h.String())
   162  	h = hash.NewHashSet(hash.SHA1)
   163  	assert.Equal(t, "[sha1]", h.String())
   164  	h = hash.NewHashSet()
   165  	assert.Equal(t, "[]", h.String())
   166  }
   167  
   168  func TestHashStringer(t *testing.T) {
   169  	h := hash.MD5
   170  	assert.Equal(t, "md5", h.String())
   171  	h = hash.SHA1
   172  	assert.Equal(t, "sha1", h.String())
   173  	h = hash.None
   174  	assert.Equal(t, "none", h.String())
   175  }
   176  
   177  func TestHashSetter(t *testing.T) {
   178  	var ht hash.Type
   179  
   180  	assert.NoError(t, ht.Set("none"))
   181  	assert.Equal(t, hash.None, ht)
   182  	assert.NoError(t, ht.Set("None"))
   183  	assert.Equal(t, hash.None, ht)
   184  
   185  	assert.NoError(t, ht.Set("md5"))
   186  	assert.Equal(t, hash.MD5, ht)
   187  	assert.NoError(t, ht.Set("MD5"))
   188  	assert.Equal(t, hash.MD5, ht)
   189  
   190  	assert.NoError(t, ht.Set("sha1"))
   191  	assert.Equal(t, hash.SHA1, ht)
   192  	assert.NoError(t, ht.Set("SHA-1"))
   193  	assert.Equal(t, hash.SHA1, ht)
   194  
   195  	assert.NoError(t, ht.Set("SHA1"))
   196  	assert.Equal(t, hash.SHA1, ht)
   197  	assert.NoError(t, ht.Set("Sha1"))
   198  	assert.Equal(t, hash.SHA1, ht)
   199  	assert.Error(t, ht.Set("Sha-1"))
   200  }
   201  
   202  func TestHashTypeStability(t *testing.T) {
   203  	assert.Equal(t, hash.Type(0), hash.None)
   204  	assert.Equal(t, hash.Type(1), hash.MD5)
   205  	assert.Equal(t, hash.Type(2), hash.SHA1)
   206  
   207  	assert.True(t, hash.Supported().Contains(hash.MD5))
   208  	assert.True(t, hash.Supported().Contains(hash.SHA1))
   209  	assert.False(t, hash.Supported().Contains(hash.None))
   210  }