code.vegaprotocol.io/vega@v0.79.0/core/datasource/spec/adaptors/adaptors_test.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package adaptors_test 17 18 import ( 19 "encoding/hex" 20 "encoding/json" 21 "fmt" 22 "testing" 23 "time" 24 25 "code.vegaprotocol.io/vega/core/datasource/common" 26 "code.vegaprotocol.io/vega/core/datasource/spec" 27 "code.vegaprotocol.io/vega/core/datasource/spec/adaptors" 28 "code.vegaprotocol.io/vega/libs/crypto" 29 commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1" 30 31 "github.com/stretchr/testify/assert" 32 "github.com/stretchr/testify/require" 33 ) 34 35 func TestAdaptors(t *testing.T) { 36 t.Run("Creating adaptors succeeds", testCreatingAdaptorsSucceeds) 37 t.Run("Normalising data from unknown oracle fails", testAdaptorsNormalisingDataFromUnknownOracleFails) 38 t.Run("Normalising data from known oracle succeeds", testAdaptorsNormalisingDataFromKnownOracleSucceeds) 39 t.Run("Validating data should pass if validators return no errors", testAdaptorValidationSuccess) 40 t.Run("Validating data should fail if any validator returns an error", testAdaptorValidationFails) 41 } 42 43 func testCreatingAdaptorsSucceeds(t *testing.T) { 44 // when 45 as := adaptors.New() 46 47 // then 48 assert.NotNil(t, as) 49 } 50 51 func testAdaptorsNormalisingDataFromUnknownOracleFails(t *testing.T) { 52 // given 53 pubKeyB := []byte("0xdeadbeef") 54 pubKey := crypto.NewPublicKey(hex.EncodeToString(pubKeyB), pubKeyB) 55 rawData := commandspb.OracleDataSubmission{ 56 Source: commandspb.OracleDataSubmission_ORACLE_SOURCE_UNSPECIFIED, 57 Payload: dummyOraclePayload(t), 58 } 59 60 // when 61 normalisedData, err := stubbedAdaptors().Normalise(pubKey, rawData) 62 63 // then 64 require.Error(t, err) 65 assert.EqualError(t, err, adaptors.ErrUnknownOracleSource.Error()) 66 assert.Nil(t, normalisedData) 67 } 68 69 func testAdaptorsNormalisingDataFromKnownOracleSucceeds(t *testing.T) { 70 tcs := []struct { 71 name string 72 source commandspb.OracleDataSubmission_OracleSource 73 }{ 74 { 75 name: "with Open Oracle source", 76 source: commandspb.OracleDataSubmission_ORACLE_SOURCE_OPEN_ORACLE, 77 }, { 78 name: "with JSON source", 79 source: commandspb.OracleDataSubmission_ORACLE_SOURCE_JSON, 80 }, 81 } 82 83 for _, tc := range tcs { 84 t.Run(tc.name, func(tt *testing.T) { 85 // given 86 pubKeyB := []byte("0xdeadbeef") 87 pubKey := crypto.NewPublicKey(hex.EncodeToString(pubKeyB), pubKeyB) 88 rawData := commandspb.OracleDataSubmission{ 89 Source: tc.source, 90 Payload: dummyOraclePayload(t), 91 } 92 93 // when 94 normalisedData, err := stubbedAdaptors().Normalise(pubKey, rawData) 95 96 // then 97 require.NoError(t, err) 98 assert.NotNil(t, normalisedData) 99 }) 100 } 101 } 102 103 func stubbedAdaptors() *adaptors.Adaptors { 104 return &adaptors.Adaptors{ 105 Adaptors: map[commandspb.OracleDataSubmission_OracleSource]adaptors.Adaptor{ 106 commandspb.OracleDataSubmission_ORACLE_SOURCE_OPEN_ORACLE: &dummyOracleAdaptor{}, 107 commandspb.OracleDataSubmission_ORACLE_SOURCE_JSON: &dummyOracleAdaptor{}, 108 }, 109 } 110 } 111 112 func dummyOraclePayload(t *testing.T) []byte { 113 t.Helper() 114 payload, err := json.Marshal(map[string]string{ 115 "field_1": "value_1", 116 "field_2": "value_2", 117 }) 118 if err != nil { 119 t.Fatalf("failed to generate random oracle payload in tests: %s", err) 120 } 121 122 return payload 123 } 124 125 func internalOraclePayload(t *testing.T) []byte { 126 t.Helper() 127 payload, err := json.Marshal(map[string]string{ 128 spec.BuiltinTimestamp: fmt.Sprintf("%d", time.Now().UnixNano()), 129 }) 130 if err != nil { 131 t.Fatalf("failed to generate internal oracle payload in tests: %s", err) 132 } 133 134 return payload 135 } 136 137 type dummyOracleAdaptor struct{} 138 139 func (d *dummyOracleAdaptor) Normalise(pk crypto.PublicKey, payload []byte) (*common.Data, error) { 140 var data map[string]string 141 if err := json.Unmarshal(payload, &data); err != nil { 142 return nil, err 143 } 144 145 return &common.Data{ 146 Signers: []*common.Signer{ 147 common.CreateSignerFromString(pk.Hex(), common.SignerTypePubKey), 148 }, 149 Data: data, 150 }, nil 151 } 152 153 func testAdaptorValidationSuccess(t *testing.T) { 154 tcs := []struct { 155 name string 156 source commandspb.OracleDataSubmission_OracleSource 157 }{ 158 { 159 name: "with Open Oracle source", 160 source: commandspb.OracleDataSubmission_ORACLE_SOURCE_OPEN_ORACLE, 161 }, { 162 name: "with JSON source", 163 source: commandspb.OracleDataSubmission_ORACLE_SOURCE_JSON, 164 }, 165 } 166 167 for _, tc := range tcs { 168 t.Run(tc.name, func(tt *testing.T) { 169 // given 170 pubKeyB := []byte("0xdeadbeef") 171 pubKey := crypto.NewPublicKey(hex.EncodeToString(pubKeyB), pubKeyB) 172 rawData := commandspb.OracleDataSubmission{ 173 Source: tc.source, 174 Payload: dummyOraclePayload(t), 175 } 176 177 // when 178 adaptor := stubbedAdaptors() 179 normalisedData, err := adaptor.Normalise(pubKey, rawData) 180 181 // then 182 require.NoError(tt, err) 183 assert.NotNil(tt, normalisedData) 184 }) 185 } 186 } 187 188 func testAdaptorValidationFails(t *testing.T) { 189 tcs := []struct { 190 name string 191 source commandspb.OracleDataSubmission_OracleSource 192 }{ 193 { 194 name: "with Open Oracle source", 195 source: commandspb.OracleDataSubmission_ORACLE_SOURCE_OPEN_ORACLE, 196 }, { 197 name: "with JSON source", 198 source: commandspb.OracleDataSubmission_ORACLE_SOURCE_JSON, 199 }, 200 } 201 202 for _, tc := range tcs { 203 t.Run(tc.name, func(tt *testing.T) { 204 // given 205 pubKeyB := []byte("0xdeadbeef") 206 pubKey := crypto.NewPublicKey(hex.EncodeToString(pubKeyB), pubKeyB) 207 rawData := commandspb.OracleDataSubmission{ 208 Source: tc.source, 209 Payload: internalOraclePayload(tt), 210 } 211 212 // when 213 adaptor := stubbedAdaptors() 214 normalisedData, err := adaptor.Normalise(pubKey, rawData) 215 216 // then 217 require.Error(tt, err) 218 assert.Nil(tt, normalisedData) 219 }) 220 } 221 }