package server import ( "context" "net/netip" "testing" "time" "github.com/netbirdio/netbird/management/server/status" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" nbdns "github.com/netbirdio/netbird/dns" "github.com/netbirdio/netbird/management/server/activity" nbgroup "github.com/netbirdio/netbird/management/server/group" nbpeer "github.com/netbirdio/netbird/management/server/peer" "github.com/netbirdio/netbird/management/server/telemetry" ) const ( group1ID = "group1" group2ID = "group2" existingNSGroupName = "existing" existingNSGroupID = "existingNSGroup" nsGroupPeer1Key = "BhRPtynAAYRDy08+q4HTMsos8fs4plTP4NOSh7C1ry8=" nsGroupPeer2Key = "/yF0+vCfv+mRR5k0dca0TrGdO/oiNeAI58gToZm5NyI=" validDomain = "example.com" invalidDomain = "dnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdns.com" testUserID = "testingUser" ) func TestCreateNameServerGroup(t *testing.T) { type input struct { name string description string enabled bool groups []string nameServers []nbdns.NameServer primary bool domains []string searchDomains bool } testCases := []struct { name string inputArgs input shouldCreate bool errFunc require.ErrorAssertionFunc expectedNSGroup *nbdns.NameServerGroup }{ { name: "Create A NS Group With Primary Status", inputArgs: input{ name: "super", description: "super", groups: []string{group1ID}, primary: true, nameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, enabled: true, }, errFunc: require.NoError, shouldCreate: true, expectedNSGroup: &nbdns.NameServerGroup{ Name: "super", Description: "super", Primary: true, Groups: []string{group1ID}, NameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, Enabled: true, }, }, { name: "Create A NS Group With Domains", inputArgs: input{ name: "super", description: "super", groups: []string{group1ID}, primary: false, domains: []string{validDomain}, nameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, enabled: true, }, errFunc: require.NoError, shouldCreate: true, expectedNSGroup: &nbdns.NameServerGroup{ Name: "super", Description: "super", Primary: false, Domains: []string{"example.com"}, Groups: []string{group1ID}, NameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, Enabled: true, }, }, { name: "Should Not Create If Name Exist", inputArgs: input{ name: existingNSGroupName, description: "super", primary: true, groups: []string{group1ID}, nameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, enabled: true, }, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Create If Name Is Small", inputArgs: input{ name: "", description: "super", primary: true, groups: []string{group1ID}, nameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, enabled: true, }, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Create If Name Is Large", inputArgs: input{ name: "1234567890123456789012345678901234567890extra", description: "super", primary: true, groups: []string{group1ID}, nameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, enabled: true, }, errFunc: require.Error, shouldCreate: false, }, { name: "Create A NS Group With No Nameservers Should Fail", inputArgs: input{ name: "super", description: "super", primary: true, groups: []string{group1ID}, nameServers: []nbdns.NameServer{}, enabled: true, }, errFunc: require.Error, shouldCreate: false, }, { name: "Create A NS Group With More Than 3 Nameservers Should Fail", inputArgs: input{ name: "super", description: "super", primary: true, groups: []string{group1ID}, nameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.3.3"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.4.4"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, enabled: true, }, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Create If Groups Is Empty", inputArgs: input{ name: "super", description: "super", primary: true, groups: []string{}, nameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, enabled: true, }, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Create If Group Doesn't Exist", inputArgs: input{ name: "super", description: "super", primary: true, groups: []string{"missingGroup"}, nameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, enabled: true, }, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Create If Group ID Is Invalid", inputArgs: input{ name: "super", description: "super", primary: true, groups: []string{""}, nameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, enabled: true, }, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Create If No Domain Or Primary", inputArgs: input{ name: "super", description: "super", groups: []string{group1ID}, nameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, enabled: true, }, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Create If Domain List Is Invalid", inputArgs: input{ name: "super", description: "super", groups: []string{group1ID}, domains: []string{invalidDomain}, nameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, enabled: true, }, errFunc: require.Error, shouldCreate: false, }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { am, err := createNSManager(t) if err != nil { t.Error("failed to create account manager") } accountID, err := initTestNSAccount(t, am) if err != nil { t.Error("failed to init testing account") } outNSGroup, err := am.CreateNameServerGroup( context.Background(), accountID, testCase.inputArgs.name, testCase.inputArgs.description, testCase.inputArgs.nameServers, testCase.inputArgs.groups, testCase.inputArgs.primary, testCase.inputArgs.domains, testCase.inputArgs.enabled, userID, testCase.inputArgs.searchDomains, ) testCase.errFunc(t, err) if !testCase.shouldCreate { return } // assign generated ID testCase.expectedNSGroup.ID = outNSGroup.ID if !testCase.expectedNSGroup.IsEqual(outNSGroup) { t.Errorf("new nameserver group didn't match expected ns group:\nGot %#v\nExpected:%#v\n", outNSGroup, testCase.expectedNSGroup) } }) } } func TestSaveNameServerGroup(t *testing.T) { existingNSGroup := &nbdns.NameServerGroup{ ID: "testingNSGroup", Name: "super", Description: "super", Primary: true, NameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, Groups: []string{group1ID}, Enabled: true, } validGroups := []string{group2ID} invalidGroups := []string{"nonExisting"} disabledPrimary := false validDomains := []string{validDomain} invalidDomains := []string{invalidDomain} validNameServerList := []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, } invalidNameServerListLarge := []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.3.3"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.4.4"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, } invalidID := "doesntExist" validName := "12345678901234567890qw" invalidNameLarge := "12345678901234567890qwertyuiopqwertyuiop1" invalidNameSmall := "" invalidNameExisting := existingNSGroupName testCases := []struct { name string existingNSGroup *nbdns.NameServerGroup newID *string newName *string newPrimary *bool newDomains []string newNSList []nbdns.NameServer newGroups []string skipCopying bool shouldCreate bool errFunc require.ErrorAssertionFunc expectedNSGroup *nbdns.NameServerGroup }{ { name: "Should Config Name Server Group", existingNSGroup: existingNSGroup, newName: &validName, newGroups: validGroups, newPrimary: &disabledPrimary, newDomains: validDomains, newNSList: validNameServerList, errFunc: require.NoError, shouldCreate: true, expectedNSGroup: &nbdns.NameServerGroup{ ID: "testingNSGroup", Name: validName, Primary: false, Domains: validDomains, Description: "super", NameServers: validNameServerList, Groups: validGroups, Enabled: true, }, }, { name: "Should Not Config If Name Is Small", existingNSGroup: existingNSGroup, newName: &invalidNameSmall, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Config If Name Is Large", existingNSGroup: existingNSGroup, newName: &invalidNameLarge, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Config If Name Exists", existingNSGroup: existingNSGroup, newName: &invalidNameExisting, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Config If ID Don't Exist", existingNSGroup: existingNSGroup, newID: &invalidID, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Config If Nameserver List Is Small", existingNSGroup: existingNSGroup, newNSList: []nbdns.NameServer{}, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Config If Nameserver List Is Large", existingNSGroup: existingNSGroup, newNSList: invalidNameServerListLarge, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Config If Groups List Is Empty", existingNSGroup: existingNSGroup, newGroups: []string{}, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Config If Groups List Has Empty ID", existingNSGroup: existingNSGroup, newGroups: []string{""}, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Config If Groups List Has Non Existing Group ID", existingNSGroup: existingNSGroup, newGroups: invalidGroups, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Config If Domains List Is Empty", existingNSGroup: existingNSGroup, newPrimary: &disabledPrimary, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Config If Primary And Domains", existingNSGroup: existingNSGroup, newPrimary: &existingNSGroup.Primary, newDomains: validDomains, errFunc: require.Error, shouldCreate: false, }, { name: "Should Not Config If Domains List Is Invalid", existingNSGroup: existingNSGroup, newPrimary: &disabledPrimary, newDomains: invalidDomains, errFunc: require.Error, shouldCreate: false, }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { am, err := createNSManager(t) if err != nil { t.Error("failed to create account manager") } accountID, err := initTestNSAccount(t, am) if err != nil { t.Error("failed to init testing account") } testCase.existingNSGroup.AccountID = accountID err = am.Store.SaveNameServerGroup(context.Background(), LockingStrengthUpdate, testCase.existingNSGroup) require.NoError(t, err, "failed to save existing nameserver group") var nsGroupToSave *nbdns.NameServerGroup if !testCase.skipCopying { nsGroupToSave = testCase.existingNSGroup.Copy() if testCase.newID != nil { nsGroupToSave.ID = *testCase.newID } if testCase.newName != nil { nsGroupToSave.Name = *testCase.newName } if testCase.newGroups != nil { nsGroupToSave.Groups = testCase.newGroups } if testCase.newNSList != nil { nsGroupToSave.NameServers = testCase.newNSList } if testCase.newPrimary != nil { nsGroupToSave.Primary = *testCase.newPrimary } if testCase.newDomains != nil { nsGroupToSave.Domains = testCase.newDomains } } err = am.SaveNameServerGroup(context.Background(), accountID, userID, nsGroupToSave) testCase.errFunc(t, err) if !testCase.shouldCreate { return } savedNSGroup, err := am.Store.GetNameServerGroupByID(context.Background(), LockingStrengthShare, accountID, testCase.expectedNSGroup.ID) require.NoError(t, err, "failed to get saved nameserver group") testCase.expectedNSGroup.AccountID = accountID if !testCase.expectedNSGroup.IsEqual(savedNSGroup) { t.Errorf("new nameserver group didn't match expected group:\nGot %#v\nExpected:%#v\n", savedNSGroup, testCase.expectedNSGroup) } }) } } func TestDeleteNameServerGroup(t *testing.T) { nsGroupID := "testingNSGroup" testingNSGroup := &nbdns.NameServerGroup{ ID: nsGroupID, Name: "super", Description: "super", NameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("1.1.2.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, Groups: []string{group1ID}, Enabled: true, } am, err := createNSManager(t) if err != nil { t.Error("failed to create account manager") } accountID, err := initTestNSAccount(t, am) if err != nil { t.Error("failed to init testing account") } testingNSGroup.AccountID = accountID err = am.Store.SaveNameServerGroup(context.Background(), LockingStrengthUpdate, testingNSGroup) require.NoError(t, err, "failed to save nameserver group") err = am.DeleteNameServerGroup(context.Background(), accountID, testingNSGroup.ID, userID) if err != nil { t.Error("deleting nameserver group failed with error: ", err) } _, err = am.Store.GetNameServerGroupByID(context.Background(), LockingStrengthShare, accountID, testingNSGroup.ID) require.NotNil(t, err) sErr, ok := status.FromError(err) require.True(t, ok, "error should be a status error") assert.Equal(t, status.NotFound, sErr.Type(), "nameserver group shouldn't be found after delete") } func TestGetNameServerGroup(t *testing.T) { am, err := createNSManager(t) if err != nil { t.Error("failed to create account manager") } accountID, err := initTestNSAccount(t, am) if err != nil { t.Error("failed to init testing account") } foundGroup, err := am.GetNameServerGroup(context.Background(), accountID, testUserID, existingNSGroupID) if err != nil { t.Error("getting existing nameserver group failed with error: ", err) } if foundGroup == nil { t.Error("got a nil group while getting nameserver group with ID") } _, err = am.GetNameServerGroup(context.Background(), accountID, testUserID, "not existing") if err == nil { t.Error("getting not existing nameserver group should return error, got nil") } } func createNSManager(t *testing.T) (*DefaultAccountManager, error) { t.Helper() store, err := createNSStore(t) if err != nil { return nil, err } eventStore := &activity.InMemoryEventStore{} metrics, err := telemetry.NewDefaultAppMetrics(context.Background()) require.NoError(t, err) return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.selfhosted", eventStore, nil, false, MocIntegratedValidator{}, metrics) } func createNSStore(t *testing.T) (Store, error) { t.Helper() dataDir := t.TempDir() store, cleanUp, err := NewTestStoreFromSQL(context.Background(), "", dataDir) if err != nil { return nil, err } t.Cleanup(cleanUp) return store, nil } func initTestNSAccount(t *testing.T, am *DefaultAccountManager) (string, error) { t.Helper() accountID := "testingAcc" userID := testUserID domain := "example.com" peer1 := &nbpeer.Peer{ Key: nsGroupPeer1Key, Name: "test-host1@netbird.io", Meta: nbpeer.PeerSystemMeta{ Hostname: "test-host1@netbird.io", GoOS: "linux", Kernel: "Linux", Core: "21.04", Platform: "x86_64", OS: "Ubuntu", WtVersion: "development", UIVersion: "development", }, } peer2 := &nbpeer.Peer{ Key: nsGroupPeer2Key, Name: "test-host2@netbird.io", Meta: nbpeer.PeerSystemMeta{ Hostname: "test-host2@netbird.io", GoOS: "linux", Kernel: "Linux", Core: "21.04", Platform: "x86_64", OS: "Ubuntu", WtVersion: "development", UIVersion: "development", }, } existingNSGroup := nbdns.NameServerGroup{ ID: existingNSGroupID, AccountID: accountID, Name: existingNSGroupName, Description: "", NameServers: []nbdns.NameServer{ { IP: netip.MustParseAddr("8.8.8.8"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("8.8.4.4"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, }, Groups: []string{group1ID}, Enabled: true, } err := newAccountWithId(context.Background(), am.Store, accountID, userID, domain) if err != nil { return "", err } err = am.Store.SaveNameServerGroup(context.Background(), LockingStrengthUpdate, &existingNSGroup) if err != nil { return "", err } err = am.Store.SaveGroups(context.Background(), LockingStrengthUpdate, []*nbgroup.Group{ { ID: group1ID, AccountID: accountID, Name: group1ID, }, { ID: group2ID, AccountID: accountID, Name: group2ID, }, }) if err != nil { return "", err } _, _, _, err = am.AddPeer(context.Background(), "", userID, peer1) if err != nil { return "", err } _, _, _, err = am.AddPeer(context.Background(), "", userID, peer2) if err != nil { return "", err } return accountID, nil } func TestValidateDomain(t *testing.T) { testCases := []struct { name string domain string errFunc require.ErrorAssertionFunc }{ { name: "Valid domain name with multiple labels", domain: "123.example.com", errFunc: require.NoError, }, { name: "Valid domain name with hyphen", domain: "test-example.com", errFunc: require.NoError, }, { name: "Invalid domain name with double hyphen", domain: "test--example.com", errFunc: require.Error, }, { name: "Invalid domain name with only one label", domain: "com", errFunc: require.Error, }, { name: "Invalid domain name with a label exceeding 63 characters", domain: "dnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdnsdns.com", errFunc: require.Error, }, { name: "Invalid domain name starting with a hyphen", domain: "-example.com", errFunc: require.Error, }, { name: "Invalid domain name ending with a hyphen", domain: "example.com-", errFunc: require.Error, }, { name: "Invalid domain with unicode", domain: "example?,.com", errFunc: require.Error, }, { name: "Invalid domain with space before top-level domain", domain: "space .example.com", errFunc: require.Error, }, { name: "Invalid domain with trailing space", domain: "example.com ", errFunc: require.Error, }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { testCase.errFunc(t, validateDomain(testCase.domain)) }) } } func TestNameServerAccountPeersUpdate(t *testing.T) { manager, account, peer1, peer2, peer3 := setupNetworkMapTest(t) var newNameServerGroupA *nbdns.NameServerGroup var newNameServerGroupB *nbdns.NameServerGroup err := manager.SaveGroups(context.Background(), account.Id, userID, []*nbgroup.Group{ { ID: "groupA", Name: "GroupA", Peers: []string{}, }, { ID: "groupB", Name: "GroupB", Peers: []string{peer1.ID, peer2.ID, peer3.ID}, }, }) assert.NoError(t, err) updMsg := manager.peersUpdateManager.CreateChannel(context.Background(), peer1.ID) t.Cleanup(func() { manager.peersUpdateManager.CloseChannel(context.Background(), peer1.ID) }) // Creating a nameserver group with a distribution group no peers should not update account peers // and not send peer update t.Run("creating nameserver group with distribution group no peers", func(t *testing.T) { done := make(chan struct{}) go func() { peerShouldNotReceiveUpdate(t, updMsg) close(done) }() newNameServerGroupA, err = manager.CreateNameServerGroup( context.Background(), account.Id, "nsGroupA", "nsGroupA", []nbdns.NameServer{{ IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }}, []string{"groupA"}, true, []string{}, true, userID, false, ) assert.NoError(t, err) select { case <-done: case <-time.After(time.Second): t.Error("timeout waiting for peerShouldNotReceiveUpdate") } }) // saving a nameserver group with a distribution group with no peers should not update account peers // and not send peer update t.Run("saving nameserver group with distribution group no peers", func(t *testing.T) { done := make(chan struct{}) go func() { peerShouldNotReceiveUpdate(t, updMsg) close(done) }() err = manager.SaveNameServerGroup(context.Background(), account.Id, userID, newNameServerGroupA) assert.NoError(t, err) select { case <-done: case <-time.After(time.Second): t.Error("timeout waiting for peerShouldNotReceiveUpdate") } }) // Creating a nameserver group with a distribution group no peers should update account peers and send peer update t.Run("creating nameserver group with distribution group has peers", func(t *testing.T) { done := make(chan struct{}) go func() { peerShouldReceiveUpdate(t, updMsg) close(done) }() newNameServerGroupB, err = manager.CreateNameServerGroup( context.Background(), account.Id, "nsGroupB", "nsGroupB", []nbdns.NameServer{{ IP: netip.MustParseAddr("1.1.1.1"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }}, []string{"groupB"}, true, []string{}, true, userID, false, ) assert.NoError(t, err) select { case <-done: case <-time.After(time.Second): t.Error("timeout waiting for peerShouldNotReceiveUpdate") } }) // saving a nameserver group with a distribution group with peers should update account peers and send peer update t.Run("saving nameserver group with distribution group has peers", func(t *testing.T) { done := make(chan struct{}) go func() { peerShouldReceiveUpdate(t, updMsg) close(done) }() newNameServerGroupB.NameServers = []nbdns.NameServer{ { IP: netip.MustParseAddr("1.1.1.2"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, { IP: netip.MustParseAddr("8.8.8.8"), NSType: nbdns.UDPNameServerType, Port: nbdns.DefaultDNSPort, }, } err = manager.SaveNameServerGroup(context.Background(), account.Id, userID, newNameServerGroupB) assert.NoError(t, err) select { case <-done: case <-time.After(time.Second): t.Error("timeout waiting for peerShouldReceiveUpdate") } }) // Deleting a nameserver group should update account peers and send peer update t.Run("deleting nameserver group", func(t *testing.T) { done := make(chan struct{}) go func() { peerShouldReceiveUpdate(t, updMsg) close(done) }() err = manager.DeleteNameServerGroup(context.Background(), account.Id, newNameServerGroupB.ID, userID) assert.NoError(t, err) select { case <-done: case <-time.After(time.Second): t.Error("timeout waiting for peerShouldReceiveUpdate") } }) }