get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/server/accounts_test.go (about) 1 // Copyright 2018-2023 The NATS Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package server 15 16 import ( 17 "encoding/base64" 18 "encoding/json" 19 "fmt" 20 "net/http" 21 "strconv" 22 "strings" 23 "sync" 24 "sync/atomic" 25 "testing" 26 "time" 27 28 "github.com/nats-io/jwt/v2" 29 "github.com/nats-io/nats.go" 30 "github.com/nats-io/nkeys" 31 ) 32 33 func simpleAccountServer(t *testing.T) (*Server, *Account, *Account) { 34 opts := defaultServerOptions 35 s := New(&opts) 36 37 // Now create two accounts. 38 f, err := s.RegisterAccount("$foo") 39 if err != nil { 40 t.Fatalf("Error creating account 'foo': %v", err) 41 } 42 b, err := s.RegisterAccount("$bar") 43 if err != nil { 44 t.Fatalf("Error creating account 'bar': %v", err) 45 } 46 return s, f, b 47 } 48 49 func TestRegisterDuplicateAccounts(t *testing.T) { 50 s, _, _ := simpleAccountServer(t) 51 if _, err := s.RegisterAccount("$foo"); err == nil { 52 t.Fatal("Expected an error registering 'foo' twice") 53 } 54 } 55 56 func TestAccountIsolation(t *testing.T) { 57 s, fooAcc, barAcc := simpleAccountServer(t) 58 cfoo, crFoo, _ := newClientForServer(s) 59 defer cfoo.close() 60 if err := cfoo.registerWithAccount(fooAcc); err != nil { 61 t.Fatalf("Error register client with 'foo' account: %v", err) 62 } 63 cbar, crBar, _ := newClientForServer(s) 64 defer cbar.close() 65 if err := cbar.registerWithAccount(barAcc); err != nil { 66 t.Fatalf("Error register client with 'bar' account: %v", err) 67 } 68 69 // Make sure they are different accounts/sl. 70 if cfoo.acc == cbar.acc { 71 t.Fatalf("Error, accounts the same for both clients") 72 } 73 74 // Now do quick test that makes sure messages do not cross over. 75 // setup bar as a foo subscriber. 76 cbar.parseAsync("SUB foo 1\r\nPING\r\nPING\r\n") 77 l, err := crBar.ReadString('\n') 78 if err != nil { 79 t.Fatalf("Error for client 'bar' from server: %v", err) 80 } 81 if !strings.HasPrefix(l, "PONG\r\n") { 82 t.Fatalf("PONG response incorrect: %q", l) 83 } 84 85 cfoo.parseAsync("SUB foo 1\r\nPUB foo 5\r\nhello\r\nPING\r\n") 86 l, err = crFoo.ReadString('\n') 87 if err != nil { 88 t.Fatalf("Error for client 'foo' from server: %v", err) 89 } 90 91 matches := msgPat.FindAllStringSubmatch(l, -1)[0] 92 if matches[SUB_INDEX] != "foo" { 93 t.Fatalf("Did not get correct subject: '%s'\n", matches[SUB_INDEX]) 94 } 95 if matches[SID_INDEX] != "1" { 96 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 97 } 98 checkPayload(crFoo, []byte("hello\r\n"), t) 99 100 // Now make sure nothing shows up on bar. 101 l, err = crBar.ReadString('\n') 102 if err != nil { 103 t.Fatalf("Error for client 'bar' from server: %v", err) 104 } 105 if !strings.HasPrefix(l, "PONG\r\n") { 106 t.Fatalf("PONG response incorrect: %q", l) 107 } 108 } 109 110 func TestAccountIsolationExportImport(t *testing.T) { 111 checkIsolation := func(t *testing.T, pubSubj string, ncExp, ncImp *nats.Conn) { 112 // We keep track of 2 subjects. 113 // One subject (pubSubj) is based off the stream import. 114 // The other subject "fizz" is not imported and should be isolated. 115 116 gotSubjs := map[string]int{ 117 pubSubj: 0, 118 "fizz": 0, 119 } 120 count := int32(0) 121 ch := make(chan struct{}, 1) 122 if _, err := ncImp.Subscribe(">", func(m *nats.Msg) { 123 gotSubjs[m.Subject] += 1 124 if n := atomic.AddInt32(&count, 1); n == 3 { 125 ch <- struct{}{} 126 } 127 }); err != nil { 128 t.Fatalf("Error on subscribe: %v", err) 129 } 130 // Since both prod and cons use same server, flushing here will ensure 131 // that the interest is registered and known at the time we publish. 132 ncImp.Flush() 133 134 if err := ncExp.Publish(pubSubj, []byte(fmt.Sprintf("ncExp pub %s", pubSubj))); err != nil { 135 t.Fatal(err) 136 } 137 if err := ncImp.Publish(pubSubj, []byte(fmt.Sprintf("ncImp pub %s", pubSubj))); err != nil { 138 t.Fatal(err) 139 } 140 141 if err := ncExp.Publish("fizz", []byte("ncExp pub fizz")); err != nil { 142 t.Fatal(err) 143 } 144 if err := ncImp.Publish("fizz", []byte("ncImp pub fizz")); err != nil { 145 t.Fatal(err) 146 } 147 148 wantSubjs := map[string]int{ 149 // Subscriber ncImp should receive publishes from ncExp and ncImp. 150 pubSubj: 2, 151 // Subscriber ncImp should only receive the publish from ncImp. 152 "fizz": 1, 153 } 154 155 // Wait for at least the 3 expected messages 156 select { 157 case <-ch: 158 case <-time.After(time.Second): 159 t.Fatalf("Expected 3 messages, got %v", atomic.LoadInt32(&count)) 160 } 161 // But now wait a bit to see if subscription receives more than expected. 162 time.Sleep(50 * time.Millisecond) 163 164 if got, want := len(gotSubjs), len(wantSubjs); got != want { 165 t.Fatalf("unexpected subjs len, got=%d; want=%d", got, want) 166 } 167 168 for key, gotCnt := range gotSubjs { 169 if wantCnt := wantSubjs[key]; gotCnt != wantCnt { 170 t.Errorf("unexpected receive count for subject %q, got=%d, want=%d", key, gotCnt, wantCnt) 171 } 172 } 173 } 174 175 cases := []struct { 176 name string 177 exp, imp string 178 pubSubj string 179 }{ 180 { 181 name: "export literal, import literal", 182 exp: "foo", imp: "foo", 183 pubSubj: "foo", 184 }, 185 { 186 name: "export full wildcard, import literal", 187 exp: "foo.>", imp: "foo.bar", 188 pubSubj: "foo.bar", 189 }, 190 { 191 name: "export full wildcard, import sublevel full wildcard", 192 exp: "foo.>", imp: "foo.bar.>", 193 pubSubj: "foo.bar.whizz", 194 }, 195 { 196 name: "export full wildcard, import full wildcard", 197 exp: "foo.>", imp: "foo.>", 198 pubSubj: "foo.bar", 199 }, 200 { 201 name: "export partial wildcard, import partial wildcard", 202 exp: "foo.*", imp: "foo.*", 203 pubSubj: "foo.bar", 204 }, 205 { 206 name: "export mid partial wildcard, import mid partial wildcard", 207 exp: "foo.*.bar", imp: "foo.*.bar", 208 pubSubj: "foo.whizz.bar", 209 }, 210 } 211 for _, c := range cases { 212 t.Run(fmt.Sprintf("%s jwt", c.name), func(t *testing.T) { 213 // Setup NATS server. 214 s := opTrustBasicSetup() 215 defer s.Shutdown() 216 s.Start() 217 if err := s.readyForConnections(5 * time.Second); err != nil { 218 t.Fatal(err) 219 } 220 buildMemAccResolver(s) 221 222 // Setup exporter account. 223 accExpPair, accExpPub := createKey(t) 224 accExpClaims := jwt.NewAccountClaims(accExpPub) 225 if c.exp != "" { 226 accExpClaims.Limits.WildcardExports = true 227 accExpClaims.Exports.Add(&jwt.Export{ 228 Name: fmt.Sprintf("%s-stream-export", c.exp), 229 Subject: jwt.Subject(c.exp), 230 Type: jwt.Stream, 231 }) 232 } 233 accExpJWT, err := accExpClaims.Encode(oKp) 234 require_NoError(t, err) 235 addAccountToMemResolver(s, accExpPub, accExpJWT) 236 237 // Setup importer account. 238 accImpPair, accImpPub := createKey(t) 239 accImpClaims := jwt.NewAccountClaims(accImpPub) 240 if c.imp != "" { 241 accImpClaims.Imports.Add(&jwt.Import{ 242 Name: fmt.Sprintf("%s-stream-import", c.imp), 243 Subject: jwt.Subject(c.imp), 244 Account: accExpPub, 245 Type: jwt.Stream, 246 }) 247 } 248 accImpJWT, err := accImpClaims.Encode(oKp) 249 require_NoError(t, err) 250 addAccountToMemResolver(s, accImpPub, accImpJWT) 251 252 // Connect with different accounts. 253 ncExp := natsConnect(t, s.ClientURL(), createUserCreds(t, nil, accExpPair), 254 nats.Name(fmt.Sprintf("nc-exporter-%s", c.exp))) 255 defer ncExp.Close() 256 ncImp := natsConnect(t, s.ClientURL(), createUserCreds(t, nil, accImpPair), 257 nats.Name(fmt.Sprintf("nc-importer-%s", c.imp))) 258 defer ncImp.Close() 259 260 checkIsolation(t, c.pubSubj, ncExp, ncImp) 261 if t.Failed() { 262 t.Logf("exported=%q; imported=%q", c.exp, c.imp) 263 } 264 }) 265 266 t.Run(fmt.Sprintf("%s conf", c.name), func(t *testing.T) { 267 // Setup NATS server. 268 cf := createConfFile(t, []byte(fmt.Sprintf(` 269 port: -1 270 271 accounts: { 272 accExp: { 273 users: [{user: accExp, password: accExp}] 274 exports: [{stream: %q}] 275 } 276 accImp: { 277 users: [{user: accImp, password: accImp}] 278 imports: [{stream: {account: accExp, subject: %q}}] 279 } 280 } 281 `, 282 c.exp, c.imp, 283 ))) 284 s, _ := RunServerWithConfig(cf) 285 defer s.Shutdown() 286 287 // Connect with different accounts. 288 ncExp := natsConnect(t, s.ClientURL(), nats.UserInfo("accExp", "accExp"), 289 nats.Name(fmt.Sprintf("nc-exporter-%s", c.exp))) 290 defer ncExp.Close() 291 ncImp := natsConnect(t, s.ClientURL(), nats.UserInfo("accImp", "accImp"), 292 nats.Name(fmt.Sprintf("nc-importer-%s", c.imp))) 293 defer ncImp.Close() 294 295 checkIsolation(t, c.pubSubj, ncExp, ncImp) 296 if t.Failed() { 297 t.Logf("exported=%q; imported=%q", c.exp, c.imp) 298 } 299 }) 300 } 301 } 302 303 func TestMultiAccountsIsolation(t *testing.T) { 304 conf := createConfFile(t, []byte(` 305 listen: 127.0.0.1:-1 306 accounts: { 307 PUBLIC: { 308 users:[{user: public, password: public}] 309 exports: [ 310 { stream: orders.client.stream.> } 311 { stream: orders.client2.stream.> } 312 ] 313 } 314 CLIENT: { 315 users:[{user: client, password: client}] 316 imports: [ 317 { stream: { account: PUBLIC, subject: orders.client.stream.> }} 318 ] 319 } 320 CLIENT2: { 321 users:[{user: client2, password: client2}] 322 imports: [ 323 { stream: { account: PUBLIC, subject: orders.client2.stream.> }} 324 ] 325 } 326 }`)) 327 328 s, _ := RunServerWithConfig(conf) 329 if config := s.JetStreamConfig(); config != nil { 330 defer removeDir(t, config.StoreDir) 331 } 332 defer s.Shutdown() 333 334 // Create a connection for CLIENT and subscribe on orders.> 335 clientnc := natsConnect(t, s.ClientURL(), nats.UserInfo("client", "client")) 336 defer clientnc.Close() 337 338 clientsub := natsSubSync(t, clientnc, "orders.>") 339 natsFlush(t, clientnc) 340 341 // Now same for CLIENT2. 342 client2nc := natsConnect(t, s.ClientURL(), nats.UserInfo("client2", "client2")) 343 defer client2nc.Close() 344 345 client2sub := natsSubSync(t, client2nc, "orders.>") 346 natsFlush(t, client2nc) 347 348 // Now create a connection for PUBLIC 349 publicnc := natsConnect(t, s.ClientURL(), nats.UserInfo("public", "public")) 350 defer publicnc.Close() 351 // Publish on 'orders.client.stream.entry', so only CLIENT should receive it. 352 natsPub(t, publicnc, "orders.client.stream.entry", []byte("test1")) 353 354 // Verify that clientsub gets it. 355 msg := natsNexMsg(t, clientsub, time.Second) 356 require_Equal(t, string(msg.Data), "test1") 357 358 // And also verify that client2sub does NOT get it. 359 _, err := client2sub.NextMsg(100 * time.Microsecond) 360 require_Error(t, err, nats.ErrTimeout) 361 362 clientsub.Unsubscribe() 363 natsFlush(t, clientnc) 364 client2sub.Unsubscribe() 365 natsFlush(t, client2nc) 366 367 // Now have both accounts subscribe to "orders.*.stream.entry" 368 clientsub = natsSubSync(t, clientnc, "orders.*.stream.entry") 369 natsFlush(t, clientnc) 370 371 client2sub = natsSubSync(t, client2nc, "orders.*.stream.entry") 372 natsFlush(t, client2nc) 373 374 // Using the PUBLIC account, publish on the "CLIENT" subject 375 natsPub(t, publicnc, "orders.client.stream.entry", []byte("test2")) 376 natsFlush(t, publicnc) 377 378 msg = natsNexMsg(t, clientsub, time.Second) 379 require_Equal(t, string(msg.Data), "test2") 380 381 _, err = client2sub.NextMsg(100 * time.Microsecond) 382 require_Error(t, err, nats.ErrTimeout) 383 } 384 385 func TestAccountFromOptions(t *testing.T) { 386 opts := defaultServerOptions 387 opts.Accounts = []*Account{NewAccount("foo"), NewAccount("bar")} 388 s := New(&opts) 389 defer s.Shutdown() 390 391 ta := s.numReservedAccounts() + 2 392 if la := s.numAccounts(); la != ta { 393 t.Fatalf("Expected to have a server with %d active accounts, got %v", ta, la) 394 } 395 // Check that sl is filled in. 396 fooAcc, _ := s.LookupAccount("foo") 397 barAcc, _ := s.LookupAccount("bar") 398 if fooAcc == nil || barAcc == nil { 399 t.Fatalf("Error retrieving accounts for 'foo' and 'bar'") 400 } 401 if fooAcc.sl == nil || barAcc.sl == nil { 402 t.Fatal("Expected Sublists to be filled in on Opts.Accounts") 403 } 404 } 405 406 // Clients used to be able to ask that the account be forced to be new. 407 // This was for dynamic sandboxes for demo environments but was never really used. 408 // Make sure it always errors if set. 409 func TestNewAccountAndRequireNewAlwaysError(t *testing.T) { 410 conf := createConfFile(t, []byte(` 411 listen: 127.0.0.1:-1 412 accounts: { 413 A: { users: [ {user: ua, password: pa} ] }, 414 B: { users: [ {user: ub, password: pb} ] }, 415 } 416 `)) 417 418 s, _ := RunServerWithConfig(conf) 419 defer s.Shutdown() 420 421 // Success case 422 c, _, _ := newClientForServer(s) 423 connectOp := "CONNECT {\"user\":\"ua\", \"pass\":\"pa\"}\r\n" 424 err := c.parse([]byte(connectOp)) 425 require_NoError(t, err) 426 c.close() 427 428 // Simple cases, any setting of account or new_account always errors. 429 // Even with proper auth. 430 c, cr, _ := newClientForServer(s) 431 connectOp = "CONNECT {\"user\":\"ua\", \"pass\":\"pa\", \"account\":\"ANY\"}\r\n" 432 c.parseAsync(connectOp) 433 l, _ := cr.ReadString('\n') 434 if !strings.HasPrefix(l, "-ERR 'Authorization Violation'") { 435 t.Fatalf("Expected an error, got %q", l) 436 } 437 c.close() 438 439 // new_account with proper credentials. 440 c, cr, _ = newClientForServer(s) 441 connectOp = "CONNECT {\"user\":\"ua\", \"pass\":\"pa\", \"new_account\":true}\r\n" 442 c.parseAsync(connectOp) 443 l, _ = cr.ReadString('\n') 444 if !strings.HasPrefix(l, "-ERR 'Authorization Violation'") { 445 t.Fatalf("Expected an error, got %q", l) 446 } 447 c.close() 448 449 // switch acccounts with proper credentials. 450 c, cr, _ = newClientForServer(s) 451 connectOp = "CONNECT {\"user\":\"ua\", \"pass\":\"pa\", \"account\":\"B\"}\r\n" 452 c.parseAsync(connectOp) 453 l, _ = cr.ReadString('\n') 454 if !strings.HasPrefix(l, "-ERR 'Authorization Violation'") { 455 t.Fatalf("Expected an error, got %q", l) 456 } 457 c.close() 458 459 // Even if correct account designation, still make sure we error. 460 c, cr, _ = newClientForServer(s) 461 connectOp = "CONNECT {\"user\":\"ua\", \"pass\":\"pa\", \"account\":\"A\"}\r\n" 462 c.parseAsync(connectOp) 463 l, _ = cr.ReadString('\n') 464 if !strings.HasPrefix(l, "-ERR 'Authorization Violation'") { 465 t.Fatalf("Expected an error, got %q", l) 466 } 467 c.close() 468 } 469 470 func accountNameExists(name string, accounts []*Account) bool { 471 for _, acc := range accounts { 472 if strings.Compare(acc.Name, name) == 0 { 473 return true 474 } 475 } 476 return false 477 } 478 479 func TestAccountSimpleConfig(t *testing.T) { 480 cfg1 := ` 481 accounts = [foo, bar] 482 ` 483 484 confFileName := createConfFile(t, []byte(cfg1)) 485 opts, err := ProcessConfigFile(confFileName) 486 if err != nil { 487 t.Fatalf("Received an error processing config file: %v", err) 488 } 489 if la := len(opts.Accounts); la != 2 { 490 t.Fatalf("Expected to see 2 accounts in opts, got %d", la) 491 } 492 if !accountNameExists("foo", opts.Accounts) { 493 t.Fatal("Expected a 'foo' account") 494 } 495 if !accountNameExists("bar", opts.Accounts) { 496 t.Fatal("Expected a 'bar' account") 497 } 498 499 cfg2 := ` 500 accounts = [foo, foo] 501 ` 502 503 // Make sure double entries is an error. 504 confFileName = createConfFile(t, []byte(cfg2)) 505 _, err = ProcessConfigFile(confFileName) 506 if err == nil { 507 t.Fatalf("Expected an error with double account entries") 508 } 509 } 510 511 func TestAccountParseConfig(t *testing.T) { 512 traceDest := "my.trace.dest" 513 traceSampling := 50 514 confFileName := createConfFile(t, []byte(fmt.Sprintf(` 515 accounts { 516 synadia { 517 users = [ 518 {user: alice, password: foo} 519 {user: bob, password: bar} 520 ] 521 } 522 nats.io { 523 msg_trace: {dest: %q, sampling: %d%%} 524 users = [ 525 {user: derek, password: foo} 526 {user: ivan, password: bar} 527 ] 528 } 529 } 530 `, traceDest, traceSampling))) 531 opts, err := ProcessConfigFile(confFileName) 532 if err != nil { 533 t.Fatalf("Received an error processing config file: %v", err) 534 } 535 536 if la := len(opts.Accounts); la != 2 { 537 t.Fatalf("Expected to see 2 accounts in opts, got %d", la) 538 } 539 540 if lu := len(opts.Users); lu != 4 { 541 t.Fatalf("Expected 4 total Users, got %d", lu) 542 } 543 544 var natsAcc *Account 545 for _, acc := range opts.Accounts { 546 if acc.Name == "nats.io" { 547 natsAcc = acc 548 break 549 } 550 } 551 if natsAcc == nil { 552 t.Fatalf("Error retrieving account for 'nats.io'") 553 } 554 td, tds := natsAcc.getTraceDestAndSampling() 555 require_Equal[string](t, td, traceDest) 556 require_Equal[int](t, tds, traceSampling) 557 558 for _, u := range opts.Users { 559 if u.Username == "derek" { 560 if u.Account != natsAcc { 561 t.Fatalf("Expected to see the 'nats.io' account, but received %+v", u.Account) 562 } 563 } 564 } 565 } 566 567 func TestAccountParseConfigDuplicateUsers(t *testing.T) { 568 confFileName := createConfFile(t, []byte(` 569 accounts { 570 synadia { 571 users = [ 572 {user: alice, password: foo} 573 {user: bob, password: bar} 574 ] 575 } 576 nats.io { 577 users = [ 578 {user: alice, password: bar} 579 ] 580 } 581 } 582 `)) 583 _, err := ProcessConfigFile(confFileName) 584 if err == nil { 585 t.Fatalf("Expected an error with double user entries") 586 } 587 } 588 589 func TestAccountParseConfigImportsExports(t *testing.T) { 590 opts, err := ProcessConfigFile("./configs/accounts.conf") 591 if err != nil { 592 t.Fatal("parsing failed: ", err) 593 } 594 if la := len(opts.Accounts); la != 3 { 595 t.Fatalf("Expected to see 3 accounts in opts, got %d", la) 596 } 597 if lu := len(opts.Nkeys); lu != 4 { 598 t.Fatalf("Expected 4 total Nkey users, got %d", lu) 599 } 600 if lu := len(opts.Users); lu != 0 { 601 t.Fatalf("Expected no Users, got %d", lu) 602 } 603 var natsAcc, synAcc *Account 604 for _, acc := range opts.Accounts { 605 if acc.Name == "nats.io" { 606 natsAcc = acc 607 } else if acc.Name == "synadia" { 608 synAcc = acc 609 } 610 } 611 if natsAcc == nil { 612 t.Fatalf("Error retrieving account for 'nats.io'") 613 } 614 if natsAcc.Nkey != "AB5UKNPVHDWBP5WODG742274I3OGY5FM3CBIFCYI4OFEH7Y23GNZPXFE" { 615 t.Fatalf("Expected nats account to have an nkey, got %q\n", natsAcc.Nkey) 616 } 617 // Check user assigned to the correct account. 618 for _, nk := range opts.Nkeys { 619 if nk.Nkey == "UBRYMDSRTC6AVJL6USKKS3FIOE466GMEU67PZDGOWYSYHWA7GSKO42VW" { 620 if nk.Account != natsAcc { 621 t.Fatalf("Expected user to be associated with natsAcc, got %q\n", nk.Account.Name) 622 } 623 break 624 } 625 } 626 627 // Now check for the imports and exports of streams and services. 628 if lis := len(natsAcc.imports.streams); lis != 2 { 629 t.Fatalf("Expected 2 imported streams, got %d\n", lis) 630 } 631 for _, si := range natsAcc.imports.streams { 632 if si.from == "public.synadia" { 633 require_True(t, si.atrc) 634 } else { 635 require_False(t, si.atrc) 636 } 637 } 638 if lis := len(natsAcc.imports.services); lis != 1 { 639 t.Fatalf("Expected 1 imported service, got %d\n", lis) 640 } 641 if les := len(natsAcc.exports.services); les != 4 { 642 t.Fatalf("Expected 4 exported services, got %d\n", les) 643 } 644 if les := len(natsAcc.exports.streams); les != 0 { 645 t.Fatalf("Expected no exported streams, got %d\n", les) 646 } 647 648 ea := natsAcc.exports.services["nats.time"] 649 if ea == nil { 650 t.Fatalf("Expected to get a non-nil exportAuth for service") 651 } 652 if ea.respType != Streamed { 653 t.Fatalf("Expected to get a Streamed response type, got %q", ea.respType) 654 } 655 require_True(t, ea.atrc) 656 ea = natsAcc.exports.services["nats.photo"] 657 if ea == nil { 658 t.Fatalf("Expected to get a non-nil exportAuth for service") 659 } 660 if ea.respType != Chunked { 661 t.Fatalf("Expected to get a Chunked response type, got %q", ea.respType) 662 } 663 require_False(t, ea.atrc) 664 ea = natsAcc.exports.services["nats.add"] 665 if ea == nil { 666 t.Fatalf("Expected to get a non-nil exportAuth for service") 667 } 668 if ea.respType != Singleton { 669 t.Fatalf("Expected to get a Singleton response type, got %q", ea.respType) 670 } 671 require_True(t, ea.atrc) 672 673 if synAcc == nil { 674 t.Fatalf("Error retrieving account for 'synadia'") 675 } 676 677 if lis := len(synAcc.imports.streams); lis != 0 { 678 t.Fatalf("Expected no imported streams, got %d\n", lis) 679 } 680 if lis := len(synAcc.imports.services); lis != 1 { 681 t.Fatalf("Expected 1 imported service, got %d\n", lis) 682 } 683 if les := len(synAcc.exports.services); les != 2 { 684 t.Fatalf("Expected 2 exported service, got %d\n", les) 685 } 686 if les := len(synAcc.exports.streams); les != 2 { 687 t.Fatalf("Expected 2 exported streams, got %d\n", les) 688 } 689 } 690 691 func TestImportExportConfigFailures(t *testing.T) { 692 // Import from unknow account 693 cf := createConfFile(t, []byte(` 694 accounts { 695 nats.io { 696 imports = [{stream: {account: "synadia", subject:"foo"}}] 697 } 698 } 699 `)) 700 if _, err := ProcessConfigFile(cf); err == nil { 701 t.Fatalf("Expected an error with import from unknown account") 702 } 703 // Import a service with no account. 704 cf = createConfFile(t, []byte(` 705 accounts { 706 nats.io { 707 imports = [{service: subject:"foo.*"}] 708 } 709 } 710 `)) 711 if _, err := ProcessConfigFile(cf); err == nil { 712 t.Fatalf("Expected an error with import of a service with no account") 713 } 714 // Import a service with a wildcard subject. 715 cf = createConfFile(t, []byte(` 716 accounts { 717 nats.io { 718 imports = [{service: {account: "nats.io", subject:"foo.*"}] 719 } 720 } 721 `)) 722 if _, err := ProcessConfigFile(cf); err == nil { 723 t.Fatalf("Expected an error with import of a service with wildcard subject") 724 } 725 // Export with unknown keyword. 726 cf = createConfFile(t, []byte(` 727 accounts { 728 nats.io { 729 exports = [{service: "foo.*", wat:true}] 730 } 731 } 732 `)) 733 if _, err := ProcessConfigFile(cf); err == nil { 734 t.Fatalf("Expected an error with export with unknown keyword") 735 } 736 // Import with unknown keyword. 737 cf = createConfFile(t, []byte(` 738 accounts { 739 nats.io { 740 imports = [{stream: {account: nats.io, subject: "foo.*"}, wat:true}] 741 } 742 } 743 `)) 744 if _, err := ProcessConfigFile(cf); err == nil { 745 t.Fatalf("Expected an error with import with unknown keyword") 746 } 747 // Export with an account. 748 cf = createConfFile(t, []byte(` 749 accounts { 750 nats.io { 751 exports = [{service: {account: nats.io, subject:"foo.*"}}] 752 } 753 } 754 `)) 755 if _, err := ProcessConfigFile(cf); err == nil { 756 t.Fatalf("Expected an error with export with account") 757 } 758 } 759 760 func TestImportAuthorized(t *testing.T) { 761 _, foo, bar := simpleAccountServer(t) 762 763 checkBool(foo.checkStreamImportAuthorized(bar, "foo", nil), false, t) 764 checkBool(foo.checkStreamImportAuthorized(bar, "*", nil), false, t) 765 checkBool(foo.checkStreamImportAuthorized(bar, ">", nil), false, t) 766 checkBool(foo.checkStreamImportAuthorized(bar, "foo.*", nil), false, t) 767 checkBool(foo.checkStreamImportAuthorized(bar, "foo.>", nil), false, t) 768 769 foo.AddStreamExport("foo", IsPublicExport) 770 checkBool(foo.checkStreamImportAuthorized(bar, "foo", nil), true, t) 771 checkBool(foo.checkStreamImportAuthorized(bar, "bar", nil), false, t) 772 checkBool(foo.checkStreamImportAuthorized(bar, "*", nil), false, t) 773 774 foo.AddStreamExport("*", []*Account{bar}) 775 checkBool(foo.checkStreamImportAuthorized(bar, "foo", nil), true, t) 776 checkBool(foo.checkStreamImportAuthorized(bar, "bar", nil), true, t) 777 checkBool(foo.checkStreamImportAuthorized(bar, "baz", nil), true, t) 778 checkBool(foo.checkStreamImportAuthorized(bar, "foo.bar", nil), false, t) 779 checkBool(foo.checkStreamImportAuthorized(bar, ">", nil), false, t) 780 checkBool(foo.checkStreamImportAuthorized(bar, "*", nil), true, t) 781 checkBool(foo.checkStreamImportAuthorized(bar, "foo.*", nil), false, t) 782 checkBool(foo.checkStreamImportAuthorized(bar, "*.*", nil), false, t) 783 checkBool(foo.checkStreamImportAuthorized(bar, "*.>", nil), false, t) 784 785 // Reset and test '>' public export 786 _, foo, bar = simpleAccountServer(t) 787 foo.AddStreamExport(">", nil) 788 // Everything should work. 789 checkBool(foo.checkStreamImportAuthorized(bar, "foo", nil), true, t) 790 checkBool(foo.checkStreamImportAuthorized(bar, "bar", nil), true, t) 791 checkBool(foo.checkStreamImportAuthorized(bar, "baz", nil), true, t) 792 checkBool(foo.checkStreamImportAuthorized(bar, "foo.bar", nil), true, t) 793 checkBool(foo.checkStreamImportAuthorized(bar, ">", nil), true, t) 794 checkBool(foo.checkStreamImportAuthorized(bar, "*", nil), true, t) 795 checkBool(foo.checkStreamImportAuthorized(bar, "foo.*", nil), true, t) 796 checkBool(foo.checkStreamImportAuthorized(bar, "*.*", nil), true, t) 797 checkBool(foo.checkStreamImportAuthorized(bar, "*.>", nil), true, t) 798 799 _, foo, bar = simpleAccountServer(t) 800 foo.addStreamExportWithAccountPos("foo.*", []*Account{}, 2) 801 foo.addStreamExportWithAccountPos("bar.*.foo", []*Account{}, 2) 802 if err := foo.addStreamExportWithAccountPos("baz.*.>", []*Account{}, 3); err == nil { 803 t.Fatal("expected error") 804 } 805 checkBool(foo.checkStreamImportAuthorized(bar, fmt.Sprintf("foo.%s", bar.Name), nil), true, t) 806 checkBool(foo.checkStreamImportAuthorized(bar, fmt.Sprintf("bar.%s.foo", bar.Name), nil), true, t) 807 checkBool(foo.checkStreamImportAuthorized(bar, fmt.Sprintf("baz.foo.%s", bar.Name), nil), false, t) 808 checkBool(foo.checkStreamImportAuthorized(bar, "foo.X", nil), false, t) 809 checkBool(foo.checkStreamImportAuthorized(bar, "bar.X.foo", nil), false, t) 810 checkBool(foo.checkStreamImportAuthorized(bar, "baz.foo.X", nil), false, t) 811 812 foo.addServiceExportWithAccountPos("a.*", []*Account{}, 2) 813 foo.addServiceExportWithAccountPos("b.*.a", []*Account{}, 2) 814 if err := foo.addServiceExportWithAccountPos("c.*.>", []*Account{}, 3); err == nil { 815 t.Fatal("expected error") 816 } 817 checkBool(foo.checkServiceImportAuthorized(bar, fmt.Sprintf("a.%s", bar.Name), nil), true, t) 818 checkBool(foo.checkServiceImportAuthorized(bar, fmt.Sprintf("b.%s.a", bar.Name), nil), true, t) 819 checkBool(foo.checkServiceImportAuthorized(bar, fmt.Sprintf("c.a.%s", bar.Name), nil), false, t) 820 checkBool(foo.checkServiceImportAuthorized(bar, "a.X", nil), false, t) 821 checkBool(foo.checkServiceImportAuthorized(bar, "b.X.a", nil), false, t) 822 checkBool(foo.checkServiceImportAuthorized(bar, "c.a.X", nil), false, t) 823 824 // Reset and test pwc and fwc 825 s, foo, bar := simpleAccountServer(t) 826 foo.AddStreamExport("foo.*.baz.>", []*Account{bar}) 827 checkBool(foo.checkStreamImportAuthorized(bar, "foo.bar.baz.1", nil), true, t) 828 checkBool(foo.checkStreamImportAuthorized(bar, "foo.bar.baz.*", nil), true, t) 829 checkBool(foo.checkStreamImportAuthorized(bar, "foo.*.baz.1.1", nil), true, t) 830 checkBool(foo.checkStreamImportAuthorized(bar, "foo.22.baz.22", nil), true, t) 831 checkBool(foo.checkStreamImportAuthorized(bar, "foo.bar.baz", nil), false, t) 832 checkBool(foo.checkStreamImportAuthorized(bar, "", nil), false, t) 833 checkBool(foo.checkStreamImportAuthorized(bar, "foo.bar.*.*", nil), false, t) 834 835 // Make sure we match the account as well 836 837 fb, _ := s.RegisterAccount("foobar") 838 bz, _ := s.RegisterAccount("baz") 839 840 checkBool(foo.checkStreamImportAuthorized(fb, "foo.bar.baz.1", nil), false, t) 841 checkBool(foo.checkStreamImportAuthorized(bz, "foo.bar.baz.1", nil), false, t) 842 } 843 844 func TestSimpleMapping(t *testing.T) { 845 s, fooAcc, barAcc := simpleAccountServer(t) 846 defer s.Shutdown() 847 848 cfoo, _, _ := newClientForServer(s) 849 defer cfoo.close() 850 851 if err := cfoo.registerWithAccount(fooAcc); err != nil { 852 t.Fatalf("Error registering client with 'foo' account: %v", err) 853 } 854 cbar, crBar, _ := newClientForServer(s) 855 defer cbar.close() 856 857 if err := cbar.registerWithAccount(barAcc); err != nil { 858 t.Fatalf("Error registering client with 'bar' account: %v", err) 859 } 860 861 // Test first that trying to import with no matching export permission returns an error. 862 if err := cbar.acc.AddStreamImport(fooAcc, "foo", "import"); err != ErrStreamImportAuthorization { 863 t.Fatalf("Expected error of ErrAccountImportAuthorization but got %v", err) 864 } 865 866 // Now map the subject space between foo and bar. 867 // Need to do export first. 868 if err := cfoo.acc.AddStreamExport("foo", nil); err != nil { // Public with no accounts defined. 869 t.Fatalf("Error adding account export to client foo: %v", err) 870 } 871 if err := cbar.acc.AddStreamImport(fooAcc, "foo", "import"); err != nil { 872 t.Fatalf("Error adding account import to client bar: %v", err) 873 } 874 875 // Normal and Queue Subscription on bar client. 876 if err := cbar.parse([]byte("SUB import.foo 1\r\nSUB import.foo bar 2\r\n")); err != nil { 877 t.Fatalf("Error for client 'bar' from server: %v", err) 878 } 879 880 // Now publish our message. 881 cfoo.parseAsync("PUB foo 5\r\nhello\r\n") 882 883 checkMsg := func(l, sid string) { 884 t.Helper() 885 mraw := msgPat.FindAllStringSubmatch(l, -1) 886 if len(mraw) == 0 { 887 t.Fatalf("No message received") 888 } 889 matches := mraw[0] 890 if matches[SUB_INDEX] != "import.foo" { 891 t.Fatalf("Did not get correct subject: wanted %q, got %q", "import.foo", matches[SUB_INDEX]) 892 } 893 if matches[SID_INDEX] != sid { 894 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 895 } 896 } 897 898 // Now check we got the message from normal subscription. 899 l, err := crBar.ReadString('\n') 900 if err != nil { 901 t.Fatalf("Error reading from client 'bar': %v", err) 902 } 903 checkMsg(l, "1") 904 checkPayload(crBar, []byte("hello\r\n"), t) 905 906 l, err = crBar.ReadString('\n') 907 if err != nil { 908 t.Fatalf("Error reading from client 'bar': %v", err) 909 } 910 checkMsg(l, "2") 911 checkPayload(crBar, []byte("hello\r\n"), t) 912 913 // We should have 2 subscriptions in both. Normal and Queue Subscriber 914 // for barAcc which are local, and 2 that are shadowed in fooAcc. 915 // Now make sure that when we unsubscribe we clean up properly for both. 916 if bslc := barAcc.sl.Count(); bslc != 2 { 917 t.Fatalf("Expected 2 normal subscriptions on barAcc, got %d", bslc) 918 } 919 if fslc := fooAcc.sl.Count(); fslc != 2 { 920 t.Fatalf("Expected 2 shadowed subscriptions on fooAcc, got %d", fslc) 921 } 922 923 // Now unsubscribe. 924 if err := cbar.parse([]byte("UNSUB 1\r\nUNSUB 2\r\n")); err != nil { 925 t.Fatalf("Error for client 'bar' from server: %v", err) 926 } 927 928 // We should have zero on both. 929 if bslc := barAcc.sl.Count(); bslc != 0 { 930 t.Fatalf("Expected no normal subscriptions on barAcc, got %d", bslc) 931 } 932 if fslc := fooAcc.sl.Count(); fslc != 0 { 933 t.Fatalf("Expected no shadowed subscriptions on fooAcc, got %d", fslc) 934 } 935 } 936 937 // https://github.com/nats-io/nats-server/issues/1159 938 func TestStreamImportLengthBug(t *testing.T) { 939 s, fooAcc, barAcc := simpleAccountServer(t) 940 defer s.Shutdown() 941 942 cfoo, _, _ := newClientForServer(s) 943 defer cfoo.close() 944 945 if err := cfoo.registerWithAccount(fooAcc); err != nil { 946 t.Fatalf("Error registering client with 'foo' account: %v", err) 947 } 948 cbar, _, _ := newClientForServer(s) 949 defer cbar.close() 950 951 if err := cbar.registerWithAccount(barAcc); err != nil { 952 t.Fatalf("Error registering client with 'bar' account: %v", err) 953 } 954 955 if err := cfoo.acc.AddStreamExport("client.>", nil); err != nil { 956 t.Fatalf("Error adding account export to client foo: %v", err) 957 } 958 if err := cbar.acc.AddStreamImport(fooAcc, "client.>", "events.>"); err == nil { 959 t.Fatalf("Expected an error when using a stream import prefix with a wildcard") 960 } 961 962 if err := cbar.acc.AddStreamImport(fooAcc, "client.>", "events"); err != nil { 963 t.Fatalf("Error adding account import to client bar: %v", err) 964 } 965 966 if err := cbar.parse([]byte("SUB events.> 1\r\n")); err != nil { 967 t.Fatalf("Error for client 'bar' from server: %v", err) 968 } 969 970 // Also make sure that we will get an error from a config version. 971 // JWT will be updated separately. 972 cf := createConfFile(t, []byte(` 973 accounts { 974 foo { 975 exports = [{stream: "client.>"}] 976 } 977 bar { 978 imports = [{stream: {account: "foo", subject:"client.>"}, prefix:"events.>"}] 979 } 980 } 981 `)) 982 if _, err := ProcessConfigFile(cf); err == nil { 983 t.Fatalf("Expected an error with import with wildcard prefix") 984 } 985 } 986 987 func TestShadowSubsCleanupOnClientClose(t *testing.T) { 988 s, fooAcc, barAcc := simpleAccountServer(t) 989 defer s.Shutdown() 990 991 // Now map the subject space between foo and bar. 992 // Need to do export first. 993 if err := fooAcc.AddStreamExport("foo", nil); err != nil { // Public with no accounts defined. 994 t.Fatalf("Error adding account export to client foo: %v", err) 995 } 996 if err := barAcc.AddStreamImport(fooAcc, "foo", "import"); err != nil { 997 t.Fatalf("Error adding account import to client bar: %v", err) 998 } 999 1000 cbar, _, _ := newClientForServer(s) 1001 defer cbar.close() 1002 1003 if err := cbar.registerWithAccount(barAcc); err != nil { 1004 t.Fatalf("Error registering client with 'bar' account: %v", err) 1005 } 1006 1007 // Normal and Queue Subscription on bar client. 1008 if err := cbar.parse([]byte("SUB import.foo 1\r\nSUB import.foo bar 2\r\n")); err != nil { 1009 t.Fatalf("Error for client 'bar' from server: %v", err) 1010 } 1011 1012 if fslc := fooAcc.sl.Count(); fslc != 2 { 1013 t.Fatalf("Expected 2 shadowed subscriptions on fooAcc, got %d", fslc) 1014 } 1015 1016 // Now close cbar and make sure we remove shadows. 1017 cbar.closeConnection(ClientClosed) 1018 1019 checkFor(t, time.Second, 10*time.Millisecond, func() error { 1020 if fslc := fooAcc.sl.Count(); fslc != 0 { 1021 return fmt.Errorf("Number of shadow subscriptions is %d", fslc) 1022 } 1023 return nil 1024 }) 1025 } 1026 1027 func TestNoPrefixWildcardMapping(t *testing.T) { 1028 s, fooAcc, barAcc := simpleAccountServer(t) 1029 defer s.Shutdown() 1030 1031 cfoo, _, _ := newClientForServer(s) 1032 defer cfoo.close() 1033 1034 if err := cfoo.registerWithAccount(fooAcc); err != nil { 1035 t.Fatalf("Error registering client with 'foo' account: %v", err) 1036 } 1037 cbar, crBar, _ := newClientForServer(s) 1038 defer cbar.close() 1039 1040 if err := cbar.registerWithAccount(barAcc); err != nil { 1041 t.Fatalf("Error registering client with 'bar' account: %v", err) 1042 } 1043 1044 if err := cfoo.acc.AddStreamExport(">", []*Account{barAcc}); err != nil { 1045 t.Fatalf("Error adding stream export to client foo: %v", err) 1046 } 1047 if err := cbar.acc.AddStreamImport(fooAcc, "*", ""); err != nil { 1048 t.Fatalf("Error adding stream import to client bar: %v", err) 1049 } 1050 1051 // Normal Subscription on bar client for literal "foo". 1052 cbar.parseAsync("SUB foo 1\r\nPING\r\n") 1053 _, err := crBar.ReadString('\n') // Make sure subscriptions were processed. 1054 if err != nil { 1055 t.Fatalf("Error for client 'bar' from server: %v", err) 1056 } 1057 1058 // Now publish our message. 1059 cfoo.parseAsync("PUB foo 5\r\nhello\r\n") 1060 1061 // Now check we got the message from normal subscription. 1062 l, err := crBar.ReadString('\n') 1063 if err != nil { 1064 t.Fatalf("Error reading from client 'bar': %v", err) 1065 } 1066 mraw := msgPat.FindAllStringSubmatch(l, -1) 1067 if len(mraw) == 0 { 1068 t.Fatalf("No message received") 1069 } 1070 matches := mraw[0] 1071 if matches[SUB_INDEX] != "foo" { 1072 t.Fatalf("Did not get correct subject: '%s'", matches[SUB_INDEX]) 1073 } 1074 if matches[SID_INDEX] != "1" { 1075 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 1076 } 1077 checkPayload(crBar, []byte("hello\r\n"), t) 1078 } 1079 1080 func TestPrefixWildcardMapping(t *testing.T) { 1081 s, fooAcc, barAcc := simpleAccountServer(t) 1082 defer s.Shutdown() 1083 1084 cfoo, _, _ := newClientForServer(s) 1085 defer cfoo.close() 1086 1087 if err := cfoo.registerWithAccount(fooAcc); err != nil { 1088 t.Fatalf("Error registering client with 'foo' account: %v", err) 1089 } 1090 cbar, crBar, _ := newClientForServer(s) 1091 defer cbar.close() 1092 1093 if err := cbar.registerWithAccount(barAcc); err != nil { 1094 t.Fatalf("Error registering client with 'bar' account: %v", err) 1095 } 1096 1097 if err := cfoo.acc.AddStreamExport(">", []*Account{barAcc}); err != nil { 1098 t.Fatalf("Error adding stream export to client foo: %v", err) 1099 } 1100 // Checking that trailing '.' is accepted, tested that it is auto added above. 1101 if err := cbar.acc.AddStreamImport(fooAcc, "*", "pub.imports."); err != nil { 1102 t.Fatalf("Error adding stream import to client bar: %v", err) 1103 } 1104 1105 // Normal Subscription on bar client for wildcard. 1106 cbar.parseAsync("SUB pub.imports.* 1\r\nPING\r\n") 1107 _, err := crBar.ReadString('\n') // Make sure subscriptions were processed. 1108 if err != nil { 1109 t.Fatalf("Error for client 'bar' from server: %v", err) 1110 } 1111 1112 // Now publish our message. 1113 cfoo.parseAsync("PUB foo 5\r\nhello\r\n") 1114 1115 // Now check we got the messages from wildcard subscription. 1116 l, err := crBar.ReadString('\n') 1117 if err != nil { 1118 t.Fatalf("Error reading from client 'bar': %v", err) 1119 } 1120 mraw := msgPat.FindAllStringSubmatch(l, -1) 1121 if len(mraw) == 0 { 1122 t.Fatalf("No message received") 1123 } 1124 matches := mraw[0] 1125 if matches[SUB_INDEX] != "pub.imports.foo" { 1126 t.Fatalf("Did not get correct subject: '%s'", matches[SUB_INDEX]) 1127 } 1128 if matches[SID_INDEX] != "1" { 1129 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 1130 } 1131 checkPayload(crBar, []byte("hello\r\n"), t) 1132 } 1133 1134 func TestPrefixWildcardMappingWithLiteralSub(t *testing.T) { 1135 s, fooAcc, barAcc := simpleAccountServer(t) 1136 defer s.Shutdown() 1137 1138 cfoo, _, _ := newClientForServer(s) 1139 defer cfoo.close() 1140 1141 if err := cfoo.registerWithAccount(fooAcc); err != nil { 1142 t.Fatalf("Error registering client with 'foo' account: %v", err) 1143 } 1144 cbar, crBar, _ := newClientForServer(s) 1145 defer cbar.close() 1146 1147 if err := cbar.registerWithAccount(barAcc); err != nil { 1148 t.Fatalf("Error registering client with 'bar' account: %v", err) 1149 } 1150 1151 if err := fooAcc.AddStreamExport(">", []*Account{barAcc}); err != nil { 1152 t.Fatalf("Error adding stream export to client foo: %v", err) 1153 } 1154 if err := barAcc.AddStreamImport(fooAcc, "*", "pub.imports."); err != nil { 1155 t.Fatalf("Error adding stream import to client bar: %v", err) 1156 } 1157 1158 // Normal Subscription on bar client for wildcard. 1159 cbar.parseAsync("SUB pub.imports.foo 1\r\nPING\r\n") 1160 _, err := crBar.ReadString('\n') // Make sure subscriptions were processed. 1161 if err != nil { 1162 t.Fatalf("Error for client 'bar' from server: %v", err) 1163 } 1164 1165 // Now publish our message. 1166 cfoo.parseAsync("PUB foo 5\r\nhello\r\n") 1167 1168 // Now check we got the messages from wildcard subscription. 1169 l, err := crBar.ReadString('\n') 1170 if err != nil { 1171 t.Fatalf("Error reading from client 'bar': %v", err) 1172 } 1173 mraw := msgPat.FindAllStringSubmatch(l, -1) 1174 if len(mraw) == 0 { 1175 t.Fatalf("No message received") 1176 } 1177 matches := mraw[0] 1178 if matches[SUB_INDEX] != "pub.imports.foo" { 1179 t.Fatalf("Did not get correct subject: '%s'", matches[SUB_INDEX]) 1180 } 1181 if matches[SID_INDEX] != "1" { 1182 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 1183 } 1184 checkPayload(crBar, []byte("hello\r\n"), t) 1185 } 1186 1187 func TestMultipleImportsAndSingleWCSub(t *testing.T) { 1188 s, fooAcc, barAcc := simpleAccountServer(t) 1189 defer s.Shutdown() 1190 1191 cfoo, _, _ := newClientForServer(s) 1192 defer cfoo.close() 1193 1194 if err := cfoo.registerWithAccount(fooAcc); err != nil { 1195 t.Fatalf("Error registering client with 'foo' account: %v", err) 1196 } 1197 cbar, crBar, _ := newClientForServer(s) 1198 defer cbar.close() 1199 1200 if err := cbar.registerWithAccount(barAcc); err != nil { 1201 t.Fatalf("Error registering client with 'bar' account: %v", err) 1202 } 1203 1204 if err := fooAcc.AddStreamExport("foo", []*Account{barAcc}); err != nil { 1205 t.Fatalf("Error adding stream export to account foo: %v", err) 1206 } 1207 if err := fooAcc.AddStreamExport("bar", []*Account{barAcc}); err != nil { 1208 t.Fatalf("Error adding stream export to account foo: %v", err) 1209 } 1210 1211 if err := barAcc.AddStreamImport(fooAcc, "foo", "pub."); err != nil { 1212 t.Fatalf("Error adding stream import to account bar: %v", err) 1213 } 1214 if err := barAcc.AddStreamImport(fooAcc, "bar", "pub."); err != nil { 1215 t.Fatalf("Error adding stream import to account bar: %v", err) 1216 } 1217 1218 // Wildcard Subscription on bar client for both imports. 1219 cbar.parse([]byte("SUB pub.* 1\r\n")) 1220 1221 // Now publish a message on 'foo' and 'bar' 1222 cfoo.parseAsync("PUB foo 5\r\nhello\r\nPUB bar 5\r\nworld\r\n") 1223 1224 // Now check we got the messages from the wildcard subscription. 1225 l, err := crBar.ReadString('\n') 1226 if err != nil { 1227 t.Fatalf("Error reading from client 'bar': %v", err) 1228 } 1229 mraw := msgPat.FindAllStringSubmatch(l, -1) 1230 if len(mraw) == 0 { 1231 t.Fatalf("No message received") 1232 } 1233 matches := mraw[0] 1234 if matches[SUB_INDEX] != "pub.foo" { 1235 t.Fatalf("Did not get correct subject: '%s'", matches[SUB_INDEX]) 1236 } 1237 if matches[SID_INDEX] != "1" { 1238 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 1239 } 1240 checkPayload(crBar, []byte("hello\r\n"), t) 1241 1242 l, err = crBar.ReadString('\n') 1243 if err != nil { 1244 t.Fatalf("Error reading from client 'bar': %v", err) 1245 } 1246 mraw = msgPat.FindAllStringSubmatch(l, -1) 1247 if len(mraw) == 0 { 1248 t.Fatalf("No message received") 1249 } 1250 matches = mraw[0] 1251 if matches[SUB_INDEX] != "pub.bar" { 1252 t.Fatalf("Did not get correct subject: '%s'", matches[SUB_INDEX]) 1253 } 1254 if matches[SID_INDEX] != "1" { 1255 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 1256 } 1257 checkPayload(crBar, []byte("world\r\n"), t) 1258 1259 // Check subscription count. 1260 if fslc := fooAcc.sl.Count(); fslc != 2 { 1261 t.Fatalf("Expected 2 shadowed subscriptions on fooAcc, got %d", fslc) 1262 } 1263 if bslc := barAcc.sl.Count(); bslc != 1 { 1264 t.Fatalf("Expected 1 normal subscriptions on barAcc, got %d", bslc) 1265 } 1266 1267 // Now unsubscribe. 1268 if err := cbar.parse([]byte("UNSUB 1\r\n")); err != nil { 1269 t.Fatalf("Error for client 'bar' from server: %v", err) 1270 } 1271 // We should have zero on both. 1272 if bslc := barAcc.sl.Count(); bslc != 0 { 1273 t.Fatalf("Expected no normal subscriptions on barAcc, got %d", bslc) 1274 } 1275 if fslc := fooAcc.sl.Count(); fslc != 0 { 1276 t.Fatalf("Expected no shadowed subscriptions on fooAcc, got %d", fslc) 1277 } 1278 } 1279 1280 // Make sure the AddServiceExport function is additive if called multiple times. 1281 func TestAddServiceExport(t *testing.T) { 1282 s, fooAcc, barAcc := simpleAccountServer(t) 1283 bazAcc, err := s.RegisterAccount("$baz") 1284 if err != nil { 1285 t.Fatalf("Error creating account 'baz': %v", err) 1286 } 1287 defer s.Shutdown() 1288 1289 if err := fooAcc.AddServiceExport("test.request", nil); err != nil { 1290 t.Fatalf("Error adding account service export to client foo: %v", err) 1291 } 1292 tr := fooAcc.exports.services["test.request"] 1293 if len(tr.approved) != 0 { 1294 t.Fatalf("Expected no authorized accounts, got %d", len(tr.approved)) 1295 } 1296 if err := fooAcc.AddServiceExport("test.request", []*Account{barAcc}); err != nil { 1297 t.Fatalf("Error adding account service export to client foo: %v", err) 1298 } 1299 tr = fooAcc.exports.services["test.request"] 1300 if tr == nil { 1301 t.Fatalf("Expected authorized accounts, got nil") 1302 } 1303 if ls := len(tr.approved); ls != 1 { 1304 t.Fatalf("Expected 1 authorized accounts, got %d", ls) 1305 } 1306 if err := fooAcc.AddServiceExport("test.request", []*Account{bazAcc}); err != nil { 1307 t.Fatalf("Error adding account service export to client foo: %v", err) 1308 } 1309 tr = fooAcc.exports.services["test.request"] 1310 if tr == nil { 1311 t.Fatalf("Expected authorized accounts, got nil") 1312 } 1313 if ls := len(tr.approved); ls != 2 { 1314 t.Fatalf("Expected 2 authorized accounts, got %d", ls) 1315 } 1316 } 1317 1318 func TestServiceExportWithWildcards(t *testing.T) { 1319 for _, test := range []struct { 1320 name string 1321 public bool 1322 }{ 1323 { 1324 name: "public", 1325 public: true, 1326 }, 1327 { 1328 name: "private", 1329 public: false, 1330 }, 1331 } { 1332 t.Run(test.name, func(t *testing.T) { 1333 s, fooAcc, barAcc := simpleAccountServer(t) 1334 defer s.Shutdown() 1335 1336 var accs []*Account 1337 if !test.public { 1338 accs = []*Account{barAcc} 1339 } 1340 // Add service export with a wildcard 1341 if err := fooAcc.AddServiceExport("ngs.update.*", accs); err != nil { 1342 t.Fatalf("Error adding account service export: %v", err) 1343 } 1344 // Import on bar account 1345 if err := barAcc.AddServiceImport(fooAcc, "ngs.update", "ngs.update.$bar"); err != nil { 1346 t.Fatalf("Error adding account service import: %v", err) 1347 } 1348 1349 cfoo, crFoo, _ := newClientForServer(s) 1350 defer cfoo.close() 1351 1352 if err := cfoo.registerWithAccount(fooAcc); err != nil { 1353 t.Fatalf("Error registering client with 'foo' account: %v", err) 1354 } 1355 cbar, crBar, _ := newClientForServer(s) 1356 defer cbar.close() 1357 1358 if err := cbar.registerWithAccount(barAcc); err != nil { 1359 t.Fatalf("Error registering client with 'bar' account: %v", err) 1360 } 1361 1362 // Now setup the responder under cfoo 1363 cfoo.parse([]byte("SUB ngs.update.* 1\r\n")) 1364 1365 // Now send the request. Remember we expect the request on our local ngs.update. 1366 // We added the route with that "from" and will map it to "ngs.update.$bar" 1367 cbar.parseAsync("SUB reply 11\r\nPUB ngs.update reply 4\r\nhelp\r\n") 1368 1369 // Now read the request from crFoo 1370 l, err := crFoo.ReadString('\n') 1371 if err != nil { 1372 t.Fatalf("Error reading from client 'bar': %v", err) 1373 } 1374 1375 mraw := msgPat.FindAllStringSubmatch(l, -1) 1376 if len(mraw) == 0 { 1377 t.Fatalf("No message received") 1378 } 1379 matches := mraw[0] 1380 if matches[SUB_INDEX] != "ngs.update.$bar" { 1381 t.Fatalf("Did not get correct subject: '%s'", matches[SUB_INDEX]) 1382 } 1383 if matches[SID_INDEX] != "1" { 1384 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 1385 } 1386 // Make sure this looks like _INBOX 1387 if !strings.HasPrefix(matches[REPLY_INDEX], "_R_.") { 1388 t.Fatalf("Expected an _R_.* like reply, got '%s'", matches[REPLY_INDEX]) 1389 } 1390 checkPayload(crFoo, []byte("help\r\n"), t) 1391 1392 replyOp := fmt.Sprintf("PUB %s 2\r\n22\r\n", matches[REPLY_INDEX]) 1393 cfoo.parseAsync(replyOp) 1394 1395 // Now read the response from crBar 1396 l, err = crBar.ReadString('\n') 1397 if err != nil { 1398 t.Fatalf("Error reading from client 'bar': %v", err) 1399 } 1400 mraw = msgPat.FindAllStringSubmatch(l, -1) 1401 if len(mraw) == 0 { 1402 t.Fatalf("No message received") 1403 } 1404 matches = mraw[0] 1405 if matches[SUB_INDEX] != "reply" { 1406 t.Fatalf("Did not get correct subject: '%s'", matches[SUB_INDEX]) 1407 } 1408 if matches[SID_INDEX] != "11" { 1409 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 1410 } 1411 if matches[REPLY_INDEX] != "" { 1412 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 1413 } 1414 checkPayload(crBar, []byte("22\r\n"), t) 1415 1416 if nr := barAcc.NumPendingAllResponses(); nr != 0 { 1417 t.Fatalf("Expected no responses on barAcc, got %d", nr) 1418 } 1419 }) 1420 } 1421 } 1422 1423 func TestAccountAddServiceImportRace(t *testing.T) { 1424 s, fooAcc, barAcc := simpleAccountServer(t) 1425 defer s.Shutdown() 1426 1427 if err := fooAcc.AddServiceExport("foo.*", nil); err != nil { 1428 t.Fatalf("Error adding account service export to client foo: %v", err) 1429 } 1430 1431 total := 100 1432 errCh := make(chan error, total) 1433 for i := 0; i < 100; i++ { 1434 go func(i int) { 1435 err := barAcc.AddServiceImport(fooAcc, fmt.Sprintf("foo.%d", i), "") 1436 errCh <- err // nil is a valid value. 1437 }(i) 1438 } 1439 1440 for i := 0; i < 100; i++ { 1441 err := <-errCh 1442 if err != nil { 1443 t.Fatalf("Error adding account service import: %v", err) 1444 } 1445 } 1446 1447 barAcc.mu.Lock() 1448 lens := len(barAcc.imports.services) 1449 c := barAcc.internalClient() 1450 barAcc.mu.Unlock() 1451 if lens != total { 1452 t.Fatalf("Expected %d imported services, got %d", total, lens) 1453 } 1454 c.mu.Lock() 1455 lens = len(c.subs) 1456 c.mu.Unlock() 1457 if lens != total { 1458 t.Fatalf("Expected %d subscriptions in internal client, got %d", total, lens) 1459 } 1460 } 1461 1462 func TestServiceImportWithWildcards(t *testing.T) { 1463 s, fooAcc, barAcc := simpleAccountServer(t) 1464 defer s.Shutdown() 1465 1466 if err := fooAcc.AddServiceExport("test.*", nil); err != nil { 1467 t.Fatalf("Error adding account service export to client foo: %v", err) 1468 } 1469 // We can not map wildcards atm, so if we supply a to mapping and a wildcard we should fail. 1470 if err := barAcc.AddServiceImport(fooAcc, "test.*", "foo"); err == nil { 1471 t.Fatalf("Expected error adding account service import with wildcard and mapping, got none") 1472 } 1473 if err := barAcc.AddServiceImport(fooAcc, "test.>", ""); err == nil { 1474 t.Fatalf("Expected error adding account service import with broader wildcard, got none") 1475 } 1476 // This should work. 1477 if err := barAcc.AddServiceImport(fooAcc, "test.*", ""); err != nil { 1478 t.Fatalf("Error adding account service import: %v", err) 1479 } 1480 // Make sure we can send and receive. 1481 cfoo, crFoo, _ := newClientForServer(s) 1482 defer cfoo.close() 1483 1484 if err := cfoo.registerWithAccount(fooAcc); err != nil { 1485 t.Fatalf("Error registering client with 'foo' account: %v", err) 1486 } 1487 1488 // Now setup the resonder under cfoo 1489 cfoo.parse([]byte("SUB test.* 1\r\n")) 1490 1491 cbar, crBar, _ := newClientForServer(s) 1492 defer cbar.close() 1493 1494 if err := cbar.registerWithAccount(barAcc); err != nil { 1495 t.Fatalf("Error registering client with 'bar' account: %v", err) 1496 } 1497 1498 // Now send the request. 1499 go cbar.parse([]byte("SUB bar 11\r\nPUB test.22 bar 4\r\nhelp\r\n")) 1500 1501 // Now read the request from crFoo 1502 l, err := crFoo.ReadString('\n') 1503 if err != nil { 1504 t.Fatalf("Error reading from client 'bar': %v", err) 1505 } 1506 1507 mraw := msgPat.FindAllStringSubmatch(l, -1) 1508 if len(mraw) == 0 { 1509 t.Fatalf("No message received") 1510 } 1511 matches := mraw[0] 1512 if matches[SUB_INDEX] != "test.22" { 1513 t.Fatalf("Did not get correct subject: '%s'", matches[SUB_INDEX]) 1514 } 1515 if matches[SID_INDEX] != "1" { 1516 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 1517 } 1518 // Make sure this looks like _INBOX 1519 if !strings.HasPrefix(matches[REPLY_INDEX], "_R_.") { 1520 t.Fatalf("Expected an _R_.* like reply, got '%s'", matches[REPLY_INDEX]) 1521 } 1522 checkPayload(crFoo, []byte("help\r\n"), t) 1523 1524 replyOp := fmt.Sprintf("PUB %s 2\r\n22\r\n", matches[REPLY_INDEX]) 1525 go cfoo.parse([]byte(replyOp)) 1526 1527 // Now read the response from crBar 1528 l, err = crBar.ReadString('\n') 1529 if err != nil { 1530 t.Fatalf("Error reading from client 'bar': %v", err) 1531 } 1532 mraw = msgPat.FindAllStringSubmatch(l, -1) 1533 if len(mraw) == 0 { 1534 t.Fatalf("No message received") 1535 } 1536 matches = mraw[0] 1537 if matches[SUB_INDEX] != "bar" { 1538 t.Fatalf("Did not get correct subject: '%s'", matches[SUB_INDEX]) 1539 } 1540 if matches[SID_INDEX] != "11" { 1541 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 1542 } 1543 if matches[REPLY_INDEX] != "" { 1544 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 1545 } 1546 checkPayload(crBar, []byte("22\r\n"), t) 1547 1548 // Remove the service import with the wildcard and make sure hasWC is cleared. 1549 barAcc.removeServiceImport("test.*") 1550 1551 barAcc.mu.Lock() 1552 defer barAcc.mu.Unlock() 1553 if len(barAcc.imports.services) != 0 { 1554 t.Fatalf("Expected no imported services, got %d", len(barAcc.imports.services)) 1555 } 1556 } 1557 1558 // Make sure the AddStreamExport function is additive if called multiple times. 1559 func TestAddStreamExport(t *testing.T) { 1560 s, fooAcc, barAcc := simpleAccountServer(t) 1561 bazAcc, err := s.RegisterAccount("$baz") 1562 if err != nil { 1563 t.Fatalf("Error creating account 'baz': %v", err) 1564 } 1565 defer s.Shutdown() 1566 1567 if err := fooAcc.AddStreamExport("test.request", nil); err != nil { 1568 t.Fatalf("Error adding account service export to client foo: %v", err) 1569 } 1570 tr := fooAcc.exports.streams["test.request"] 1571 if tr != nil { 1572 t.Fatalf("Expected no authorized accounts, got %d", len(tr.approved)) 1573 } 1574 if err := fooAcc.AddStreamExport("test.request", []*Account{barAcc}); err != nil { 1575 t.Fatalf("Error adding account service export to client foo: %v", err) 1576 } 1577 tr = fooAcc.exports.streams["test.request"] 1578 if tr == nil { 1579 t.Fatalf("Expected authorized accounts, got nil") 1580 } 1581 if ls := len(tr.approved); ls != 1 { 1582 t.Fatalf("Expected 1 authorized accounts, got %d", ls) 1583 } 1584 if err := fooAcc.AddStreamExport("test.request", []*Account{bazAcc}); err != nil { 1585 t.Fatalf("Error adding account service export to client foo: %v", err) 1586 } 1587 tr = fooAcc.exports.streams["test.request"] 1588 if tr == nil { 1589 t.Fatalf("Expected authorized accounts, got nil") 1590 } 1591 if ls := len(tr.approved); ls != 2 { 1592 t.Fatalf("Expected 2 authorized accounts, got %d", ls) 1593 } 1594 } 1595 1596 func TestCrossAccountRequestReply(t *testing.T) { 1597 s, fooAcc, barAcc := simpleAccountServer(t) 1598 defer s.Shutdown() 1599 1600 cfoo, crFoo, _ := newClientForServer(s) 1601 defer cfoo.close() 1602 1603 if err := cfoo.registerWithAccount(fooAcc); err != nil { 1604 t.Fatalf("Error registering client with 'foo' account: %v", err) 1605 } 1606 1607 cbar, crBar, _ := newClientForServer(s) 1608 defer cbar.close() 1609 1610 if err := cbar.registerWithAccount(barAcc); err != nil { 1611 t.Fatalf("Error registering client with 'bar' account: %v", err) 1612 } 1613 1614 // Add in the service export for the requests. Make it public. 1615 if err := cfoo.acc.AddServiceExport("test.request", nil); err != nil { 1616 t.Fatalf("Error adding account service export to client foo: %v", err) 1617 } 1618 1619 // Test addServiceImport to make sure it requires accounts. 1620 if err := cbar.acc.AddServiceImport(nil, "foo", "test.request"); err != ErrMissingAccount { 1621 t.Fatalf("Expected ErrMissingAccount but received %v.", err) 1622 } 1623 if err := cbar.acc.AddServiceImport(fooAcc, "foo", "test..request."); err != ErrInvalidSubject { 1624 t.Fatalf("Expected ErrInvalidSubject but received %v.", err) 1625 } 1626 1627 // Now add in the route mapping for request to be routed to the foo account. 1628 if err := cbar.acc.AddServiceImport(fooAcc, "foo", "test.request"); err != nil { 1629 t.Fatalf("Error adding account service import to client bar: %v", err) 1630 } 1631 1632 // Now setup the resonder under cfoo 1633 cfoo.parse([]byte("SUB test.request 1\r\n")) 1634 1635 // Now send the request. Remember we expect the request on our local foo. We added the route 1636 // with that "from" and will map it to "test.request" 1637 cbar.parseAsync("SUB bar 11\r\nPUB foo bar 4\r\nhelp\r\n") 1638 1639 // Now read the request from crFoo 1640 l, err := crFoo.ReadString('\n') 1641 if err != nil { 1642 t.Fatalf("Error reading from client 'bar': %v", err) 1643 } 1644 1645 mraw := msgPat.FindAllStringSubmatch(l, -1) 1646 if len(mraw) == 0 { 1647 t.Fatalf("No message received") 1648 } 1649 matches := mraw[0] 1650 if matches[SUB_INDEX] != "test.request" { 1651 t.Fatalf("Did not get correct subject: '%s'", matches[SUB_INDEX]) 1652 } 1653 if matches[SID_INDEX] != "1" { 1654 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 1655 } 1656 // Make sure this looks like _INBOX 1657 if !strings.HasPrefix(matches[REPLY_INDEX], "_R_.") { 1658 t.Fatalf("Expected an _R_.* like reply, got '%s'", matches[REPLY_INDEX]) 1659 } 1660 checkPayload(crFoo, []byte("help\r\n"), t) 1661 1662 replyOp := fmt.Sprintf("PUB %s 2\r\n22\r\n", matches[REPLY_INDEX]) 1663 cfoo.parseAsync(replyOp) 1664 1665 // Now read the response from crBar 1666 l, err = crBar.ReadString('\n') 1667 if err != nil { 1668 t.Fatalf("Error reading from client 'bar': %v", err) 1669 } 1670 mraw = msgPat.FindAllStringSubmatch(l, -1) 1671 if len(mraw) == 0 { 1672 t.Fatalf("No message received") 1673 } 1674 matches = mraw[0] 1675 if matches[SUB_INDEX] != "bar" { 1676 t.Fatalf("Did not get correct subject: '%s'", matches[SUB_INDEX]) 1677 } 1678 if matches[SID_INDEX] != "11" { 1679 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 1680 } 1681 if matches[REPLY_INDEX] != "" { 1682 t.Fatalf("Did not get correct sid: '%s'", matches[SID_INDEX]) 1683 } 1684 checkPayload(crBar, []byte("22\r\n"), t) 1685 1686 if nr := barAcc.NumPendingAllResponses(); nr != 0 { 1687 t.Fatalf("Expected no responses on barAcc, got %d", nr) 1688 } 1689 } 1690 1691 func TestAccountRequestReplyTrackLatency(t *testing.T) { 1692 s, fooAcc, barAcc := simpleAccountServer(t) 1693 defer s.Shutdown() 1694 1695 // Run server in Go routine. We need this one running for internal sending of msgs. 1696 s.Start() 1697 // Wait for accept loop(s) to be started 1698 if err := s.readyForConnections(10 * time.Second); err != nil { 1699 t.Fatal(err) 1700 } 1701 1702 cfoo, crFoo, _ := newClientForServer(s) 1703 defer cfoo.close() 1704 1705 if err := cfoo.registerWithAccount(fooAcc); err != nil { 1706 t.Fatalf("Error registering client with 'foo' account: %v", err) 1707 } 1708 1709 cbar, crBar, _ := newClientForServer(s) 1710 defer cbar.close() 1711 1712 if err := cbar.registerWithAccount(barAcc); err != nil { 1713 t.Fatalf("Error registering client with 'bar' account: %v", err) 1714 } 1715 1716 // Add in the service export for the requests. Make it public. 1717 if err := fooAcc.AddServiceExport("track.service", nil); err != nil { 1718 t.Fatalf("Error adding account service export to client foo: %v", err) 1719 } 1720 1721 // Now let's add in tracking 1722 1723 // First check we get an error if service does not exist. 1724 if err := fooAcc.TrackServiceExport("track.wrong", "results"); err != ErrMissingService { 1725 t.Fatalf("Expected error enabling tracking latency for wrong service") 1726 } 1727 // Check results should be a valid subject 1728 if err := fooAcc.TrackServiceExport("track.service", "results.*"); err != ErrBadPublishSubject { 1729 t.Fatalf("Expected error enabling tracking latency for bad results subject") 1730 } 1731 // Make sure we can not loop around on ourselves.. 1732 if err := fooAcc.TrackServiceExport("track.service", "track.service"); err != ErrBadPublishSubject { 1733 t.Fatalf("Expected error enabling tracking latency for same subject") 1734 } 1735 // Check bad sampling 1736 if err := fooAcc.TrackServiceExportWithSampling("track.service", "results", -1); err != ErrBadSampling { 1737 t.Fatalf("Expected error enabling tracking latency for bad sampling") 1738 } 1739 if err := fooAcc.TrackServiceExportWithSampling("track.service", "results", 101); err != ErrBadSampling { 1740 t.Fatalf("Expected error enabling tracking latency for bad sampling") 1741 } 1742 1743 // Now let's add in tracking for real. This will be 100% 1744 if err := fooAcc.TrackServiceExport("track.service", "results"); err != nil { 1745 t.Fatalf("Error enabling tracking latency: %v", err) 1746 } 1747 1748 // Now add in the route mapping for request to be routed to the foo account. 1749 if err := barAcc.AddServiceImport(fooAcc, "req", "track.service"); err != nil { 1750 t.Fatalf("Error adding account service import to client bar: %v", err) 1751 } 1752 1753 // Now setup the responder under cfoo and the listener for the results 1754 cfoo.parse([]byte("SUB track.service 1\r\nSUB results 2\r\n")) 1755 1756 readFooMsg := func() ([]byte, string) { 1757 t.Helper() 1758 l, err := crFoo.ReadString('\n') 1759 if err != nil { 1760 t.Fatalf("Error reading from client 'foo': %v", err) 1761 } 1762 mraw := msgPat.FindAllStringSubmatch(l, -1) 1763 if len(mraw) == 0 { 1764 t.Fatalf("No message received") 1765 } 1766 msg := mraw[0] 1767 msgSize, _ := strconv.Atoi(msg[LEN_INDEX]) 1768 return grabPayload(crFoo, msgSize), msg[REPLY_INDEX] 1769 } 1770 1771 start := time.Now() 1772 1773 // Now send the request. Remember we expect the request on our local foo. We added the route 1774 // with that "from" and will map it to "test.request" 1775 cbar.parseAsync("SUB resp 11\r\nPUB req resp 4\r\nhelp\r\n") 1776 1777 // Now read the request from crFoo 1778 _, reply := readFooMsg() 1779 replyOp := fmt.Sprintf("PUB %s 2\r\n22\r\n", reply) 1780 1781 serviceTime := 25 * time.Millisecond 1782 1783 // We will wait a bit to check latency results 1784 go func() { 1785 time.Sleep(serviceTime) 1786 cfoo.parseAsync(replyOp) 1787 }() 1788 1789 // Now read the response from crBar 1790 _, err := crBar.ReadString('\n') 1791 if err != nil { 1792 t.Fatalf("Error reading from client 'bar': %v", err) 1793 } 1794 1795 // Now let's check that we got the sampling results 1796 rMsg, _ := readFooMsg() 1797 1798 // Unmarshal and check it. 1799 var sl ServiceLatency 1800 err = json.Unmarshal(rMsg, &sl) 1801 if err != nil { 1802 t.Fatalf("Could not parse latency json: %v\n", err) 1803 } 1804 startDelta := sl.RequestStart.Sub(start) 1805 if startDelta > 5*time.Millisecond { 1806 t.Fatalf("Bad start delta %v", startDelta) 1807 } 1808 if sl.ServiceLatency < serviceTime { 1809 t.Fatalf("Bad service latency: %v", sl.ServiceLatency) 1810 } 1811 if sl.TotalLatency < sl.ServiceLatency { 1812 t.Fatalf("Bad total latency: %v", sl.ServiceLatency) 1813 } 1814 } 1815 1816 // This will test for leaks in the remote latency tracking via client.rrTracking 1817 func TestAccountTrackLatencyRemoteLeaks(t *testing.T) { 1818 optsA, err := ProcessConfigFile("./configs/seed.conf") 1819 require_NoError(t, err) 1820 optsA.NoSigs, optsA.NoLog = true, true 1821 optsA.ServerName = "A" 1822 srvA := RunServer(optsA) 1823 defer srvA.Shutdown() 1824 optsB := nextServerOpts(optsA) 1825 optsB.Routes = RoutesFromStr(fmt.Sprintf("nats://%s:%d", optsA.Cluster.Host, optsA.Cluster.Port)) 1826 optsB.ServerName = "B" 1827 srvB := RunServer(optsB) 1828 defer srvB.Shutdown() 1829 1830 checkClusterFormed(t, srvA, srvB) 1831 srvs := []*Server{srvA, srvB} 1832 1833 // Now add in the accounts and setup tracking. 1834 for _, s := range srvs { 1835 s.SetSystemAccount(globalAccountName) 1836 fooAcc, _ := s.RegisterAccount("$foo") 1837 fooAcc.AddServiceExport("track.service", nil) 1838 fooAcc.TrackServiceExport("track.service", "results") 1839 barAcc, _ := s.RegisterAccount("$bar") 1840 if err := barAcc.AddServiceImport(fooAcc, "req", "track.service"); err != nil { 1841 t.Fatalf("Failed to import: %v", err) 1842 } 1843 } 1844 1845 getClient := func(s *Server, name string) *client { 1846 t.Helper() 1847 s.mu.Lock() 1848 defer s.mu.Unlock() 1849 for _, c := range s.clients { 1850 c.mu.Lock() 1851 n := c.opts.Name 1852 c.mu.Unlock() 1853 if n == name { 1854 return c 1855 } 1856 } 1857 t.Fatalf("Did not find client %q on server %q", name, s.info.ID) 1858 return nil 1859 } 1860 1861 // Test with a responder on second server, srvB. but they will not respond. 1862 cfooNC := natsConnect(t, srvB.ClientURL(), nats.Name("foo")) 1863 defer cfooNC.Close() 1864 cfoo := getClient(srvB, "foo") 1865 fooAcc, _ := srvB.LookupAccount("$foo") 1866 if err := cfoo.registerWithAccount(fooAcc); err != nil { 1867 t.Fatalf("Error registering client with 'foo' account: %v", err) 1868 } 1869 1870 // Set new limits 1871 for _, srv := range srvs { 1872 fooAcc, _ := srv.LookupAccount("$foo") 1873 err := fooAcc.SetServiceExportResponseThreshold("track.service", 5*time.Millisecond) 1874 if err != nil { 1875 t.Fatalf("Error setting response threshold: %v", err) 1876 } 1877 } 1878 1879 // Now setup the responder under cfoo and the listener for the results 1880 time.Sleep(50 * time.Millisecond) 1881 baseSubs := int(srvA.NumSubscriptions()) 1882 fooSub := natsSubSync(t, cfooNC, "track.service") 1883 natsFlush(t, cfooNC) 1884 // Wait for it to propagate. 1885 checkExpectedSubs(t, baseSubs+1, srvA) 1886 1887 cbarNC := natsConnect(t, srvA.ClientURL(), nats.Name("bar")) 1888 defer cbarNC.Close() 1889 cbar := getClient(srvA, "bar") 1890 1891 barAcc, _ := srvA.LookupAccount("$bar") 1892 if err := cbar.registerWithAccount(barAcc); err != nil { 1893 t.Fatalf("Error registering client with 'bar' account: %v", err) 1894 } 1895 1896 readFooMsg := func() { 1897 t.Helper() 1898 if _, err := fooSub.NextMsg(time.Second); err != nil { 1899 t.Fatalf("Did not receive foo msg: %v", err) 1900 } 1901 } 1902 1903 // Send 2 requests 1904 natsSubSync(t, cbarNC, "resp") 1905 1906 natsPubReq(t, cbarNC, "req", "resp", []byte("help")) 1907 natsPubReq(t, cbarNC, "req", "resp", []byte("help")) 1908 1909 readFooMsg() 1910 readFooMsg() 1911 1912 var rc *client 1913 // Pull out first client 1914 srvB.mu.Lock() 1915 for _, rc = range srvB.clients { 1916 if rc != nil { 1917 break 1918 } 1919 } 1920 srvB.mu.Unlock() 1921 1922 tracking := func() int { 1923 rc.mu.Lock() 1924 var nt int 1925 if rc.rrTracking != nil { 1926 nt = len(rc.rrTracking.rmap) 1927 } 1928 rc.mu.Unlock() 1929 return nt 1930 } 1931 1932 expectTracking := func(expected int) { 1933 t.Helper() 1934 checkFor(t, time.Second, 10*time.Millisecond, func() error { 1935 if numTracking := tracking(); numTracking != expected { 1936 return fmt.Errorf("Expected to have %d tracking replies, got %d", expected, numTracking) 1937 } 1938 return nil 1939 }) 1940 } 1941 1942 expectTracking(2) 1943 // Make sure these remote tracking replies honor the current respThresh for a service export. 1944 time.Sleep(10 * time.Millisecond) 1945 expectTracking(0) 1946 // Also make sure tracking is removed 1947 rc.mu.Lock() 1948 removed := rc.rrTracking == nil 1949 rc.mu.Unlock() 1950 if !removed { 1951 t.Fatalf("Expected the rrTracking to be removed") 1952 } 1953 1954 // Now let's test that a lower response threshold is picked up. 1955 fSub := natsSubSync(t, cfooNC, "foo") 1956 natsFlush(t, cfooNC) 1957 1958 // Wait for it to propagate. 1959 checkExpectedSubs(t, baseSubs+4, srvA) 1960 1961 // queue up some first. We want to test changing when rrTracking exists. 1962 natsPubReq(t, cbarNC, "req", "resp", []byte("help")) 1963 readFooMsg() 1964 expectTracking(1) 1965 1966 for _, s := range srvs { 1967 fooAcc, _ := s.LookupAccount("$foo") 1968 barAcc, _ := s.LookupAccount("$bar") 1969 fooAcc.AddServiceExport("foo", nil) 1970 fooAcc.TrackServiceExport("foo", "foo.results") 1971 fooAcc.SetServiceExportResponseThreshold("foo", time.Millisecond) 1972 barAcc.AddServiceImport(fooAcc, "foo", "foo") 1973 } 1974 1975 natsSubSync(t, cbarNC, "reply") 1976 natsPubReq(t, cbarNC, "foo", "reply", []byte("help")) 1977 if _, err := fSub.NextMsg(time.Second); err != nil { 1978 t.Fatalf("Did not receive foo msg: %v", err) 1979 } 1980 expectTracking(2) 1981 1982 rc.mu.Lock() 1983 lrt := rc.rrTracking.lrt 1984 rc.mu.Unlock() 1985 if lrt != time.Millisecond { 1986 t.Fatalf("Expected lrt of %v, got %v", time.Millisecond, lrt) 1987 } 1988 1989 // Now make sure we clear on close. 1990 rc.closeConnection(ClientClosed) 1991 1992 // Actual tear down will be not inline. 1993 checkFor(t, time.Second, 5*time.Millisecond, func() error { 1994 rc.mu.Lock() 1995 removed = rc.rrTracking == nil 1996 rc.mu.Unlock() 1997 if !removed { 1998 return fmt.Errorf("Expected the rrTracking to be removed after client close") 1999 } 2000 return nil 2001 }) 2002 } 2003 2004 func TestCrossAccountServiceResponseTypes(t *testing.T) { 2005 s, fooAcc, barAcc := simpleAccountServer(t) 2006 defer s.Shutdown() 2007 2008 cfoo, crFoo, _ := newClientForServer(s) 2009 defer cfoo.close() 2010 2011 if err := cfoo.registerWithAccount(fooAcc); err != nil { 2012 t.Fatalf("Error registering client with 'foo' account: %v", err) 2013 } 2014 cbar, crBar, _ := newClientForServer(s) 2015 defer cbar.close() 2016 2017 if err := cbar.registerWithAccount(barAcc); err != nil { 2018 t.Fatalf("Error registering client with 'bar' account: %v", err) 2019 } 2020 2021 // Add in the service export for the requests. Make it public. 2022 if err := fooAcc.AddServiceExportWithResponse("test.request", Streamed, nil); err != nil { 2023 t.Fatalf("Error adding account service export to client foo: %v", err) 2024 } 2025 // Now add in the route mapping for request to be routed to the foo account. 2026 if err := barAcc.AddServiceImport(fooAcc, "foo", "test.request"); err != nil { 2027 t.Fatalf("Error adding account service import to client bar: %v", err) 2028 } 2029 2030 // Now setup the resonder under cfoo 2031 cfoo.parse([]byte("SUB test.request 1\r\n")) 2032 2033 // Now send the request. Remember we expect the request on our local foo. We added the route 2034 // with that "from" and will map it to "test.request" 2035 cbar.parseAsync("SUB bar 11\r\nPUB foo bar 4\r\nhelp\r\n") 2036 2037 // Now read the request from crFoo 2038 l, err := crFoo.ReadString('\n') 2039 if err != nil { 2040 t.Fatalf("Error reading from client 'bar': %v", err) 2041 } 2042 2043 mraw := msgPat.FindAllStringSubmatch(l, -1) 2044 if len(mraw) == 0 { 2045 t.Fatalf("No message received") 2046 } 2047 matches := mraw[0] 2048 reply := matches[REPLY_INDEX] 2049 if !strings.HasPrefix(reply, "_R_.") { 2050 t.Fatalf("Expected an _R_.* like reply, got '%s'", reply) 2051 } 2052 crFoo.ReadString('\n') 2053 2054 replyOp := fmt.Sprintf("PUB %s 2\r\n22\r\n", matches[REPLY_INDEX]) 2055 var mReply []byte 2056 for i := 0; i < 10; i++ { 2057 mReply = append(mReply, replyOp...) 2058 } 2059 2060 cfoo.parseAsync(string(mReply)) 2061 2062 var buf []byte 2063 for i := 0; i < 20; i++ { 2064 b, err := crBar.ReadBytes('\n') 2065 if err != nil { 2066 t.Fatalf("Error reading response: %v", err) 2067 } 2068 buf = append(buf[:], b...) 2069 if mraw = msgPat.FindAllStringSubmatch(string(buf), -1); len(mraw) == 10 { 2070 break 2071 } 2072 } 2073 if len(mraw) != 10 { 2074 t.Fatalf("Expected a response but got %d", len(mraw)) 2075 } 2076 2077 // Also make sure the response map gets cleaned up when interest goes away. 2078 cbar.closeConnection(ClientClosed) 2079 2080 checkFor(t, time.Second, 10*time.Millisecond, func() error { 2081 if nr := barAcc.NumPendingAllResponses(); nr != 0 { 2082 return fmt.Errorf("Number of responses is %d", nr) 2083 } 2084 return nil 2085 }) 2086 2087 // Now test bogus reply subjects are handled and do not accumulate the response maps. 2088 cbar, _, _ = newClientForServer(s) 2089 defer cbar.close() 2090 2091 if err := cbar.registerWithAccount(barAcc); err != nil { 2092 t.Fatalf("Error registering client with 'bar' account: %v", err) 2093 } 2094 2095 // Do not create any interest in the reply subject 'bar'. Just send a request. 2096 cbar.parseAsync("PUB foo bar 4\r\nhelp\r\n") 2097 2098 // Now read the request from crFoo 2099 l, err = crFoo.ReadString('\n') 2100 if err != nil { 2101 t.Fatalf("Error reading from client 'bar': %v", err) 2102 } 2103 mraw = msgPat.FindAllStringSubmatch(l, -1) 2104 if len(mraw) == 0 { 2105 t.Fatalf("No message received") 2106 } 2107 matches = mraw[0] 2108 reply = matches[REPLY_INDEX] 2109 if !strings.HasPrefix(reply, "_R_.") { 2110 t.Fatalf("Expected an _R_.* like reply, got '%s'", reply) 2111 } 2112 crFoo.ReadString('\n') 2113 2114 replyOp = fmt.Sprintf("PUB %s 2\r\n22\r\n", matches[REPLY_INDEX]) 2115 2116 cfoo.parseAsync(replyOp) 2117 2118 // Now wait for a bit, the reply should trip a no interest condition 2119 // which should clean this up. 2120 checkFor(t, time.Second, 10*time.Millisecond, func() error { 2121 if nr := fooAcc.NumPendingAllResponses(); nr != 0 { 2122 return fmt.Errorf("Number of responses is %d", nr) 2123 } 2124 return nil 2125 }) 2126 2127 // Also make sure the response map entry is gone as well. 2128 fooAcc.mu.RLock() 2129 lrm := len(fooAcc.exports.responses) 2130 fooAcc.mu.RUnlock() 2131 2132 if lrm != 0 { 2133 t.Fatalf("Expected the responses to be cleared, got %d entries", lrm) 2134 } 2135 } 2136 2137 func TestAccountMapsUsers(t *testing.T) { 2138 // Used for the nkey users to properly sign. 2139 seed1 := "SUAPM67TC4RHQLKBX55NIQXSMATZDOZK6FNEOSS36CAYA7F7TY66LP4BOM" 2140 seed2 := "SUAIS5JPX4X4GJ7EIIJEQ56DH2GWPYJRPWN5XJEDENJOZHCBLI7SEPUQDE" 2141 2142 confFileName := createConfFile(t, []byte(` 2143 accounts { 2144 synadia { 2145 users = [ 2146 {user: derek, password: foo}, 2147 {nkey: UCNGL4W5QX66CFX6A6DCBVDH5VOHMI7B2UZZU7TXAUQQSI2JPHULCKBR} 2148 ] 2149 } 2150 nats { 2151 users = [ 2152 {user: ivan, password: bar}, 2153 {nkey: UDPGQVFIWZ7Q5UH4I5E6DBCZULQS6VTVBG6CYBD7JV3G3N2GMQOMNAUH} 2154 ] 2155 } 2156 } 2157 `)) 2158 opts, err := ProcessConfigFile(confFileName) 2159 if err != nil { 2160 t.Fatalf("Unexpected error parsing config file: %v", err) 2161 } 2162 opts.NoSigs = true 2163 s := New(opts) 2164 defer s.Shutdown() 2165 synadia, _ := s.LookupAccount("synadia") 2166 nats, _ := s.LookupAccount("nats") 2167 2168 if synadia == nil || nats == nil { 2169 t.Fatalf("Expected non nil accounts during lookup") 2170 } 2171 2172 // Make sure a normal log in maps the accounts correctly. 2173 c, _, _ := newClientForServer(s) 2174 defer c.close() 2175 connectOp := []byte("CONNECT {\"user\":\"derek\",\"pass\":\"foo\"}\r\n") 2176 c.parse(connectOp) 2177 if c.acc != synadia { 2178 t.Fatalf("Expected the client's account to match 'synadia', got %v", c.acc) 2179 } 2180 2181 c, _, _ = newClientForServer(s) 2182 defer c.close() 2183 connectOp = []byte("CONNECT {\"user\":\"ivan\",\"pass\":\"bar\"}\r\n") 2184 c.parse(connectOp) 2185 if c.acc != nats { 2186 t.Fatalf("Expected the client's account to match 'nats', got %v", c.acc) 2187 } 2188 2189 // Now test nkeys as well. 2190 kp, _ := nkeys.FromSeed([]byte(seed1)) 2191 pubKey, _ := kp.PublicKey() 2192 2193 c, cr, l := newClientForServer(s) 2194 defer c.close() 2195 // Check for Nonce 2196 var info nonceInfo 2197 err = json.Unmarshal([]byte(l[5:]), &info) 2198 if err != nil { 2199 t.Fatalf("Could not parse INFO json: %v\n", err) 2200 } 2201 if info.Nonce == "" { 2202 t.Fatalf("Expected a non-empty nonce with nkeys defined") 2203 } 2204 sigraw, err := kp.Sign([]byte(info.Nonce)) 2205 if err != nil { 2206 t.Fatalf("Failed signing nonce: %v", err) 2207 } 2208 sig := base64.RawURLEncoding.EncodeToString(sigraw) 2209 2210 // PING needed to flush the +OK to us. 2211 cs := fmt.Sprintf("CONNECT {\"nkey\":%q,\"sig\":\"%s\",\"verbose\":true,\"pedantic\":true}\r\nPING\r\n", pubKey, sig) 2212 c.parseAsync(cs) 2213 l, _ = cr.ReadString('\n') 2214 if !strings.HasPrefix(l, "+OK") { 2215 t.Fatalf("Expected an OK, got: %v", l) 2216 } 2217 if c.acc != synadia { 2218 t.Fatalf("Expected the nkey client's account to match 'synadia', got %v", c.acc) 2219 } 2220 2221 // Now nats account nkey user. 2222 kp, _ = nkeys.FromSeed([]byte(seed2)) 2223 pubKey, _ = kp.PublicKey() 2224 2225 c, cr, l = newClientForServer(s) 2226 defer c.close() 2227 // Check for Nonce 2228 err = json.Unmarshal([]byte(l[5:]), &info) 2229 if err != nil { 2230 t.Fatalf("Could not parse INFO json: %v\n", err) 2231 } 2232 if info.Nonce == "" { 2233 t.Fatalf("Expected a non-empty nonce with nkeys defined") 2234 } 2235 sigraw, err = kp.Sign([]byte(info.Nonce)) 2236 if err != nil { 2237 t.Fatalf("Failed signing nonce: %v", err) 2238 } 2239 sig = base64.RawURLEncoding.EncodeToString(sigraw) 2240 2241 // PING needed to flush the +OK to us. 2242 cs = fmt.Sprintf("CONNECT {\"nkey\":%q,\"sig\":\"%s\",\"verbose\":true,\"pedantic\":true}\r\nPING\r\n", pubKey, sig) 2243 c.parseAsync(cs) 2244 l, _ = cr.ReadString('\n') 2245 if !strings.HasPrefix(l, "+OK") { 2246 t.Fatalf("Expected an OK, got: %v", l) 2247 } 2248 if c.acc != nats { 2249 t.Fatalf("Expected the nkey client's account to match 'nats', got %v", c.acc) 2250 } 2251 } 2252 2253 func TestAccountGlobalDefault(t *testing.T) { 2254 opts := defaultServerOptions 2255 s := New(&opts) 2256 2257 if acc, _ := s.LookupAccount(globalAccountName); acc == nil { 2258 t.Fatalf("Expected a global default account on a new server, got none.") 2259 } 2260 // Make sure we can not create one with same name.. 2261 if _, err := s.RegisterAccount(globalAccountName); err == nil { 2262 t.Fatalf("Expected error trying to create a new reserved account") 2263 } 2264 2265 // Make sure we can not define one in a config file either. 2266 confFileName := createConfFile(t, []byte(`accounts { $G {} }`)) 2267 2268 if _, err := ProcessConfigFile(confFileName); err == nil { 2269 t.Fatalf("Expected an error parsing config file with reserved account") 2270 } 2271 } 2272 2273 func TestAccountCheckStreamImportsEqual(t *testing.T) { 2274 // Create bare accounts for this test 2275 fooAcc := NewAccount("foo") 2276 if err := fooAcc.AddStreamExport(">", nil); err != nil { 2277 t.Fatalf("Error adding stream export: %v", err) 2278 } 2279 2280 barAcc := NewAccount("bar") 2281 if err := barAcc.AddStreamImport(fooAcc, "foo", "myPrefix"); err != nil { 2282 t.Fatalf("Error adding stream import: %v", err) 2283 } 2284 bazAcc := NewAccount("baz") 2285 if err := bazAcc.AddStreamImport(fooAcc, "foo", "myPrefix"); err != nil { 2286 t.Fatalf("Error adding stream import: %v", err) 2287 } 2288 if !barAcc.checkStreamImportsEqual(bazAcc) { 2289 t.Fatal("Expected stream imports to be the same") 2290 } 2291 2292 if err := bazAcc.AddStreamImport(fooAcc, "foo.>", ""); err != nil { 2293 t.Fatalf("Error adding stream import: %v", err) 2294 } 2295 if barAcc.checkStreamImportsEqual(bazAcc) { 2296 t.Fatal("Expected stream imports to be different") 2297 } 2298 if err := barAcc.AddStreamImport(fooAcc, "foo.>", ""); err != nil { 2299 t.Fatalf("Error adding stream import: %v", err) 2300 } 2301 if !barAcc.checkStreamImportsEqual(bazAcc) { 2302 t.Fatal("Expected stream imports to be the same") 2303 } 2304 2305 // Create another account that is named "foo". We want to make sure 2306 // that the comparison still works (based on account name, not pointer) 2307 newFooAcc := NewAccount("foo") 2308 if err := newFooAcc.AddStreamExport(">", nil); err != nil { 2309 t.Fatalf("Error adding stream export: %v", err) 2310 } 2311 batAcc := NewAccount("bat") 2312 if err := batAcc.AddStreamImport(newFooAcc, "foo", "myPrefix"); err != nil { 2313 t.Fatalf("Error adding stream import: %v", err) 2314 } 2315 if err := batAcc.AddStreamImport(newFooAcc, "foo.>", ""); err != nil { 2316 t.Fatalf("Error adding stream import: %v", err) 2317 } 2318 if !batAcc.checkStreamImportsEqual(barAcc) { 2319 t.Fatal("Expected stream imports to be the same") 2320 } 2321 if !batAcc.checkStreamImportsEqual(bazAcc) { 2322 t.Fatal("Expected stream imports to be the same") 2323 } 2324 2325 // Test with account with different "from" 2326 expAcc := NewAccount("new_acc") 2327 if err := expAcc.AddStreamExport(">", nil); err != nil { 2328 t.Fatalf("Error adding stream export: %v", err) 2329 } 2330 aAcc := NewAccount("a") 2331 if err := aAcc.AddStreamImport(expAcc, "bar", ""); err != nil { 2332 t.Fatalf("Error adding stream import: %v", err) 2333 } 2334 bAcc := NewAccount("b") 2335 if err := bAcc.AddStreamImport(expAcc, "baz", ""); err != nil { 2336 t.Fatalf("Error adding stream import: %v", err) 2337 } 2338 if aAcc.checkStreamImportsEqual(bAcc) { 2339 t.Fatal("Expected stream imports to be different") 2340 } 2341 2342 // Test with account with different "prefix" 2343 aAcc = NewAccount("a") 2344 if err := aAcc.AddStreamImport(expAcc, "bar", "prefix"); err != nil { 2345 t.Fatalf("Error adding stream import: %v", err) 2346 } 2347 bAcc = NewAccount("b") 2348 if err := bAcc.AddStreamImport(expAcc, "bar", "diff_prefix"); err != nil { 2349 t.Fatalf("Error adding stream import: %v", err) 2350 } 2351 if aAcc.checkStreamImportsEqual(bAcc) { 2352 t.Fatal("Expected stream imports to be different") 2353 } 2354 2355 // Test with account with different "name" 2356 expAcc = NewAccount("diff_name") 2357 if err := expAcc.AddStreamExport(">", nil); err != nil { 2358 t.Fatalf("Error adding stream export: %v", err) 2359 } 2360 bAcc = NewAccount("b") 2361 if err := bAcc.AddStreamImport(expAcc, "bar", "prefix"); err != nil { 2362 t.Fatalf("Error adding stream import: %v", err) 2363 } 2364 if aAcc.checkStreamImportsEqual(bAcc) { 2365 t.Fatal("Expected stream imports to be different") 2366 } 2367 } 2368 2369 func TestAccountNoDeadlockOnQueueSubRouteMapUpdate(t *testing.T) { 2370 opts := DefaultOptions() 2371 s := RunServer(opts) 2372 defer s.Shutdown() 2373 2374 nc, err := nats.Connect(fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port)) 2375 if err != nil { 2376 t.Fatalf("Error on connect: %v", err) 2377 } 2378 defer nc.Close() 2379 2380 nc.QueueSubscribeSync("foo", "bar") 2381 2382 var accs []*Account 2383 for i := 0; i < 10; i++ { 2384 acc, _ := s.RegisterAccount(fmt.Sprintf("acc%d", i)) 2385 acc.mu.Lock() 2386 accs = append(accs, acc) 2387 } 2388 2389 opts2 := DefaultOptions() 2390 opts2.Routes = RoutesFromStr(fmt.Sprintf("nats://%s:%d", opts.Cluster.Host, opts.Cluster.Port)) 2391 s2 := RunServer(opts2) 2392 defer s2.Shutdown() 2393 2394 wg := sync.WaitGroup{} 2395 wg.Add(1) 2396 go func() { 2397 time.Sleep(100 * time.Millisecond) 2398 for _, acc := range accs { 2399 acc.mu.Unlock() 2400 } 2401 wg.Done() 2402 }() 2403 2404 nc.QueueSubscribeSync("foo", "bar") 2405 nc.Flush() 2406 2407 wg.Wait() 2408 } 2409 2410 func TestAccountDuplicateServiceImportSubject(t *testing.T) { 2411 opts := DefaultOptions() 2412 s := RunServer(opts) 2413 defer s.Shutdown() 2414 2415 fooAcc, _ := s.RegisterAccount("foo") 2416 fooAcc.AddServiceExport("remote1", nil) 2417 fooAcc.AddServiceExport("remote2", nil) 2418 2419 barAcc, _ := s.RegisterAccount("bar") 2420 if err := barAcc.AddServiceImport(fooAcc, "foo", "remote1"); err != nil { 2421 t.Fatalf("Error adding service import: %v", err) 2422 } 2423 if err := barAcc.AddServiceImport(fooAcc, "foo", "remote2"); err == nil || !strings.Contains(err.Error(), "duplicate") { 2424 t.Fatalf("Expected an error about duplicate service import subject, got %q", err) 2425 } 2426 } 2427 2428 func TestMultipleStreamImportsWithSameSubjectDifferentPrefix(t *testing.T) { 2429 opts := DefaultOptions() 2430 s := RunServer(opts) 2431 defer s.Shutdown() 2432 2433 fooAcc, _ := s.RegisterAccount("foo") 2434 fooAcc.AddStreamExport("test", nil) 2435 2436 barAcc, _ := s.RegisterAccount("bar") 2437 barAcc.AddStreamExport("test", nil) 2438 2439 importAcc, _ := s.RegisterAccount("import") 2440 2441 if err := importAcc.AddStreamImport(fooAcc, "test", "foo"); err != nil { 2442 t.Fatalf("Unexpected error: %v", err) 2443 } 2444 if err := importAcc.AddStreamImport(barAcc, "test", "bar"); err != nil { 2445 t.Fatalf("Unexpected error: %v", err) 2446 } 2447 2448 // Now make sure we can see messages from both. 2449 cimport, crImport, _ := newClientForServer(s) 2450 defer cimport.close() 2451 if err := cimport.registerWithAccount(importAcc); err != nil { 2452 t.Fatalf("Error registering client with 'import' account: %v", err) 2453 } 2454 if err := cimport.parse([]byte("SUB *.test 1\r\n")); err != nil { 2455 t.Fatalf("Error for client 'import' from server: %v", err) 2456 } 2457 2458 cfoo, _, _ := newClientForServer(s) 2459 defer cfoo.close() 2460 if err := cfoo.registerWithAccount(fooAcc); err != nil { 2461 t.Fatalf("Error registering client with 'foo' account: %v", err) 2462 } 2463 2464 cbar, _, _ := newClientForServer(s) 2465 defer cbar.close() 2466 if err := cbar.registerWithAccount(barAcc); err != nil { 2467 t.Fatalf("Error registering client with 'bar' account: %v", err) 2468 } 2469 2470 readMsg := func() { 2471 t.Helper() 2472 l, err := crImport.ReadString('\n') 2473 if err != nil { 2474 t.Fatalf("Error reading msg header from client 'import': %v", err) 2475 } 2476 mraw := msgPat.FindAllStringSubmatch(l, -1) 2477 if len(mraw) == 0 { 2478 t.Fatalf("No message received") 2479 } 2480 // Consume msg body too. 2481 if _, err = crImport.ReadString('\n'); err != nil { 2482 t.Fatalf("Error reading msg body from client 'import': %v", err) 2483 } 2484 } 2485 2486 cbar.parseAsync("PUB test 9\r\nhello-bar\r\n") 2487 readMsg() 2488 2489 cfoo.parseAsync("PUB test 9\r\nhello-foo\r\n") 2490 readMsg() 2491 } 2492 2493 // This should work with prefixes that are different but we also want it to just work with same subject 2494 // being imported from multiple accounts. 2495 func TestMultipleStreamImportsWithSameSubject(t *testing.T) { 2496 opts := DefaultOptions() 2497 s := RunServer(opts) 2498 defer s.Shutdown() 2499 2500 fooAcc, _ := s.RegisterAccount("foo") 2501 fooAcc.AddStreamExport("test", nil) 2502 2503 barAcc, _ := s.RegisterAccount("bar") 2504 barAcc.AddStreamExport("test", nil) 2505 2506 importAcc, _ := s.RegisterAccount("import") 2507 2508 if err := importAcc.AddStreamImport(fooAcc, "test", ""); err != nil { 2509 t.Fatalf("Unexpected error: %v", err) 2510 } 2511 // Since we allow this now, make sure we do detect a duplicate import from same account etc. 2512 // That should be not allowed. 2513 if err := importAcc.AddStreamImport(fooAcc, "test", ""); err != ErrStreamImportDuplicate { 2514 t.Fatalf("Expected ErrStreamImportDuplicate but got %v", err) 2515 } 2516 2517 if err := importAcc.AddStreamImport(barAcc, "test", ""); err != nil { 2518 t.Fatalf("Unexpected error: %v", err) 2519 } 2520 2521 // Now make sure we can see messages from both. 2522 cimport, crImport, _ := newClientForServer(s) 2523 defer cimport.close() 2524 if err := cimport.registerWithAccount(importAcc); err != nil { 2525 t.Fatalf("Error registering client with 'import' account: %v", err) 2526 } 2527 if err := cimport.parse([]byte("SUB test 1\r\n")); err != nil { 2528 t.Fatalf("Error for client 'import' from server: %v", err) 2529 } 2530 2531 cfoo, _, _ := newClientForServer(s) 2532 defer cfoo.close() 2533 if err := cfoo.registerWithAccount(fooAcc); err != nil { 2534 t.Fatalf("Error registering client with 'foo' account: %v", err) 2535 } 2536 2537 cbar, _, _ := newClientForServer(s) 2538 defer cbar.close() 2539 if err := cbar.registerWithAccount(barAcc); err != nil { 2540 t.Fatalf("Error registering client with 'bar' account: %v", err) 2541 } 2542 2543 readMsg := func() { 2544 t.Helper() 2545 l, err := crImport.ReadString('\n') 2546 if err != nil { 2547 t.Fatalf("Error reading msg header from client 'import': %v", err) 2548 } 2549 mraw := msgPat.FindAllStringSubmatch(l, -1) 2550 if len(mraw) == 0 { 2551 t.Fatalf("No message received") 2552 } 2553 // Consume msg body too. 2554 if _, err = crImport.ReadString('\n'); err != nil { 2555 t.Fatalf("Error reading msg body from client 'import': %v", err) 2556 } 2557 } 2558 2559 cbar.parseAsync("PUB test 9\r\nhello-bar\r\n") 2560 readMsg() 2561 2562 cfoo.parseAsync("PUB test 9\r\nhello-foo\r\n") 2563 readMsg() 2564 } 2565 2566 func TestAccountBasicRouteMapping(t *testing.T) { 2567 opts := DefaultOptions() 2568 opts.Port = -1 2569 s := RunServer(opts) 2570 defer s.Shutdown() 2571 2572 acc, _ := s.LookupAccount(DEFAULT_GLOBAL_ACCOUNT) 2573 acc.AddMapping("foo", "bar") 2574 2575 nc := natsConnect(t, s.ClientURL()) 2576 defer nc.Close() 2577 2578 fsub, _ := nc.SubscribeSync("foo") 2579 bsub, _ := nc.SubscribeSync("bar") 2580 nc.Publish("foo", nil) 2581 nc.Flush() 2582 2583 checkPending := func(sub *nats.Subscription, expected int) { 2584 t.Helper() 2585 if n, _, _ := sub.Pending(); n != expected { 2586 t.Fatalf("Expected %d msgs for %q, but got %d", expected, sub.Subject, n) 2587 } 2588 } 2589 2590 checkPending(fsub, 0) 2591 checkPending(bsub, 1) 2592 2593 acc.RemoveMapping("foo") 2594 2595 nc.Publish("foo", nil) 2596 nc.Flush() 2597 2598 checkPending(fsub, 1) 2599 checkPending(bsub, 1) 2600 } 2601 2602 func TestAccountWildcardRouteMapping(t *testing.T) { 2603 opts := DefaultOptions() 2604 opts.Port = -1 2605 s := RunServer(opts) 2606 defer s.Shutdown() 2607 2608 acc, _ := s.LookupAccount(DEFAULT_GLOBAL_ACCOUNT) 2609 2610 addMap := func(src, dest string) { 2611 t.Helper() 2612 if err := acc.AddMapping(src, dest); err != nil { 2613 t.Fatalf("Error adding mapping: %v", err) 2614 } 2615 } 2616 2617 addMap("foo.*.*", "bar.$2.$1") 2618 addMap("bar.*.>", "baz.$1.>") 2619 2620 nc := natsConnect(t, s.ClientURL()) 2621 defer nc.Close() 2622 2623 pub := func(subj string) { 2624 t.Helper() 2625 err := nc.Publish(subj, nil) 2626 if err == nil { 2627 err = nc.Flush() 2628 } 2629 if err != nil { 2630 t.Fatalf("Error publishing: %v", err) 2631 } 2632 } 2633 2634 fsub, _ := nc.SubscribeSync("foo.>") 2635 bsub, _ := nc.SubscribeSync("bar.>") 2636 zsub, _ := nc.SubscribeSync("baz.>") 2637 2638 checkPending := func(sub *nats.Subscription, expected int) { 2639 t.Helper() 2640 if n, _, _ := sub.Pending(); n != expected { 2641 t.Fatalf("Expected %d msgs for %q, but got %d", expected, sub.Subject, n) 2642 } 2643 } 2644 2645 pub("foo.1.2") 2646 2647 checkPending(fsub, 0) 2648 checkPending(bsub, 1) 2649 checkPending(zsub, 0) 2650 } 2651 2652 func TestAccountRouteMappingChangesAfterClientStart(t *testing.T) { 2653 opts := DefaultOptions() 2654 opts.Port = -1 2655 s := RunServer(opts) 2656 defer s.Shutdown() 2657 2658 // Create the client first then add in mapping. 2659 nc := natsConnect(t, s.ClientURL()) 2660 defer nc.Close() 2661 2662 nc.Flush() 2663 2664 acc, _ := s.LookupAccount(DEFAULT_GLOBAL_ACCOUNT) 2665 acc.AddMapping("foo", "bar") 2666 2667 fsub, _ := nc.SubscribeSync("foo") 2668 bsub, _ := nc.SubscribeSync("bar") 2669 nc.Publish("foo", nil) 2670 nc.Flush() 2671 2672 checkPending := func(sub *nats.Subscription, expected int) { 2673 t.Helper() 2674 if n, _, _ := sub.Pending(); n != expected { 2675 t.Fatalf("Expected %d msgs for %q, but got %d", expected, sub.Subject, n) 2676 } 2677 } 2678 2679 checkPending(fsub, 0) 2680 checkPending(bsub, 1) 2681 2682 acc.RemoveMapping("foo") 2683 2684 nc.Publish("foo", nil) 2685 nc.Flush() 2686 2687 checkPending(fsub, 1) 2688 checkPending(bsub, 1) 2689 } 2690 2691 func TestAccountSimpleWeightedRouteMapping(t *testing.T) { 2692 opts := DefaultOptions() 2693 opts.Port = -1 2694 s := RunServer(opts) 2695 defer s.Shutdown() 2696 2697 acc, _ := s.LookupAccount(DEFAULT_GLOBAL_ACCOUNT) 2698 acc.AddWeightedMappings("foo", NewMapDest("bar", 50)) 2699 2700 nc := natsConnect(t, s.ClientURL()) 2701 defer nc.Close() 2702 2703 fsub, _ := nc.SubscribeSync("foo") 2704 bsub, _ := nc.SubscribeSync("bar") 2705 2706 total := 500 2707 for i := 0; i < total; i++ { 2708 nc.Publish("foo", nil) 2709 } 2710 nc.Flush() 2711 2712 fpending, _, _ := fsub.Pending() 2713 bpending, _, _ := bsub.Pending() 2714 2715 h := total / 2 2716 tp := h / 5 2717 min, max := h-tp, h+tp 2718 if fpending < min || fpending > max { 2719 t.Fatalf("Expected about %d msgs, got %d and %d", h, fpending, bpending) 2720 } 2721 } 2722 2723 func TestAccountMultiWeightedRouteMappings(t *testing.T) { 2724 opts := DefaultOptions() 2725 opts.Port = -1 2726 s := RunServer(opts) 2727 defer s.Shutdown() 2728 2729 acc, _ := s.LookupAccount(DEFAULT_GLOBAL_ACCOUNT) 2730 2731 // Check failures for bad weights. 2732 shouldErr := func(rds ...*MapDest) { 2733 t.Helper() 2734 if acc.AddWeightedMappings("foo", rds...) == nil { 2735 t.Fatalf("Expected an error, got none") 2736 } 2737 } 2738 shouldNotErr := func(rds ...*MapDest) { 2739 t.Helper() 2740 if err := acc.AddWeightedMappings("foo", rds...); err != nil { 2741 t.Fatalf("Unexpected error: %v", err) 2742 } 2743 } 2744 2745 shouldErr(NewMapDest("bar", 150)) 2746 shouldNotErr(NewMapDest("bar", 50)) 2747 shouldNotErr(NewMapDest("bar", 50), NewMapDest("baz", 50)) 2748 // Same dest duplicated should error. 2749 shouldErr(NewMapDest("bar", 50), NewMapDest("bar", 50)) 2750 // total over 100 2751 shouldErr(NewMapDest("bar", 50), NewMapDest("baz", 60)) 2752 2753 acc.RemoveMapping("foo") 2754 2755 // 20 for original, you can leave it off will be auto-added. 2756 shouldNotErr(NewMapDest("bar", 50), NewMapDest("baz", 30)) 2757 2758 nc := natsConnect(t, s.ClientURL()) 2759 defer nc.Close() 2760 2761 fsub, _ := nc.SubscribeSync("foo") 2762 bsub, _ := nc.SubscribeSync("bar") 2763 zsub, _ := nc.SubscribeSync("baz") 2764 2765 // For checking later. 2766 rds := []struct { 2767 sub *nats.Subscription 2768 w uint8 2769 }{ 2770 {fsub, 20}, 2771 {bsub, 50}, 2772 {zsub, 30}, 2773 } 2774 2775 total := 5000 2776 for i := 0; i < total; i++ { 2777 nc.Publish("foo", nil) 2778 } 2779 nc.Flush() 2780 2781 for _, rd := range rds { 2782 pending, _, _ := rd.sub.Pending() 2783 expected := total / int(100/rd.w) 2784 tp := expected / 5 // 20% 2785 min, max := expected-tp, expected+tp 2786 if pending < min || pending > max { 2787 t.Fatalf("Expected about %d msgs for %q, got %d", expected, rd.sub.Subject, pending) 2788 } 2789 } 2790 } 2791 2792 func TestGlobalAccountRouteMappingsConfiguration(t *testing.T) { 2793 cf := createConfFile(t, []byte(` 2794 port: -1 2795 mappings = { 2796 foo: bar 2797 foo.*: [ { dest: bar.v1.$1, weight: 40% }, { destination: baz.v2.$1, weight: 20 } ] 2798 bar.*.*: RAB.$2.$1 2799 } 2800 `)) 2801 2802 s, _ := RunServerWithConfig(cf) 2803 defer s.Shutdown() 2804 2805 nc := natsConnect(t, s.ClientURL()) 2806 defer nc.Close() 2807 2808 bsub, _ := nc.SubscribeSync("bar") 2809 fsub1, _ := nc.SubscribeSync("bar.v1.>") 2810 fsub2, _ := nc.SubscribeSync("baz.v2.>") 2811 zsub, _ := nc.SubscribeSync("RAB.>") 2812 f22sub, _ := nc.SubscribeSync("foo.*") 2813 2814 checkPending := func(sub *nats.Subscription, expected int) { 2815 t.Helper() 2816 if n, _, _ := sub.Pending(); n != expected { 2817 t.Fatalf("Expected %d msgs for %q, but got %d", expected, sub.Subject, n) 2818 } 2819 } 2820 2821 nc.Publish("foo", nil) 2822 nc.Publish("bar.11.22", nil) 2823 2824 total := 500 2825 for i := 0; i < total; i++ { 2826 nc.Publish("foo.22", nil) 2827 } 2828 nc.Flush() 2829 2830 checkPending(bsub, 1) 2831 checkPending(zsub, 1) 2832 2833 fpending, _, _ := f22sub.Pending() 2834 fpending1, _, _ := fsub1.Pending() 2835 fpending2, _, _ := fsub2.Pending() 2836 2837 if fpending1 < fpending2 || fpending < fpending2 { 2838 t.Fatalf("Loadbalancing seems off for the foo.* mappings: %d and %d and %d", fpending, fpending1, fpending2) 2839 } 2840 } 2841 2842 func TestAccountRouteMappingsConfiguration(t *testing.T) { 2843 cf := createConfFile(t, []byte(` 2844 port: -1 2845 accounts { 2846 synadia { 2847 users = [{user: derek, password: foo}] 2848 mappings = { 2849 foo: bar 2850 foo.*: [ { dest: bar.v1.$1, weight: 40% }, { destination: baz.v2.$1, weight: 20 } ] 2851 bar.*.*: RAB.$2.$1 2852 } 2853 } 2854 } 2855 `)) 2856 2857 s, _ := RunServerWithConfig(cf) 2858 defer s.Shutdown() 2859 2860 // We test functionality above, so for this one just make sure we have mappings for the account. 2861 acc, _ := s.LookupAccount("synadia") 2862 if !acc.hasMappings() { 2863 t.Fatalf("Account %q does not have mappings", "synadia") 2864 } 2865 2866 az, err := s.Accountz(&AccountzOptions{"synadia"}) 2867 if err != nil { 2868 t.Fatalf("Error getting Accountz: %v", err) 2869 } 2870 if az.Account == nil { 2871 t.Fatalf("Expected an Account") 2872 } 2873 if len(az.Account.Mappings) != 3 { 2874 t.Fatalf("Expected %d mappings, saw %d", 3, len(az.Account.Mappings)) 2875 } 2876 } 2877 2878 func TestAccountRouteMappingsWithLossInjection(t *testing.T) { 2879 cf := createConfFile(t, []byte(` 2880 port: -1 2881 mappings = { 2882 foo: { dest: foo, weight: 80% } 2883 bar: { dest: bar, weight: 0% } 2884 } 2885 `)) 2886 2887 s, _ := RunServerWithConfig(cf) 2888 defer s.Shutdown() 2889 2890 nc := natsConnect(t, s.ClientURL()) 2891 defer nc.Close() 2892 2893 sub, _ := nc.SubscribeSync("foo") 2894 2895 total := 1000 2896 for i := 0; i < total; i++ { 2897 nc.Publish("foo", nil) 2898 } 2899 nc.Flush() 2900 2901 if pending, _, _ := sub.Pending(); pending == total { 2902 t.Fatalf("Expected some loss and pending to not be same as sent") 2903 } 2904 2905 sub, _ = nc.SubscribeSync("bar") 2906 for i := 0; i < total; i++ { 2907 nc.Publish("bar", nil) 2908 } 2909 nc.Flush() 2910 2911 if pending, _, _ := sub.Pending(); pending != 0 { 2912 t.Fatalf("Expected all messages to be dropped and pending to be 0, got %d", pending) 2913 } 2914 } 2915 2916 func TestAccountRouteMappingsWithOriginClusterFilter(t *testing.T) { 2917 cf := createConfFile(t, []byte(` 2918 port: -1 2919 mappings = { 2920 foo: { dest: bar, cluster: SYN, weight: 100% } 2921 } 2922 `)) 2923 2924 s, _ := RunServerWithConfig(cf) 2925 defer s.Shutdown() 2926 2927 nc := natsConnect(t, s.ClientURL()) 2928 defer nc.Close() 2929 2930 sub, _ := nc.SubscribeSync("foo") 2931 2932 total := 1000 2933 for i := 0; i < total; i++ { 2934 nc.Publish("foo", nil) 2935 } 2936 nc.Flush() 2937 2938 if pending, _, _ := sub.Pending(); pending != total { 2939 t.Fatalf("Expected pending to be %d, got %d", total, pending) 2940 } 2941 2942 s.setClusterName("SYN") 2943 sub, _ = nc.SubscribeSync("bar") 2944 for i := 0; i < total; i++ { 2945 nc.Publish("foo", nil) 2946 } 2947 nc.Flush() 2948 2949 if pending, _, _ := sub.Pending(); pending != total { 2950 t.Fatalf("Expected pending to be %d, got %d", total, pending) 2951 } 2952 } 2953 2954 func TestAccountServiceImportWithRouteMappings(t *testing.T) { 2955 cf := createConfFile(t, []byte(` 2956 port: -1 2957 accounts { 2958 foo { 2959 users = [{user: derek, password: foo}] 2960 exports = [{service: "request"}] 2961 } 2962 bar { 2963 users = [{user: ivan, password: bar}] 2964 imports = [{service: {account: "foo", subject:"request"}}] 2965 } 2966 } 2967 `)) 2968 2969 s, opts := RunServerWithConfig(cf) 2970 defer s.Shutdown() 2971 2972 acc, _ := s.LookupAccount("foo") 2973 acc.AddMapping("request", "request.v2") 2974 2975 // Create the service client first. 2976 ncFoo := natsConnect(t, fmt.Sprintf("nats://derek:foo@%s:%d", opts.Host, opts.Port)) 2977 defer ncFoo.Close() 2978 2979 fooSub := natsSubSync(t, ncFoo, "request.v2") 2980 ncFoo.Flush() 2981 2982 // Requestor 2983 ncBar := natsConnect(t, fmt.Sprintf("nats://ivan:bar@%s:%d", opts.Host, opts.Port)) 2984 defer ncBar.Close() 2985 2986 ncBar.Publish("request", nil) 2987 ncBar.Flush() 2988 2989 checkFor(t, time.Second, 10*time.Millisecond, func() error { 2990 if n, _, _ := fooSub.Pending(); n != 1 { 2991 return fmt.Errorf("Expected a request for %q, but got %d", fooSub.Subject, n) 2992 } 2993 return nil 2994 }) 2995 } 2996 2997 func TestAccountImportsWithWildcardSupport(t *testing.T) { 2998 cf := createConfFile(t, []byte(` 2999 port: -1 3000 accounts { 3001 foo { 3002 users = [{user: derek, password: foo}] 3003 exports = [ 3004 { service: "request.*" } 3005 { stream: "events.>" } 3006 { stream: "info.*.*.>" } 3007 ] 3008 } 3009 bar { 3010 users = [{user: ivan, password: bar}] 3011 imports = [ 3012 { service: {account: "foo", subject:"request.*"}, to:"my.request.*"} 3013 { stream: {account: "foo", subject:"events.>"}, to:"foo.events.>"} 3014 { stream: {account: "foo", subject:"info.*.*.>"}, to:"foo.info.$2.$1.>"} 3015 ] 3016 } 3017 } 3018 `)) 3019 3020 s, opts := RunServerWithConfig(cf) 3021 defer s.Shutdown() 3022 3023 ncFoo := natsConnect(t, fmt.Sprintf("nats://derek:foo@%s:%d", opts.Host, opts.Port)) 3024 defer ncFoo.Close() 3025 3026 ncBar := natsConnect(t, fmt.Sprintf("nats://ivan:bar@%s:%d", opts.Host, opts.Port)) 3027 defer ncBar.Close() 3028 3029 // Create subscriber for the service endpoint in foo. 3030 _, err := ncFoo.QueueSubscribe("request.*", "t22", func(m *nats.Msg) { 3031 if m.Subject != "request.22" { 3032 t.Fatalf("Expected literal subject for request, got %q", m.Subject) 3033 } 3034 m.Respond([]byte("yes!")) 3035 }) 3036 if err != nil { 3037 t.Fatalf("Error on subscribe: %v", err) 3038 } 3039 ncFoo.Flush() 3040 3041 // Now test service import. 3042 resp, err := ncBar.Request("my.request.22", []byte("yes?"), time.Second) 3043 if err != nil { 3044 t.Fatalf("Expected a response") 3045 } 3046 if string(resp.Data) != "yes!" { 3047 t.Fatalf("Expected a response of %q, got %q", "yes!", resp.Data) 3048 } 3049 3050 // Now test stream imports. 3051 esub, _ := ncBar.SubscribeSync("foo.events.*") // subset 3052 isub, _ := ncBar.SubscribeSync("foo.info.>") 3053 ncBar.Flush() 3054 3055 // Now publish some stream events. 3056 ncFoo.Publish("events.22", nil) 3057 ncFoo.Publish("info.11.22.bar", nil) 3058 ncFoo.Flush() 3059 3060 checkPending := func(sub *nats.Subscription, expected int) { 3061 t.Helper() 3062 checkFor(t, time.Second, 10*time.Millisecond, func() error { 3063 if n, _, _ := sub.Pending(); n != expected { 3064 return fmt.Errorf("Expected %d msgs for %q, but got %d", expected, sub.Subject, n) 3065 } 3066 return nil 3067 }) 3068 } 3069 3070 checkPending(esub, 1) 3071 checkPending(isub, 1) 3072 3073 // Now check to make sure the subjects are correct etc. 3074 m, err := esub.NextMsg(time.Second) 3075 if err != nil { 3076 t.Fatalf("Unexpected error: %v", err) 3077 } 3078 if m.Subject != "foo.events.22" { 3079 t.Fatalf("Incorrect subject for stream import, expected %q, got %q", "foo.events.22", m.Subject) 3080 } 3081 3082 m, err = isub.NextMsg(time.Second) 3083 if err != nil { 3084 t.Fatalf("Unexpected error: %v", err) 3085 } 3086 if m.Subject != "foo.info.22.11.bar" { 3087 t.Fatalf("Incorrect subject for stream import, expected %q, got %q", "foo.info.22.11.bar", m.Subject) 3088 } 3089 } 3090 3091 // duplicates TestJWTAccountImportsWithWildcardSupport (jwt_test.go) in config 3092 func TestAccountImportsWithWildcardSupportStreamAndService(t *testing.T) { 3093 cf := createConfFile(t, []byte(` 3094 port: -1 3095 accounts { 3096 foo { 3097 users = [{user: derek, password: foo}] 3098 exports = [ 3099 { service: "$request.*.$in.*.>" } 3100 { stream: "$events.*.$in.*.>" } 3101 ] 3102 } 3103 bar { 3104 users = [{user: ivan, password: bar}] 3105 imports = [ 3106 { service: {account: "foo", subject:"$request.*.$in.*.>"}, to:"my.request.$2.$1.>"} 3107 { stream: {account: "foo", subject:"$events.*.$in.*.>"}, to:"my.events.$2.$1.>"} 3108 ] 3109 } 3110 } 3111 `)) 3112 3113 s, opts := RunServerWithConfig(cf) 3114 defer s.Shutdown() 3115 3116 ncFoo := natsConnect(t, fmt.Sprintf("nats://derek:foo@%s:%d", opts.Host, opts.Port)) 3117 defer ncFoo.Close() 3118 3119 ncBar := natsConnect(t, fmt.Sprintf("nats://ivan:bar@%s:%d", opts.Host, opts.Port)) 3120 defer ncBar.Close() 3121 3122 // Create subscriber for the service endpoint in foo. 3123 _, err := ncFoo.Subscribe("$request.>", func(m *nats.Msg) { 3124 if m.Subject != "$request.2.$in.1.bar" { 3125 t.Fatalf("Expected literal subject for request, got %q", m.Subject) 3126 } 3127 m.Respond([]byte("yes!")) 3128 }) 3129 if err != nil { 3130 t.Fatalf("Error on subscribe: %v", err) 3131 } 3132 ncFoo.Flush() 3133 3134 // Now test service import. 3135 if resp, err := ncBar.Request("my.request.1.2.bar", []byte("yes?"), time.Second); err != nil { 3136 t.Fatalf("Expected a response") 3137 } else if string(resp.Data) != "yes!" { 3138 t.Fatalf("Expected a response of %q, got %q", "yes!", resp.Data) 3139 } 3140 subBar, err := ncBar.SubscribeSync("my.events.>") 3141 if err != nil { 3142 t.Fatalf("Expected a response") 3143 } 3144 ncBar.Flush() 3145 3146 ncFoo.Publish("$events.1.$in.2.bar", nil) 3147 3148 m, err := subBar.NextMsg(time.Second) 3149 if err != nil { 3150 t.Fatalf("Expected a response") 3151 } 3152 if m.Subject != "my.events.2.1.bar" { 3153 t.Fatalf("Expected literal subject for request, got %q", m.Subject) 3154 } 3155 } 3156 3157 func BenchmarkNewRouteReply(b *testing.B) { 3158 opts := defaultServerOptions 3159 s := New(&opts) 3160 g := s.globalAccount() 3161 b.ResetTimer() 3162 for i := 0; i < b.N; i++ { 3163 g.newServiceReply(false) 3164 } 3165 } 3166 3167 func TestSamplingHeader(t *testing.T) { 3168 test := func(expectSampling bool, h http.Header) { 3169 t.Helper() 3170 b := strings.Builder{} 3171 b.WriteString("\r\n") // simulate status line 3172 h.Write(&b) 3173 b.WriteString("\r\n") 3174 hdrString := b.String() 3175 c := &client{parseState: parseState{msgBuf: []byte(hdrString), pa: pubArg{hdr: len(hdrString)}}} 3176 sample, hdr := shouldSample(&serviceLatency{0, "foo"}, c) 3177 if expectSampling { 3178 if !sample { 3179 t.Fatal("Expected to sample") 3180 } else if hdr == nil { 3181 t.Fatal("Expected a header") 3182 } 3183 for k, v := range h { 3184 if hdr.Get(k) != v[0] { 3185 t.Fatal("Expect header to match") 3186 } 3187 } 3188 } else { 3189 if sample { 3190 t.Fatal("Expected not to sample") 3191 } else if hdr != nil { 3192 t.Fatal("Expected no header") 3193 } 3194 } 3195 } 3196 3197 test(false, http.Header{"Uber-Trace-Id": []string{"0:0:0:0"}}) 3198 test(false, http.Header{"Uber-Trace-Id": []string{"0:0:0:00"}}) // one byte encoded as two hex digits 3199 test(true, http.Header{"Uber-Trace-Id": []string{"0:0:0:1"}}) 3200 test(true, http.Header{"Uber-Trace-Id": []string{"0:0:0:01"}}) 3201 test(true, http.Header{"Uber-Trace-Id": []string{"0:0:0:5"}}) // debug and sample 3202 test(true, http.Header{"Uber-Trace-Id": []string{"479fefe9525eddb:5adb976bfc1f95c1:479fefe9525eddb:1"}}) 3203 test(true, http.Header{"Uber-Trace-Id": []string{"479fefe9525eddb:479fefe9525eddb:0:1"}}) 3204 test(false, http.Header{"Uber-Trace-Id": []string{"479fefe9525eddb:5adb976bfc1f95c1:479fefe9525eddb:0"}}) 3205 test(false, http.Header{"Uber-Trace-Id": []string{"479fefe9525eddb:479fefe9525eddb:0:0"}}) 3206 3207 test(true, http.Header{"X-B3-Sampled": []string{"1"}}) 3208 test(false, http.Header{"X-B3-Sampled": []string{"0"}}) 3209 test(true, http.Header{"X-B3-TraceId": []string{"80f198ee56343ba864fe8b2a57d3eff7"}}) // decision left to recipient 3210 test(false, http.Header{"X-B3-TraceId": []string{"80f198ee56343ba864fe8b2a57d3eff7"}, "X-B3-Sampled": []string{"0"}}) 3211 test(true, http.Header{"X-B3-TraceId": []string{"80f198ee56343ba864fe8b2a57d3eff7"}, "X-B3-Sampled": []string{"1"}}) 3212 3213 test(false, http.Header{"B3": []string{"0"}}) // deny only 3214 test(false, http.Header{"B3": []string{"0-0-0-0"}}) 3215 test(false, http.Header{"B3": []string{"0-0-0"}}) 3216 test(true, http.Header{"B3": []string{"0-0-1-0"}}) 3217 test(true, http.Header{"B3": []string{"0-0-1"}}) 3218 test(true, http.Header{"B3": []string{"0-0-d"}}) // debug is not a deny 3219 test(true, http.Header{"B3": []string{"80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1-1"}}) 3220 test(true, http.Header{"B3": []string{"80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1-1-05e3ac9a4f6e3b90"}}) 3221 test(false, http.Header{"B3": []string{"80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1-0-05e3ac9a4f6e3b90"}}) 3222 3223 test(true, http.Header{"traceparent": []string{"00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"}}) 3224 test(true, http.Header{"traceparent": []string{"00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-27"}}) 3225 test(false, http.Header{"traceparent": []string{"00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00"}}) 3226 test(false, http.Header{"traceparent": []string{"00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-22"}}) 3227 } 3228 3229 func TestAccountSystemPermsWithGlobalAccess(t *testing.T) { 3230 conf := createConfFile(t, []byte(` 3231 listen: 127.0.0.1:-1 3232 accounts { 3233 $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } 3234 } 3235 `)) 3236 3237 s, _ := RunServerWithConfig(conf) 3238 defer s.Shutdown() 3239 3240 // Make sure we can connect with no auth to global account as normal. 3241 nc, err := nats.Connect(s.ClientURL()) 3242 if err != nil { 3243 t.Fatalf("Failed to create client: %v", err) 3244 } 3245 defer nc.Close() 3246 3247 // Make sure we can connect to the system account with correct credentials. 3248 sc, err := nats.Connect(s.ClientURL(), nats.UserInfo("admin", "s3cr3t!")) 3249 if err != nil { 3250 t.Fatalf("Failed to create system client: %v", err) 3251 } 3252 defer sc.Close() 3253 } 3254 3255 const importSubscriptionOverlapTemplate = ` 3256 listen: 127.0.0.1:-1 3257 accounts: { 3258 ACCOUNT_X: { 3259 users: [ 3260 {user: publisher} 3261 ] 3262 exports: [ 3263 {stream: %s} 3264 ] 3265 }, 3266 ACCOUNT_Y: { 3267 users: [ 3268 {user: subscriber} 3269 ] 3270 imports: [ 3271 {stream: {account: ACCOUNT_X, subject: %s }, %s} 3272 ] 3273 } 3274 }` 3275 3276 func TestImportSubscriptionPartialOverlapWithPrefix(t *testing.T) { 3277 cf := createConfFile(t, []byte(fmt.Sprintf(importSubscriptionOverlapTemplate, ">", ">", "prefix: myprefix"))) 3278 3279 s, opts := RunServerWithConfig(cf) 3280 defer s.Shutdown() 3281 3282 ncX := natsConnect(t, fmt.Sprintf("nats://%s:%s@127.0.0.1:%d", "publisher", "", opts.Port)) 3283 defer ncX.Close() 3284 3285 ncY := natsConnect(t, fmt.Sprintf("nats://%s:%s@127.0.0.1:%d", "subscriber", "", opts.Port)) 3286 defer ncY.Close() 3287 3288 for _, subj := range []string{">", "myprefix.*", "myprefix.>", "myprefix.test", "*.>", "*.*", "*.test"} { 3289 t.Run(subj, func(t *testing.T) { 3290 sub, err := ncY.SubscribeSync(subj) 3291 sub.AutoUnsubscribe(1) 3292 require_NoError(t, err) 3293 require_NoError(t, ncY.Flush()) 3294 3295 ncX.Publish("test", []byte("hello")) 3296 3297 m, err := sub.NextMsg(time.Second) 3298 require_NoError(t, err) 3299 require_True(t, string(m.Data) == "hello") 3300 }) 3301 } 3302 } 3303 3304 func TestImportSubscriptionPartialOverlapWithTransform(t *testing.T) { 3305 cf := createConfFile(t, []byte(fmt.Sprintf(importSubscriptionOverlapTemplate, "*.*.>", "*.*.>", "to: myprefix.$2.$1.>"))) 3306 3307 s, opts := RunServerWithConfig(cf) 3308 defer s.Shutdown() 3309 3310 ncX := natsConnect(t, fmt.Sprintf("nats://%s:%s@127.0.0.1:%d", "publisher", "", opts.Port)) 3311 defer ncX.Close() 3312 3313 ncY := natsConnect(t, fmt.Sprintf("nats://%s:%s@127.0.0.1:%d", "subscriber", "", opts.Port)) 3314 defer ncY.Close() 3315 3316 for _, subj := range []string{">", "*.*.*.>", "*.2.*.>", "*.*.1.>", "*.2.1.>", "*.*.*.*", "*.2.1.*", "*.*.*.test", 3317 "*.*.1.test", "*.2.*.test", "*.2.1.test", "myprefix.*.*.*", "myprefix.>", "myprefix.*.>", "myprefix.*.*.>", 3318 "myprefix.2.>", "myprefix.2.1.>", "myprefix.*.1.>", "myprefix.2.*.>", "myprefix.2.1.*", "myprefix.*.*.test", 3319 "myprefix.2.1.test"} { 3320 t.Run(subj, func(t *testing.T) { 3321 sub, err := ncY.SubscribeSync(subj) 3322 sub.AutoUnsubscribe(1) 3323 require_NoError(t, err) 3324 require_NoError(t, ncY.Flush()) 3325 3326 ncX.Publish("1.2.test", []byte("hello")) 3327 3328 m, err := sub.NextMsg(time.Second) 3329 require_NoError(t, err) 3330 require_True(t, string(m.Data) == "hello") 3331 require_Equal(t, m.Subject, "myprefix.2.1.test") 3332 }) 3333 } 3334 } 3335 3336 func TestAccountLimitsServerConfig(t *testing.T) { 3337 cf := createConfFile(t, []byte(` 3338 port: -1 3339 max_connections: 10 3340 accounts { 3341 MAXC { 3342 users = [{user: derek, password: foo}] 3343 limits { 3344 max_connections: 5 3345 max_subs: 10 3346 max_payload: 32k 3347 max_leafnodes: 1 3348 } 3349 } 3350 } 3351 `)) 3352 3353 s, _ := RunServerWithConfig(cf) 3354 defer s.Shutdown() 3355 3356 acc, err := s.lookupAccount("MAXC") 3357 require_NoError(t, err) 3358 3359 if mc := acc.MaxActiveConnections(); mc != 5 { 3360 t.Fatalf("Did not set MaxActiveConnections properly, expected 5, got %d", mc) 3361 } 3362 if mlc := acc.MaxActiveLeafNodes(); mlc != 1 { 3363 t.Fatalf("Did not set MaxActiveLeafNodes properly, expected 1, got %d", mlc) 3364 } 3365 3366 // Do quick test on connections, but if they are registered above should be good. 3367 for i := 0; i < 5; i++ { 3368 c, err := nats.Connect(s.ClientURL(), nats.UserInfo("derek", "foo")) 3369 require_NoError(t, err) 3370 defer c.Close() 3371 } 3372 3373 // Should fail. 3374 _, err = nats.Connect(s.ClientURL(), nats.UserInfo("derek", "foo")) 3375 require_Error(t, err) 3376 } 3377 3378 func TestAccountUserSubPermsWithQueueGroups(t *testing.T) { 3379 cf := createConfFile(t, []byte(` 3380 listen: 127.0.0.1:-1 3381 3382 authorization { 3383 users = [ 3384 { user: user, password: "pass", 3385 permissions: { 3386 publish: "foo.restricted" 3387 subscribe: { allow: "foo.>", deny: "foo.restricted" } 3388 allow_responses: { max: 1, ttl: 0s } 3389 } 3390 } 3391 ]} 3392 `)) 3393 3394 s, _ := RunServerWithConfig(cf) 3395 defer s.Shutdown() 3396 3397 nc, err := nats.Connect(s.ClientURL(), nats.UserInfo("user", "pass")) 3398 require_NoError(t, err) 3399 defer nc.Close() 3400 3401 // qsub solo. 3402 qsub, err := nc.QueueSubscribeSync("foo.>", "qg") 3403 require_NoError(t, err) 3404 3405 err = nc.Publish("foo.restricted", []byte("RESTRICTED")) 3406 require_NoError(t, err) 3407 nc.Flush() 3408 3409 // Expect no msgs. 3410 checkSubsPending(t, qsub, 0) 3411 } 3412 3413 func TestAccountImportCycle(t *testing.T) { 3414 tmpl := ` 3415 port: -1 3416 accounts: { 3417 CP: { 3418 users: [ 3419 {user: cp, password: cp}, 3420 ], 3421 exports: [ 3422 {service: "q1.>", response_type: Singleton}, 3423 {service: "q2.>", response_type: Singleton}, 3424 %s 3425 ], 3426 }, 3427 A: { 3428 users: [ 3429 {user: a, password: a}, 3430 ], 3431 imports: [ 3432 {service: {account: CP, subject: "q1.>"}}, 3433 {service: {account: CP, subject: "q2.>"}}, 3434 %s 3435 ] 3436 }, 3437 } 3438 ` 3439 cf := createConfFile(t, []byte(fmt.Sprintf(tmpl, _EMPTY_, _EMPTY_))) 3440 s, _ := RunServerWithConfig(cf) 3441 defer s.Shutdown() 3442 ncCp, err := nats.Connect(s.ClientURL(), nats.UserInfo("cp", "cp")) 3443 require_NoError(t, err) 3444 defer ncCp.Close() 3445 ncA, err := nats.Connect(s.ClientURL(), nats.UserInfo("a", "a")) 3446 require_NoError(t, err) 3447 defer ncA.Close() 3448 // setup responder 3449 natsSub(t, ncCp, "q1.>", func(m *nats.Msg) { m.Respond([]byte("reply")) }) 3450 // setup requestor 3451 ib := "q2.inbox" 3452 subAResp, err := ncA.SubscribeSync(ib) 3453 ncA.Flush() 3454 require_NoError(t, err) 3455 req := func() { 3456 t.Helper() 3457 // send request 3458 err = ncA.PublishRequest("q1.a", ib, []byte("test")) 3459 ncA.Flush() 3460 require_NoError(t, err) 3461 mRep, err := subAResp.NextMsg(time.Second) 3462 require_NoError(t, err) 3463 require_Equal(t, string(mRep.Data), "reply") 3464 } 3465 req() 3466 3467 // Update the config and do a config reload and make sure it all still work 3468 changeCurrentConfigContentWithNewContent(t, cf, []byte( 3469 fmt.Sprintf(tmpl, `{service: "q3.>", response_type: Singleton},`, `{service: {account: CP, subject: "q3.>"}},`))) 3470 err = s.Reload() 3471 require_NoError(t, err) 3472 req() 3473 } 3474 3475 func TestAccountImportOwnExport(t *testing.T) { 3476 conf := createConfFile(t, []byte(` 3477 port: -1 3478 accounts: { 3479 A: { 3480 exports: [ 3481 { service: echo, accounts: [A], latency: { subject: "latency.echo" } } 3482 ], 3483 imports: [ 3484 { service: { account: A, subject: echo } } 3485 ] 3486 3487 users: [ 3488 { user: user, pass: pass } 3489 ] 3490 } 3491 } 3492 `)) 3493 s, _ := RunServerWithConfig(conf) 3494 defer s.Shutdown() 3495 3496 nc := natsConnect(t, s.ClientURL(), nats.UserInfo("user", "pass")) 3497 defer nc.Close() 3498 3499 natsSub(t, nc, "echo", func(m *nats.Msg) { m.Respond(nil) }) 3500 _, err := nc.Request("echo", []byte("request"), time.Second) 3501 require_NoError(t, err) 3502 } 3503 3504 // Test for a bug that would cause duplicate deliveries in certain situations when 3505 // service export/imports and leafnodes involved. 3506 // https://github.com/nats-io/nats-server/issues/3191 3507 func TestAccountImportDuplicateResponseDeliveryWithLeafnodes(t *testing.T) { 3508 conf := createConfFile(t, []byte(` 3509 port: -1 3510 accounts: { 3511 A: { 3512 users = [{user: A, password: P}] 3513 exports: [ { service: "foo", response_type: stream } ] 3514 } 3515 B: { 3516 users = [{user: B, password: P}] 3517 imports: [ { service: {account: "A", subject:"foo"} } ] 3518 } 3519 } 3520 leaf { listen: "127.0.0.1:17222" } 3521 `)) 3522 s, _ := RunServerWithConfig(conf) 3523 defer s.Shutdown() 3524 3525 // Requestors will connect to account B. 3526 nc, err := nats.Connect(s.ClientURL(), nats.UserInfo("B", "P")) 3527 require_NoError(t, err) 3528 defer nc.Close() 3529 3530 // By sending a request (regardless of no responders), this will trigger a wildcard _R_ subscription since 3531 // we do not have a leafnode connected. 3532 nc.PublishRequest("foo", "reply", nil) 3533 nc.Flush() 3534 3535 // Now connect the LN. This will be where the service responder lives. 3536 conf = createConfFile(t, []byte(` 3537 port: -1 3538 leaf { 3539 remotes [ { url: "nats://A:P@127.0.0.1:17222" } ] 3540 } 3541 `)) 3542 ln, _ := RunServerWithConfig(conf) 3543 defer ln.Shutdown() 3544 checkLeafNodeConnected(t, s) 3545 3546 // Now attach a responder to the LN. 3547 lnc, err := nats.Connect(ln.ClientURL()) 3548 require_NoError(t, err) 3549 defer lnc.Close() 3550 3551 lnc.Subscribe("foo", func(m *nats.Msg) { 3552 m.Respond([]byte("bar")) 3553 }) 3554 lnc.Flush() 3555 checkSubInterest(t, s, "A", "foo", time.Second) 3556 3557 // Make sure it works, but request only wants one, so need second test to show failure, but 3558 // want to make sure we are wired up correctly. 3559 _, err = nc.Request("foo", nil, time.Second) 3560 require_NoError(t, err) 3561 3562 // Now setup inbox reply so we can check if we get multiple responses. 3563 reply := nats.NewInbox() 3564 sub, err := nc.SubscribeSync(reply) 3565 require_NoError(t, err) 3566 3567 nc.PublishRequest("foo", reply, nil) 3568 3569 // Do another to make sure we know the other request will have been processed too. 3570 _, err = nc.Request("foo", nil, time.Second) 3571 require_NoError(t, err) 3572 3573 if n, _, _ := sub.Pending(); n > 1 { 3574 t.Fatalf("Expected only 1 response, got %d", n) 3575 } 3576 } 3577 3578 func TestAccountReloadServiceImportPanic(t *testing.T) { 3579 conf := createConfFile(t, []byte(` 3580 listen: 127.0.0.1:-1 3581 accounts { 3582 A { 3583 users = [ { user: "a", pass: "p" } ] 3584 exports [ { service: "HELP" } ] 3585 } 3586 B { 3587 users = [ { user: "b", pass: "p" } ] 3588 imports [ { service: { account: A, subject: "HELP"} } ] 3589 } 3590 $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } 3591 } 3592 `)) 3593 3594 s, _ := RunServerWithConfig(conf) 3595 defer s.Shutdown() 3596 3597 // Now connect up the subscriber for HELP. No-op for this test. 3598 nc, _ := jsClientConnect(t, s, nats.UserInfo("a", "p")) 3599 defer nc.Close() 3600 3601 _, err := nc.Subscribe("HELP", func(m *nats.Msg) { m.Respond([]byte("OK")) }) 3602 require_NoError(t, err) 3603 3604 // Now create connection to account b where we will publish to HELP. 3605 nc, _ = jsClientConnect(t, s, nats.UserInfo("b", "p")) 3606 defer nc.Close() 3607 3608 // We want to continually be publishing messages that will trigger the service import while calling reload. 3609 done := make(chan bool) 3610 var wg sync.WaitGroup 3611 wg.Add(1) 3612 3613 var requests, responses atomic.Uint64 3614 reply := nats.NewInbox() 3615 _, err = nc.Subscribe(reply, func(m *nats.Msg) { responses.Add(1) }) 3616 require_NoError(t, err) 3617 3618 go func() { 3619 defer wg.Done() 3620 for { 3621 select { 3622 case <-done: 3623 return 3624 default: 3625 nc.PublishRequest("HELP", reply, []byte("HELP")) 3626 requests.Add(1) 3627 } 3628 } 3629 }() 3630 3631 // Perform a bunch of reloads. 3632 for i := 0; i < 1000; i++ { 3633 require_NoError(t, s.Reload()) 3634 } 3635 3636 close(done) 3637 wg.Wait() 3638 3639 totalRequests := requests.Load() 3640 checkFor(t, 20*time.Second, 250*time.Millisecond, func() error { 3641 resp := responses.Load() 3642 if resp == totalRequests { 3643 return nil 3644 } 3645 return fmt.Errorf("Have not received all responses, want %d got %d", totalRequests, resp) 3646 }) 3647 } 3648 3649 // https://github.com/nats-io/nats-server/issues/4674 3650 func TestAccountServiceAndStreamExportDoubleDelivery(t *testing.T) { 3651 conf := createConfFile(t, []byte(` 3652 listen: 127.0.0.1:-1 3653 accounts: { 3654 tenant1: { 3655 jetstream: enabled 3656 users: [ { user: "one", password: "one" } ] 3657 exports: [ 3658 { stream: "DW.>" } 3659 { service: "DW.>" } 3660 ] 3661 } 3662 global: { 3663 jetstream: enabled 3664 users: [ { user: "global", password: "global" } ] 3665 imports: [ 3666 { stream: { account: tenant1, subject: "DW.>" }, prefix: tenant1 } 3667 { service: { account: tenant1, subject: "DW.>" }, to: "tenant1.DW.>" } 3668 ] 3669 } 3670 $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } 3671 } 3672 `)) 3673 3674 s, _ := RunServerWithConfig(conf) 3675 defer s.Shutdown() 3676 3677 // Now connect up the subscriber for HELP. No-op for this test. 3678 nc, _ := jsClientConnect(t, s, nats.UserInfo("one", "one")) 3679 defer nc.Close() 3680 3681 var msgs atomic.Int32 3682 _, err := nc.Subscribe(">", func(m *nats.Msg) { 3683 msgs.Add(1) 3684 }) 3685 require_NoError(t, err) 3686 3687 nc.Publish("DW.test.123", []byte("test")) 3688 time.Sleep(200 * time.Millisecond) 3689 require_Equal(t, msgs.Load(), 1) 3690 }