This is an automated email from the ASF dual-hosted git repository.
srijeet0406 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git
The following commit(s) were added to refs/heads/master by this push:
new e593f36151 Improve unit test coverage for servers folder in Traffic
Ops (#7396)
e593f36151 is described below
commit e593f36151057c04ebe540470c8884b1901c0904
Author: Rima Shah <[email protected]>
AuthorDate: Tue Mar 14 14:49:25 2023 -0600
Improve unit test coverage for servers folder in Traffic Ops (#7396)
* Added unit test for server capability and server server capability
* Added unit tests for server capability and server server capability-1
* Added unit tests for put_status, assignment and server_server_capability-1
* addressed review comments.
* Updated imports and test data
---
.../traffic_ops_golang/server/put_status_test.go | 78 ++++++++++
.../server/servers_assignment_test.go | 84 +++++++++-
.../server/servers_server_capability_test.go | 171 +++++++++++++++++++++
.../servercapability/servercapability.go | 13 +-
.../servercapability/servercapability_test.go | 146 ++++++++++++++++++
5 files changed, 482 insertions(+), 10 deletions(-)
diff --git a/traffic_ops/traffic_ops_golang/server/put_status_test.go
b/traffic_ops/traffic_ops_golang/server/put_status_test.go
new file mode 100644
index 0000000000..82b81e72a8
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/server/put_status_test.go
@@ -0,0 +1,78 @@
+package server
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+ "testing"
+ "time"
+
+ "github.com/apache/trafficcontrol/lib/go-util"
+
+ "github.com/jmoiron/sqlx"
+ "gopkg.in/DATA-DOG/go-sqlmock.v1"
+)
+
+func TestCheckExistingStatusInfo(t *testing.T) {
+ mockDB, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%v' was not expected when opening a stub
database connection", err)
+ }
+ defer mockDB.Close()
+
+ db := sqlx.NewDb(mockDB, "sqlmock")
+ defer db.Close()
+
+ lastUpdated := time.Now()
+ mock.ExpectBegin()
+ rows := sqlmock.NewRows([]string{"status", "status_last_updated"})
+ rows.AddRow(1, lastUpdated)
+ mock.ExpectQuery("SELECT").WithArgs(1).WillReturnRows(rows)
+
+ status, statusLastUpdated := checkExistingStatusInfo(1,
db.MustBegin().Tx)
+ if status != 1 {
+ t.Errorf("Expected server status to be 1, got %v", status)
+ }
+
+ if statusLastUpdated != lastUpdated {
+ t.Errorf("Expected status time: %s, got: %s", lastUpdated,
statusLastUpdated)
+ }
+}
+
+func TestUpdateServerStatusAndOfflineReason(t *testing.T) {
+ mockDB, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%v' was not expected when opening a stub
database connection", err)
+ }
+ defer mockDB.Close()
+
+ db := sqlx.NewDb(mockDB, "sqlmock")
+ defer db.Close()
+
+ lastUpdated := time.Now()
+ mock.ExpectBegin()
+ mock.ExpectExec("UPDATE").WithArgs(2, "no longer needed", lastUpdated,
1).WillReturnResult(sqlmock.NewResult(1, 1))
+ mock.ExpectCommit()
+
+ reason := util.Ptr("no longer needed")
+ err = updateServerStatusAndOfflineReason(2, 2, 1, lastUpdated, reason,
db.MustBegin().Tx)
+ if err != nil {
+ t.Errorf("unable to change the status of the server, error:
%s", err)
+ }
+}
diff --git a/traffic_ops/traffic_ops_golang/server/servers_assignment_test.go
b/traffic_ops/traffic_ops_golang/server/servers_assignment_test.go
index 0aff38a37e..09027be538 100644
--- a/traffic_ops/traffic_ops_golang/server/servers_assignment_test.go
+++ b/traffic_ops/traffic_ops_golang/server/servers_assignment_test.go
@@ -21,12 +21,16 @@ package server
import (
"context"
+ "net/http"
"reflect"
"testing"
"time"
- "github.com/jmoiron/sqlx"
+ "github.com/apache/trafficcontrol/lib/go-tc"
+ "github.com/apache/trafficcontrol/lib/go-util"
+ "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth"
+ "github.com/jmoiron/sqlx"
"github.com/lib/pq"
sqlmock "gopkg.in/DATA-DOG/go-sqlmock.v1"
)
@@ -34,7 +38,7 @@ import (
func TestAssignDsesToServer(t *testing.T) {
mockDB, mock, err := sqlmock.New()
if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub
database connection", err)
+ t.Fatalf("an error '%v' was not expected when opening a stub
database connection", err)
}
defer mockDB.Close()
@@ -103,3 +107,79 @@ func TestAssignDsesToServer(t *testing.T) {
t.Errorf("delivery services assigned: Expected %v. Got %v",
newDses, result)
}
}
+
+func TestCheckForLastServerInActiveDeliveryServices(t *testing.T) {
+ mockDB, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%v' was not expected when opening a stub
database connection", err)
+ }
+ defer mockDB.Close()
+
+ db := sqlx.NewDb(mockDB, "sqlmock")
+ defer db.Close()
+
+ dsIDs := []int{1, 2, 3}
+ mock.ExpectBegin()
+ rows := sqlmock.NewRows([]string{"id", "multi_site_origin", "topology"})
+ rows.AddRow(1, false, util.Ptr(""))
+ mock.ExpectQuery("SELECT").WithArgs(1, tc.DSActiveStateActive,
pq.Array(dsIDs), tc.CacheStatusOnline, tc.CacheStatusReported,
"EDGE%").WillReturnRows(rows)
+ mock.ExpectCommit()
+
+ _, err = checkForLastServerInActiveDeliveryServices(1, "EDGE", dsIDs,
db.MustBegin().Tx)
+ if err != nil {
+ t.Errorf("unable to check server in active DS, got error:%v",
err)
+ }
+}
+
+func TestCheckTenancyAndCDN(t *testing.T) {
+ mockDB, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%v' was not expected when opening a stub
database connection", err)
+ }
+ defer mockDB.Close()
+
+ db := sqlx.NewDb(mockDB, "sqlmock")
+ defer db.Close()
+
+ dsIDs := []int{1}
+ serverInfo := tc.ServerInfo{
+ Cachegroup: "testCG",
+ CachegroupID: 0,
+ CDNID: 1,
+ DomainName: "",
+ HostName: "",
+ ID: 1,
+ Status: "",
+ Type: "EDGE",
+ }
+ user := auth.CurrentUser{
+ UserName: "user",
+ ID: 0,
+ PrivLevel: 0,
+ TenantID: 1,
+ Role: 0,
+ RoleName: "admin",
+ Capabilities: nil,
+ UCDN: "",
+ }
+ mock.ExpectBegin()
+ rows := sqlmock.NewRows([]string{"id", "cdn_id", "tenant_id", "xml_id",
"name"})
+ rows.AddRow(1, 1, 1, "test", "ALL")
+ mock.ExpectQuery("SELECT
deliveryservice.id").WithArgs(pq.Array(dsIDs)).WillReturnRows(rows)
+
+ rows1 := sqlmock.NewRows([]string{"id", "active"})
+ rows1.AddRow(1, true)
+ mock.ExpectQuery("WITH RECURSIVE").WithArgs(user.TenantID,
1).WillReturnRows(rows1)
+ mock.ExpectCommit()
+
+ code, usrErr, sysErr := checkTenancyAndCDN(db.MustBegin().Tx, "ALL", 1,
serverInfo, dsIDs, &user)
+ if usrErr != nil {
+ t.Errorf("unable to check tenancy, either DS doesn't exist or
DS-CDN not the same as server-CDN, incorrect user input: %v", usrErr)
+ }
+ if sysErr != nil {
+ t.Errorf("unable to check tenancy, system error: %v", sysErr)
+ }
+ if code != http.StatusOK {
+ t.Errorf("tenancy and cdn check for a given user failed with
status code:%d", code)
+ }
+}
diff --git
a/traffic_ops/traffic_ops_golang/server/servers_server_capability_test.go
b/traffic_ops/traffic_ops_golang/server/servers_server_capability_test.go
index 097dadecd7..a6ee9e46b2 100644
--- a/traffic_ops/traffic_ops_golang/server/servers_server_capability_test.go
+++ b/traffic_ops/traffic_ops_golang/server/servers_server_capability_test.go
@@ -20,11 +20,76 @@ package server
*/
import (
+ "net/http"
+ "strings"
"testing"
+ "time"
+ "github.com/apache/trafficcontrol/lib/go-tc"
+ "github.com/apache/trafficcontrol/lib/go-util"
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+ "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/test"
+
+ "github.com/jmoiron/sqlx"
+ "github.com/lib/pq"
+ "gopkg.in/DATA-DOG/go-sqlmock.v1"
)
+func getTestSSCs() []tc.ServerServerCapability {
+ sscs := []tc.ServerServerCapability{}
+ testSSC := tc.ServerServerCapability{
+ LastUpdated: &tc.TimeNoMod{Time: time.Now()},
+ Server: util.StrPtr("test"),
+ ServerID: util.IntPtr(1),
+ ServerCapability: util.StrPtr("test"),
+ }
+ sscs = append(sscs, testSSC)
+
+ testSSC1 := testSSC
+ testSSC1.ServerCapability = util.Ptr("blah")
+ sscs = append(sscs, testSSC1)
+
+ return sscs
+}
+
+func TestReadSCs(t *testing.T) {
+ mockDB, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%v' was not expected when opening a stub
database connection", err)
+ }
+ defer mockDB.Close()
+
+ db := sqlx.NewDb(mockDB, "sqlmock")
+ defer db.Close()
+
+ testSCs := getTestSSCs()
+ rows := sqlmock.NewRows([]string{"server_capability", "server",
"last_updated"})
+
+ for _, ts := range testSCs {
+ rows = rows.AddRow(
+ ts.ServerCapability,
+ ts.ServerID,
+ ts.LastUpdated)
+ }
+ mock.ExpectBegin()
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+ mock.ExpectCommit()
+
+ reqInfo := api.APIInfo{Tx: db.MustBegin(), Params:
map[string]string{"serverId": "1"}}
+ obj := TOServerServerCapability{
+ api.APIInfoImpl{ReqInfo: &reqInfo},
+ tc.ServerServerCapability{},
+ }
+ sscs, userErr, sysErr, _, _ := obj.Read(nil, false)
+ if userErr != nil || sysErr != nil {
+ t.Errorf("Read expected: no errors, actual: %v %v", userErr,
sysErr)
+ }
+
+ if len(sscs) != 2 {
+ t.Errorf("ServerServerCapability.Read expected: len(scs) == 1,
actual: %v", len(sscs))
+ }
+}
+
func TestInterfaces(t *testing.T) {
var i interface{}
i = &TOServerServerCapability{}
@@ -42,3 +107,109 @@ func TestInterfaces(t *testing.T) {
t.Errorf("ServerServerCapability must be Identifier")
}
}
+
+func TestFuncs(t *testing.T) {
+ if strings.Index(scSelectQuery(), "SELECT") != 0 {
+ t.Errorf("expected selectQuery to start with SELECT")
+ }
+ if strings.Index(scInsertQuery(), "INSERT") != 0 {
+ t.Errorf("expected insertQuery to start with INSERT")
+ }
+ if strings.Index(scDeleteQuery(), "DELETE") != 0 {
+ t.Errorf("expected deleteQuery to start with DELETE")
+ }
+}
+
+func TestValidate(t *testing.T) {
+ testSSC := tc.ServerServerCapability{
+ LastUpdated: &tc.TimeNoMod{Time: time.Now()},
+ Server: util.StrPtr("test1"),
+ ServerID: util.IntPtr(1),
+ ServerCapability: util.StrPtr("abc"),
+ }
+ testTOSSC := TOServerServerCapability{
+ ServerServerCapability: testSSC,
+ }
+
+ err, _ := testTOSSC.Validate()
+ errs := test.SortErrors(test.SplitErrors(err))
+
+ if len(errs) > 0 {
+ t.Errorf(`expected no errors, got %v`, errs)
+ }
+}
+
+func TestCheckExistingServer(t *testing.T) {
+ mockDB, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub
database connection", err)
+ }
+ defer mockDB.Close()
+
+ db := sqlx.NewDb(mockDB, "sqlmock")
+ defer db.Close()
+
+ mock.ExpectBegin()
+ rows := sqlmock.NewRows([]string{"host_name"})
+ rows.AddRow("test")
+ mock.ExpectQuery("SELECT host_name").WithArgs(1).WillReturnRows(rows)
+
+ rows1 := sqlmock.NewRows([]string{"name"})
+ rows1.AddRow("ALL")
+ mock.ExpectQuery("SELECT name").WithArgs(1).WillReturnRows(rows1)
+
+ rows2 := sqlmock.NewRows([]string{"username", "soft",
"shared_usernames"})
+ rows2.AddRow("user1", false, []byte("{}"))
+ mock.ExpectQuery("SELECT c.username,
c.soft").WithArgs("ALL").WillReturnRows(rows2)
+ mock.ExpectCommit()
+
+ testSCCs := getTestSSCs()
+ var sids []int64
+ sids = append(sids, int64(*testSCCs[0].ServerID))
+ code, usrErr, sysErr := checkExistingServer(db.MustBegin().Tx, sids,
"user1")
+ if usrErr != nil {
+ t.Errorf("server not found, error:%v", usrErr)
+ }
+ if sysErr != nil {
+ t.Errorf("unable to check if server exists, error:%v", sysErr)
+ }
+ if code != http.StatusOK {
+ t.Errorf("existing server check failed, expected:%d, got:%d",
http.StatusOK, code)
+ }
+}
+
+func TestCheckServerType(t *testing.T) {
+ mockDB, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub
database connection", err)
+ }
+ defer mockDB.Close()
+
+ db := sqlx.NewDb(mockDB, "sqlmock")
+ defer db.Close()
+
+ testSCCs := getTestSSCs()
+ testSCCs[1].ServerID = util.Ptr(2)
+ testSCCs[1].Server = util.Ptr("foo")
+
+ mock.ExpectBegin()
+ rows := sqlmock.NewRows([]string{"array_agg"})
+ var sids []int64
+ for i, _ := range testSCCs {
+ sids = append(sids, int64(*testSCCs[i].ServerID))
+ }
+ rows.AddRow([]byte("{1,2}"))
+ mock.ExpectQuery("SELECT
array_agg").WithArgs(pq.Array(sids)).WillReturnRows(rows)
+ mock.ExpectCommit()
+
+ code, usrErr, sysErr := checkServerType(db.MustBegin().Tx, sids)
+ if usrErr != nil {
+ t.Errorf("mismatch in server type, error:%v", usrErr)
+ }
+ if sysErr != nil {
+ t.Errorf("unable to check if server type exists, error:%v",
sysErr)
+ }
+ if code != http.StatusOK {
+ t.Errorf("server type check failed, expected:%d, got:%d",
http.StatusOK, code)
+ }
+}
diff --git
a/traffic_ops/traffic_ops_golang/servercapability/servercapability.go
b/traffic_ops/traffic_ops_golang/servercapability/servercapability.go
index 8d9d60e442..2f92436805 100644
--- a/traffic_ops/traffic_ops_golang/servercapability/servercapability.go
+++ b/traffic_ops/traffic_ops_golang/servercapability/servercapability.go
@@ -46,8 +46,7 @@ type TOServerCapability struct {
func (v *TOServerCapability) SetLastUpdated(t tc.TimeNoMod) { v.LastUpdated =
&t }
func (v *TOServerCapability) NewReadObj() interface{} { return
&tc.ServerCapability{} }
func (v *TOServerCapability) InsertQuery() string {
- return `
-INSERT INTO server_capability (
+ return `INSERT INTO server_capability (
name
)
VALUES (
@@ -58,8 +57,7 @@ RETURNING last_updated
}
func (v *TOServerCapability) SelectQuery() string {
- return `
-SELECT
+ return `SELECT
name,
last_updated
FROM
@@ -68,8 +66,7 @@ FROM
}
func (v *TOServerCapability) updateQuery() string {
- return `
-UPDATE server_capability sc SET
+ return `UPDATE server_capability sc SET
name = $1
WHERE sc.name = $2
RETURNING sc.name, sc.last_updated
@@ -77,8 +74,8 @@ RETURNING sc.name, sc.last_updated
}
func (v *TOServerCapability) DeleteQuery() string {
- return `
-DELETE FROM server_capability WHERE name=:name
+ return `DELETE FROM server_capability
+WHERE name=:name
`
}
diff --git
a/traffic_ops/traffic_ops_golang/servercapability/servercapability_test.go
b/traffic_ops/traffic_ops_golang/servercapability/servercapability_test.go
new file mode 100644
index 0000000000..263bbf9e06
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/servercapability/servercapability_test.go
@@ -0,0 +1,146 @@
+package servercapability
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/apache/trafficcontrol/lib/go-tc"
+ "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+ "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/test"
+
+ "github.com/jmoiron/sqlx"
+ "gopkg.in/DATA-DOG/go-sqlmock.v1"
+)
+
+func getTestSCs() []tc.ServerCapability {
+ scs := []tc.ServerCapability{}
+ testSC := tc.ServerCapability{
+ Name: "test",
+ LastUpdated: &tc.TimeNoMod{Time: time.Now()},
+ }
+ scs = append(scs, testSC)
+
+ testSC1 := testSC
+ testSC1.Name = "blah"
+ scs = append(scs, testSC1)
+
+ return scs
+}
+
+func TestReadSCs(t *testing.T) {
+ mockDB, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub
database connection", err)
+ }
+ defer mockDB.Close()
+
+ db := sqlx.NewDb(mockDB, "sqlmock")
+ defer db.Close()
+
+ testSCs := getTestSCs()
+ rows := sqlmock.NewRows([]string{"name", "last_updated"})
+ for _, ts := range testSCs {
+ rows = rows.AddRow(
+ ts.Name,
+ ts.LastUpdated,
+ )
+ }
+ mock.ExpectBegin()
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+ mock.ExpectCommit()
+
+ reqInfo := api.APIInfo{Tx: db.MustBegin(), Params:
map[string]string{"name": "test"}}
+ obj := TOServerCapability{
+ APIInfoImpl: api.APIInfoImpl{ReqInfo: &reqInfo},
+ ServerCapability: tc.ServerCapability{},
+ }
+
+ scs, userErr, sysErr, _, _ := obj.Read(nil, false)
+ if userErr != nil || sysErr != nil {
+ t.Errorf("Read expected: no errors, actual: %v %v", userErr,
sysErr)
+ }
+
+ if len(scs) != 2 {
+ t.Errorf("Server Capability.Read expected: len(sc) == 1,
actual: %v", len(scs))
+ }
+}
+
+func TestInterfaces(t *testing.T) {
+ var i interface{}
+ i = &TOServerCapability{}
+
+ if _, ok := i.(api.Creator); !ok {
+ t.Errorf("ServerServerCapability must be Creator")
+ }
+ if _, ok := i.(api.Reader); !ok {
+ t.Errorf("ServerServerCapability must be Reader")
+ }
+ if _, ok := i.(api.Deleter); !ok {
+ t.Errorf("ServerServerCapability must be Deleter")
+ }
+ if _, ok := i.(api.Identifier); !ok {
+ t.Errorf("ServerServerCapability must be Identifier")
+ }
+}
+
+func TestFuncs(t *testing.T) {
+ testTOSC := TOServerCapability{}
+ if strings.Index(testTOSC.SelectQuery(), "SELECT") != 0 {
+ t.Errorf("expected selectQuery to start with SELECT")
+ }
+ if strings.Index(testTOSC.InsertQuery(), "INSERT") != 0 {
+ t.Errorf("expected insertQuery to start with INSERT")
+ }
+ if strings.Index(testTOSC.updateQuery(), "UPDATE") != 0 {
+ t.Errorf("expected updateQuery to start with UPDATE")
+ }
+ if strings.Index(testTOSC.DeleteQuery(), "DELETE") != 0 {
+ t.Errorf("expected deleteQuery to start with DELETE")
+ }
+}
+
+func TestValidate(t *testing.T) {
+ var errs []error
+ // Negative test case
+ testSC := tc.ServerCapability{
+ Name: "",
+ }
+ testTOSC := TOServerCapability{}
+ testTOSC.ServerCapability = testSC
+ err, _ := testTOSC.Validate()
+ errs = test.SortErrors(test.SplitErrors(err))
+ if len(errs) < 0 {
+ t.Errorf(`expected errors: %v, got no errors`, errs)
+ }
+
+ // Positive test case
+ testSCs := getTestSCs()
+ for _, val := range testSCs {
+ testTOSC.ServerCapability = val
+ err, _ := testTOSC.Validate()
+ errs = test.SortErrors(test.SplitErrors(err))
+ }
+ if len(errs) > 0 {
+ t.Errorf(`expected no errors, got errors: %v`, errs)
+ }
+}