1package libkb 2 3import ( 4 "strings" 5 "testing" 6 7 "github.com/keybase/client/go/msgpack" 8 keybase1 "github.com/keybase/client/go/protocol/keybase1" 9 "github.com/stretchr/testify/require" 10) 11 12// requireErrorHasSuffix makes sure that err's string has 13// expectedErrSuffix's string as a suffix. This is necessary as 14// go-codec prepends stuff to any errors it catches. 15func requireErrorHasSuffix(t *testing.T, expectedErrSuffix, err error) { 16 t.Helper() 17 require.Error(t, err) 18 require.True(t, strings.HasSuffix(err.Error(), expectedErrSuffix.Error()), "Expected %q to have %q as a suffix", err, expectedErrSuffix) 19} 20 21// Test that various ways in which OuterLinkV2WithMetadata may be 22// encoded/decoded all fail. 23 24func TestOuterLinkV2WithMetadataEncode(t *testing.T) { 25 var o OuterLinkV2WithMetadata 26 _, err := msgpack.Encode(o) 27 requireErrorHasSuffix(t, errCodecEncodeSelf, err) 28 _, err = msgpack.Encode(&o) 29 requireErrorHasSuffix(t, errCodecEncodeSelf, err) 30} 31 32func TestOuterLinkV2WithMetadataDecode(t *testing.T) { 33 var o OuterLinkV2WithMetadata 34 err := msgpack.Decode(&o, []byte{0x1, 0x2}) 35 requireErrorHasSuffix(t, errCodecDecodeSelf, err) 36} 37 38type outerLinkV2WithMetadataEmbedder struct { 39 OuterLinkV2WithMetadata 40} 41 42func TestOuterLinkV2WithMetadataEmbedderEncode(t *testing.T) { 43 var o outerLinkV2WithMetadataEmbedder 44 _, err := msgpack.Encode(o) 45 requireErrorHasSuffix(t, errCodecEncodeSelf, err) 46} 47 48func TestOuterLinkV2WithMetadataEmbedderDecode(t *testing.T) { 49 var o outerLinkV2WithMetadataEmbedder 50 err := msgpack.Decode(&o, []byte{0x1, 0x2}) 51 requireErrorHasSuffix(t, errCodecDecodeSelf, err) 52} 53 54type outerLinkV2WithMetadataPointerEmbedder struct { 55 *OuterLinkV2WithMetadata 56} 57 58func TestOuterLinkV2WithMetadataPointerEmbedderEncode(t *testing.T) { 59 o := outerLinkV2WithMetadataPointerEmbedder{ 60 OuterLinkV2WithMetadata: &OuterLinkV2WithMetadata{}, 61 } 62 _, err := msgpack.Encode(o) 63 requireErrorHasSuffix(t, errCodecEncodeSelf, err) 64} 65 66func TestOuterLinkV2WithMetadataPointerEmbedderDecode(t *testing.T) { 67 var o outerLinkV2WithMetadataPointerEmbedder 68 err := msgpack.Decode(&o, []byte{0x1, 0x2}) 69 requireErrorHasSuffix(t, errCodecDecodeSelf, err) 70} 71 72type outerLinkV2WithMetadataContainer struct { 73 O OuterLinkV2WithMetadata 74} 75 76func TestOuterLinkV2WithMetadataContainerEncode(t *testing.T) { 77 var o outerLinkV2WithMetadataContainer 78 _, err := msgpack.Encode(o) 79 requireErrorHasSuffix(t, errCodecEncodeSelf, err) 80} 81 82func TestOuterLinkV2WithMetadataContainerDecode(t *testing.T) { 83 bytes, err := msgpack.Encode(map[string]interface{}{ 84 "O": []byte{0x01, 0x02}, 85 }) 86 require.NoError(t, err) 87 88 var o outerLinkV2WithMetadataContainer 89 err = msgpack.Decode(&o, bytes) 90 requireErrorHasSuffix(t, errCodecDecodeSelf, err) 91} 92 93type outerLinkV2WithMetadataPointerContainer struct { 94 O *OuterLinkV2WithMetadata 95} 96 97func TestOuterLinkV2WithMetadataPointerContainerEncode(t *testing.T) { 98 o := outerLinkV2WithMetadataPointerContainer{ 99 O: &OuterLinkV2WithMetadata{}, 100 } 101 _, err := msgpack.Encode(o) 102 requireErrorHasSuffix(t, errCodecEncodeSelf, err) 103} 104 105func TestOuterLinkV2WithMetadataPointerContainerDecode(t *testing.T) { 106 bytes, err := msgpack.Encode(map[string]interface{}{ 107 "O": []byte{0x01, 0x02}, 108 }) 109 require.NoError(t, err) 110 111 var o outerLinkV2WithMetadataPointerContainer 112 err = msgpack.Decode(&o, bytes) 113 requireErrorHasSuffix(t, errCodecDecodeSelf, err) 114} 115 116func serdeOuterLink(t *testing.T, tc TestContext, seqno keybase1.Seqno, highSkipSeqno *keybase1.Seqno, highSkipHash LinkID) OuterLinkV2 { 117 m := NewMetaContextForTest(tc) 118 119 AddEnvironmentFeatureForTest(tc, EnvironmentFeatureAllowHighSkips) 120 121 var highSkip *HighSkip 122 if highSkipSeqno != nil { 123 highSkipPre := NewHighSkip(*highSkipSeqno, highSkipHash) 124 highSkip = &highSkipPre 125 } 126 encoded, err := encodeOuterLink(m, LinkTypeLeave, seqno, nil, nil, false, keybase1.SeqType_PUBLIC, false, highSkip) 127 require.NoError(t, err) 128 129 o2 := OuterLinkV2{} 130 err = msgpack.Decode(&o2, encoded) 131 require.NoError(t, err) 132 return o2 133} 134 135func highSkipMatch(ol OuterLinkV2, highSkip *HighSkip) error { 136 return ol.AssertFields(ol.Version, ol.Seqno, ol.Prev, ol.Curr, ol.LinkType, ol.SeqType, ol.IgnoreIfUnsupported, highSkip) 137} 138 139func TestHighSkipBackwardsCompatibility(t *testing.T) { 140 tc := SetupTest(t, "test_high_skip_backwards_compatibility", 1) 141 defer tc.Cleanup() 142 143 seqno := keybase1.Seqno(1) 144 highSkipSeqno := keybase1.Seqno(0) 145 146 o := serdeOuterLink(t, tc, seqno, nil, nil) 147 require.True(t, o.HighSkipSeqno == nil) 148 require.True(t, o.HighSkipHash == nil) 149 require.NoError(t, highSkipMatch(o, nil)) 150 151 o = serdeOuterLink(t, tc, seqno, &highSkipSeqno, nil) 152 require.True(t, *o.HighSkipSeqno == 0) 153 require.True(t, o.HighSkipHash == nil) 154 highSkip := NewHighSkip(keybase1.Seqno(0), nil) 155 badHighSkip1 := NewHighSkip(keybase1.Seqno(0), []byte{0, 5, 2}) 156 badHighSkip2 := NewHighSkip(keybase1.Seqno(2), nil) 157 require.NoError(t, highSkipMatch(o, &highSkip)) 158 require.Error(t, highSkipMatch(o, &badHighSkip1)) 159 require.Error(t, highSkipMatch(o, &badHighSkip2)) 160 161 seqno = keybase1.Seqno(10) 162 highSkipSeqno = keybase1.Seqno(5) 163 164 highSkipHash := []byte{0, 6, 2, 42, 123} 165 o = serdeOuterLink(t, tc, seqno, &highSkipSeqno, highSkipHash) 166 highSkip = NewHighSkip(keybase1.Seqno(5), highSkipHash) 167 badHighSkip1 = NewHighSkip(keybase1.Seqno(5), []byte{0, 5, 2}) 168 badHighSkip2 = NewHighSkip(keybase1.Seqno(5), nil) 169 require.NoError(t, highSkipMatch(o, &highSkip)) 170 require.Error(t, highSkipMatch(o, &badHighSkip1)) 171 require.Error(t, highSkipMatch(o, &badHighSkip2)) 172} 173