code.vegaprotocol.io/vega@v0.79.0/core/netparams/values_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 netparams_test 17 18 import ( 19 "encoding/json" 20 "errors" 21 "testing" 22 23 "code.vegaprotocol.io/vega/core/netparams" 24 "code.vegaprotocol.io/vega/libs/num" 25 "code.vegaprotocol.io/vega/protos/vega" 26 27 "github.com/stretchr/testify/assert" 28 "github.com/stretchr/testify/require" 29 ) 30 31 type A struct { 32 S string 33 I int 34 } 35 36 func (a *A) Reset() { *a = A{} } 37 38 type B struct { 39 F float32 40 SS []string 41 } 42 43 func (b *B) Reset() { *b = B{} } 44 45 func TestNegativeUint(t *testing.T) { 46 require.Error(t, errors.New("invalid uint"), netparams.NewUint().Mutable(true).Update("-30")) 47 require.Error(t, errors.New("invalid uint"), netparams.NewUint().Mutable(true).Update("- 30")) 48 require.Error(t, errors.New("invalid uint"), netparams.NewUint().Mutable(true).Update(" - 3 0")) 49 require.NoError(t, netparams.NewUint().Mutable(true).Update("30")) 50 } 51 52 func TestJSONValues(t *testing.T) { 53 validator := func(v interface{}, p interface{}) error { 54 a, ok := v.(*A) 55 if !ok { 56 return errors.New("invalid type") 57 } 58 59 if len(a.S) <= 0 { 60 return errors.New("empty string") 61 } 62 if a.I < 0 { 63 return errors.New("I negative") 64 } 65 66 b := &A{} 67 json.Unmarshal([]byte(p.(string)), b) 68 69 if !ok { 70 return errors.New("invalid type B") 71 } 72 73 if a.I < b.I { 74 return errors.New("cannot amended to lower value") 75 } 76 77 return nil 78 } 79 80 // happy case, all good 81 j := netparams.NewJSON(&A{}, validator).Mutable(true).MustUpdate(`{"s": "notempty", "i": 42}`) 82 assert.NotNil(t, j) 83 err := j.Validate(`{"s": "notempty", "i": 84}`) 84 assert.NoError(t, err) 85 86 err = j.Update(`{"s": "notempty", "i": 84}`) 87 assert.NoError(t, err) 88 89 a := &A{} 90 err = j.ToJSONStruct(a) 91 assert.NoError(t, err) 92 93 assert.Equal(t, a.I, 84) 94 assert.Equal(t, a.S, "notempty") 95 96 // errors cases now 97 98 // invalid field 99 err = j.Validate(`{"s": "notempty", "i": 84, "nope": 3.2}`) 100 assert.EqualError(t, err, "unable to unmarshal value, json: unknown field \"nope\"") 101 102 err = j.Update(`{"s": "notempty", "i": 84, "nope": 3.2}`) 103 assert.EqualError(t, err, "unable to unmarshal value, json: unknown field \"nope\"") 104 105 // invalid type 106 b := &B{} 107 err = j.ToJSONStruct(b) 108 assert.EqualError(t, err, "incompatible type") 109 110 // valid type, field validation failed 111 err = j.Update(`{"s": "", "i": 84}`) 112 assert.EqualError(t, err, "empty string") 113 114 // flex rule that prevents update to a lower value of i 115 err = j.Validate(`{"s": "notempty", "i": 1}`) 116 assert.EqualError(t, err, "cannot amended to lower value") 117 } 118 119 func TestJSONVPriceMonitoringParameters(t *testing.T) { 120 // happy case, populated parameters array 121 validPmJSONString := `{"triggers": [{"horizon": 60, "probability": "0.95", "auction_extension": 90},{"horizon": 120, "probability": "0.99", "auction_extension": 180}]}` 122 j := netparams.NewJSON(&vega.PriceMonitoringParameters{}, netparams.PriceMonitoringParametersValidation).Mutable(true).MustUpdate(validPmJSONString) 123 assert.NotNil(t, j) 124 err := j.Validate(validPmJSONString) 125 assert.NoError(t, err) 126 127 err = j.Update(validPmJSONString) 128 assert.NoError(t, err) 129 130 pm := &vega.PriceMonitoringParameters{} 131 err = j.ToJSONStruct(pm) 132 assert.NoError(t, err) 133 134 assert.Equal(t, 2, len(pm.Triggers)) 135 assert.Equal(t, int64(60), pm.Triggers[0].Horizon) 136 assert.Equal(t, "0.95", pm.Triggers[0].Probability) 137 assert.Equal(t, int64(90), pm.Triggers[0].AuctionExtension) 138 assert.Equal(t, int64(120), pm.Triggers[1].Horizon) 139 assert.Equal(t, "0.99", pm.Triggers[1].Probability) 140 assert.Equal(t, int64(180), pm.Triggers[1].AuctionExtension) 141 142 // happy case, empty parameters array 143 validPmJSONString = `{"triggers": []}` 144 j = netparams.NewJSON(&vega.PriceMonitoringParameters{}, netparams.PriceMonitoringParametersValidation).Mutable(true).MustUpdate(validPmJSONString) 145 assert.NotNil(t, j) 146 err = j.Validate(validPmJSONString) 147 assert.NoError(t, err) 148 149 err = j.Update(validPmJSONString) 150 assert.NoError(t, err) 151 152 pm = &vega.PriceMonitoringParameters{} 153 err = j.ToJSONStruct(pm) 154 assert.NoError(t, err) 155 156 assert.Equal(t, 0, len(pm.Triggers)) 157 158 // errors cases now 159 160 // invalid field 161 invalidPmJSONString := `{"triggers": [{"horizon": 60, "probability": "0.95", "auction_extension": 90},{"horizon": 120, "probability": "0.99", "auction_extension": 180, "nope": "abc"}]}` 162 expectedErrorMsg := "unable to unmarshal value, json: unknown field \"nope\"" 163 err = j.Validate(invalidPmJSONString) 164 assert.EqualError(t, err, expectedErrorMsg) 165 166 err = j.Update(invalidPmJSONString) 167 assert.EqualError(t, err, expectedErrorMsg) 168 169 // invalid value 170 171 // horizon 172 invalidPmJSONString = `{"triggers": [{"horizon": 0, "probability": "0.95", "auction_extension": 90},{"horizon": 120, "probability": "0.99", "auction_extension": 180}]}` 173 expectedErrorMsg = "triggers.horizon must be greater than `0`, got `0`" 174 err = j.Validate(invalidPmJSONString) 175 assert.EqualError(t, err, expectedErrorMsg) 176 177 err = j.Update(invalidPmJSONString) 178 assert.EqualError(t, err, expectedErrorMsg) 179 180 // probability 181 invalidPmJSONString = `{"triggers": [{"horizon": 60, "probability": "0", "auction_extension": 90},{"horizon": 120, "probability": "0.99", "auction_extension": 180}]}` 182 expectedErrorMsg = "triggers.probability must be greater than `0`, got `0`" 183 err = j.Validate(invalidPmJSONString) 184 assert.EqualError(t, err, expectedErrorMsg) 185 186 err = j.Update(invalidPmJSONString) 187 assert.EqualError(t, err, expectedErrorMsg) 188 189 invalidPmJSONString = `{"triggers": [{"horizon": 60, "probability": "1", "auction_extension": 90},{"horizon": 120, "probability": "0.99", "auction_extension": 180}]}` 190 expectedErrorMsg = "triggers.probability must be lower than `1`, got `1`" 191 err = j.Validate(invalidPmJSONString) 192 assert.EqualError(t, err, expectedErrorMsg) 193 194 err = j.Update(invalidPmJSONString) 195 assert.EqualError(t, err, expectedErrorMsg) 196 197 // auctionExtension 198 invalidPmJSONString = `{"triggers": [{"horizon": 60, "probability": "0.95", "auction_extension": 0},{"horizon": 120, "probability": "0.99", "auction_extension": 180}]}` 199 expectedErrorMsg = "triggers.auction_extension must be greater than `0`, got `0`" 200 err = j.Validate(invalidPmJSONString) 201 assert.EqualError(t, err, expectedErrorMsg) 202 } 203 204 func TestDependent(t *testing.T) { 205 u1 := netparams.NewUint(netparams.UintGTE(num.NewUint(1)), netparams.UintLTE(num.NewUint(1000))).Mutable(true).MustUpdate("500") 206 u2 := netparams.NewUint(netparams.UintGTE(num.NewUint(1)), netparams.UintLTE(num.NewUint(1000))).Mutable(true).MustUpdate("100") 207 // we want to enforce u1 >= 2x u2 208 u1.AddRules(netparams.UintDependentGTE("u2", u2, num.MustDecimalFromString("2"))) 209 u2.AddRules(netparams.UintDependentLTE("u1", u1, num.MustDecimalFromString("0.5"))) 210 211 // try to update u1 to less than 2 * u2 212 require.Equal(t, "expect >= 200 (u2 * 2) got 100", u1.Update("100").Error()) 213 require.NoError(t, u1.Update("200")) 214 215 // try to update u2 to more than 0.5 u1 216 require.Equal(t, "expect <= 100 (u1 * 0.5) got 101", u2.Update("101").Error()) 217 require.NoError(t, u2.Update("99")) 218 }