You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by sr...@apache.org on 2023/03/14 20:49:32 UTC

[trafficcontrol] branch master updated: Improve unit test coverage for servers folder in Traffic Ops (#7396)

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 <22...@users.noreply.github.com>
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)
+	}
+}