github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/core/policy/localcopy/oracle_test.go (about) 1 /* 2 * Copyright (C) 2020 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package localcopy 19 20 import ( 21 "fmt" 22 "net/http" 23 "net/http/httptest" 24 "sync" 25 "testing" 26 "time" 27 28 "github.com/mysteriumnetwork/node/market" 29 "github.com/mysteriumnetwork/node/requests" 30 "github.com/stretchr/testify/assert" 31 ) 32 33 func Test_Oracle_Policy(t *testing.T) { 34 repo := &Oracle{fetchURL: "http://policy.localhost"} 35 assert.Equal( 36 t, 37 market.AccessPolicy{ID: "1", Source: "http://policy.localhost/1"}, 38 repo.Policy("1"), 39 ) 40 41 repo = &Oracle{fetchURL: "http://policy.localhost/"} 42 assert.Equal( 43 t, 44 market.AccessPolicy{ID: "2", Source: "http://policy.localhost/2"}, 45 repo.Policy("2"), 46 ) 47 } 48 49 func Test_Oracle_Policies(t *testing.T) { 50 repo := &Oracle{fetchURL: "http://policy.localhost"} 51 assert.Equal( 52 t, 53 []market.AccessPolicy{ 54 {ID: "1", Source: "http://policy.localhost/1"}, 55 }, 56 repo.Policies([]string{"1"}), 57 ) 58 59 repo = &Oracle{fetchURL: "http://policy.localhost/"} 60 assert.Equal( 61 t, 62 []market.AccessPolicy{ 63 {ID: "2", Source: "http://policy.localhost/2"}, 64 {ID: "3", Source: "http://policy.localhost/3"}, 65 }, 66 repo.Policies([]string{"2", "3"}), 67 ) 68 } 69 70 func Test_Oracle_SubscribePolicies_WhenEndpointFails(t *testing.T) { 71 repo := NewRepository() 72 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 73 w.WriteHeader(http.StatusInternalServerError) 74 w.Write([]byte("Something wong")) 75 })) 76 defer server.Close() 77 78 oracle := createEmptyOracle(server.URL) 79 err := oracle.SubscribePolicies( 80 []market.AccessPolicy{oracle.Policy("1"), oracle.Policy("3")}, 81 repo, 82 ) 83 assert.EqualError( 84 t, 85 err, 86 fmt.Sprintf("initial fetch failed: failed to fetch policy rule {1 %s/1}: Something wong", server.URL), 87 ) 88 assert.Equal(t, []market.AccessPolicy{}, repo.Policies()) 89 } 90 91 func Test_Oracle_SubscribePolicies_Race(t *testing.T) { 92 repo := NewRepository() 93 server := mockPolicyServer() 94 defer server.Close() 95 oracle := createEmptyOracle(server.URL) 96 97 var wg sync.WaitGroup 98 wg.Add(2) 99 go func() { 100 defer wg.Done() 101 err := oracle.SubscribePolicies( 102 []market.AccessPolicy{oracle.Policy("1"), oracle.Policy("3")}, 103 repo, 104 ) 105 assert.NoError(t, err) 106 }() 107 go func() { 108 defer wg.Done() 109 err := oracle.SubscribePolicies([]market.AccessPolicy{oracle.Policy("2")}, repo) 110 assert.NoError(t, err) 111 }() 112 wg.Wait() 113 114 assert.Len(t, repo.Rules(), 3) 115 } 116 117 func Test_Oracle_SubscribePolicies_WhenEndpointSucceeds(t *testing.T) { 118 repo := NewRepository() 119 server := mockPolicyServer() 120 defer server.Close() 121 122 oracle := createEmptyOracle(server.URL) 123 err := oracle.SubscribePolicies( 124 []market.AccessPolicy{oracle.Policy("1"), oracle.Policy("3")}, 125 repo, 126 ) 127 assert.NoError(t, err) 128 assert.Equal( 129 t, 130 []market.AccessPolicyRuleSet{policyOneRulesUpdated, policyThreeRulesUpdated}, 131 repo.Rules(), 132 ) 133 134 oracle = createFilledOracle(server.URL, time.Minute, repo) 135 err = oracle.SubscribePolicies( 136 []market.AccessPolicy{oracle.Policy("1"), oracle.Policy("3")}, 137 repo, 138 ) 139 assert.NoError(t, err) 140 141 assert.Equal( 142 t, 143 []market.AccessPolicyRuleSet{policyOneRulesUpdated, policyThreeRulesUpdated, policyTwoRulesUpdated}, 144 repo.Rules(), 145 ) 146 } 147 148 func Test_Oracle_SubscribePolicies_MultipleSubscribers(t *testing.T) { 149 server := mockPolicyServer() 150 defer server.Close() 151 152 oracle := createEmptyOracle(server.URL) 153 154 repo1 := NewRepository() 155 err := oracle.SubscribePolicies(oracle.Policies([]string{"1"}), repo1) 156 assert.NoError(t, err) 157 assert.Equal(t, []market.AccessPolicyRuleSet{policyOneRulesUpdated}, repo1.Rules()) 158 159 repo2 := NewRepository() 160 err = oracle.SubscribePolicies(oracle.Policies([]string{"1"}), repo2) 161 assert.NoError(t, err) 162 assert.Equal(t, []market.AccessPolicyRuleSet{policyOneRulesUpdated}, repo2.Rules()) 163 } 164 165 func Test_Oracle_StartSyncsPolicies(t *testing.T) { 166 repo := NewRepository() 167 server := mockPolicyServer() 168 defer server.Close() 169 170 oracle := createFilledOracle(server.URL, 1*time.Millisecond, repo) 171 go oracle.Start() 172 defer oracle.Stop() 173 174 var policiesRules []market.AccessPolicyRuleSet 175 assert.Eventually(t, func() bool { 176 policiesRules = repo.Rules() 177 return len(policiesRules) == 2 178 }, 2*time.Second, 10*time.Millisecond) 179 assert.Equal(t, []market.AccessPolicyRuleSet{policyOneRulesUpdated, policyTwoRulesUpdated}, policiesRules) 180 } 181 182 func Test_PolicyRepository_StartMultipleTimes(t *testing.T) { 183 oracle := NewOracle( 184 requests.NewHTTPClient("0.0.0.0", time.Second), 185 "http://policy.localhost", 186 time.Minute, 187 true, 188 ) 189 go oracle.Start() 190 oracle.Stop() 191 192 go oracle.Start() 193 oracle.Stop() 194 } 195 196 func createEmptyOracle(mockServerURL string) *Oracle { 197 return NewOracle( 198 requests.NewHTTPClient("0.0.0.0", 100*time.Millisecond), 199 mockServerURL+"/", 200 time.Minute, 201 true, 202 ) 203 } 204 205 func createFilledOracle(mockServerURL string, interval time.Duration, repo *Repository) *Oracle { 206 oracle := NewOracle( 207 requests.NewHTTPClient("0.0.0.0", time.Second), 208 mockServerURL+"/", 209 interval, 210 true, 211 ) 212 oracle.SubscribePolicies( 213 []market.AccessPolicy{oracle.Policy("1"), oracle.Policy("2")}, 214 repo, 215 ) 216 return oracle 217 } 218 219 func mockPolicyServer() *httptest.Server { 220 return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 221 switch r.URL.Path { 222 case "/1": 223 w.WriteHeader(http.StatusOK) 224 _, _ = w.Write([]byte(`{ 225 "id": "1", 226 "title": "One (updated)", 227 "description": "", 228 "allow": [ 229 {"type": "identity", "value": "0x1"} 230 ] 231 }`)) 232 case "/2": 233 w.WriteHeader(http.StatusOK) 234 _, _ = w.Write([]byte(`{ 235 "id": "2", 236 "title": "Two (updated)", 237 "description": "", 238 "allow": [ 239 {"type": "dns_hostname", "value": "ipinfo.io"} 240 ] 241 }`)) 242 case "/3": 243 w.WriteHeader(http.StatusOK) 244 _, _ = w.Write([]byte(`{ 245 "id": "3", 246 "title": "Three (updated)", 247 "description": "", 248 "allow": [ 249 {"type": "dns_zone", "value": "ipinfo.io"} 250 ] 251 }`)) 252 default: 253 w.WriteHeader(http.StatusNotFound) 254 } 255 })) 256 }