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 47a9e37bbb Use Topology type parameter for Topology API TestCase
(#7116)
47a9e37bbb is described below
commit 47a9e37bbbc1f75dc4e7b9005b06bd18531e2a79
Author: Zach Hoffman <[email protected]>
AuthorDate: Fri Oct 7 21:03:48 2022 +0000
Use Topology type parameter for Topology API TestCase (#7116)
* API and struct-agnistic TestData and TestCase
* Use Topology type parameter for Topology API TestCase
* Use Topology type parameter for Topology API V3TestCase
* Remove unused TO client session type from type constraint
---
traffic_ops/testing/api/utils/utils.go | 33 +++
traffic_ops/testing/api/v3/topologies_test.go | 276 ++++++++++++------------
traffic_ops/testing/api/v4/topologies_test.go | 300 +++++++++++++-------------
traffic_ops/testing/api/v5/topologies_test.go | 300 +++++++++++++-------------
4 files changed, 459 insertions(+), 450 deletions(-)
diff --git a/traffic_ops/testing/api/utils/utils.go
b/traffic_ops/testing/api/utils/utils.go
index f08e9ce76b..6b72505675 100644
--- a/traffic_ops/testing/api/utils/utils.go
+++ b/traffic_ops/testing/api/utils/utils.go
@@ -116,6 +116,16 @@ type V3TestData struct {
Expectations []CkReqFunc
}
+// V3TestDataT represents the data needed for testing the v3 api endpoints.
+type V3TestDataT[B any] struct {
+ EndpointId func() int
+ ClientSession *v3client.Session
+ RequestParams url.Values
+ RequestHeaders http.Header
+ RequestBody B
+ Expectations []CkReqFunc
+}
+
// V4TestData represents the data needed for testing the v4 api endpoints.
type V4TestData struct {
EndpointId func() int
@@ -134,10 +144,31 @@ type V5TestData struct {
Expectations []CkReqFunc
}
+type clientSession interface {
+ v4client.Session | v5client.Session
+}
+
+type requestOpts interface {
+ v4client.RequestOptions | v5client.RequestOptions
+}
+
+// TestData represents the data needed for testing the api endpoints.
+type TestData[C clientSession, R requestOpts, B any] struct {
+ EndpointId func() int
+ ClientSession *C
+ RequestOpts R
+ RequestBody B
+ Expectations []CkReqFunc
+}
+
// V3TestCase is the type of the V3TestData struct.
// Uses nested map to represent the method being tested and the test's
description.
type V3TestCase map[string]map[string]V3TestData
+// V3TestCaseT is the type of the V3TestDataT struct.
+// Uses nested map to represent the method being tested and the test's
description.
+type V3TestCaseT[B any] map[string]map[string]V3TestDataT[B]
+
// V4TestCase is the type of the V4TestData struct.
// Uses nested map to represent the method being tested and the test's
description.
type V4TestCase map[string]map[string]V4TestData
@@ -147,6 +178,8 @@ type V4TestCase map[string]map[string]V4TestData
// Uses nested map to represent the method being tested and the test's
description.
type V5TestCase map[string]map[string]V5TestData
+type TestCase[C clientSession, R requestOpts, B any]
map[string]map[string]TestData[C, R, B]
+
// CkReqFunc defines the reusable signature for all other functions that
perform checks.
// Common parameters that are checked include the request's info, response,
alerts, and errors.
type CkReqFunc func(*testing.T, toclientlib.ReqInf, interface{}, tc.Alerts,
error)
diff --git a/traffic_ops/testing/api/v3/topologies_test.go
b/traffic_ops/testing/api/v3/topologies_test.go
index 5b56b4cdfe..667477940b 100644
--- a/traffic_ops/testing/api/v3/topologies_test.go
+++ b/traffic_ops/testing/api/v3/topologies_test.go
@@ -20,7 +20,6 @@ package v3
*/
import (
- "encoding/json"
"net/http"
"net/url"
"testing"
@@ -34,7 +33,7 @@ import (
func TestTopologies(t *testing.T) {
WithObjs(t, []TCObj{Tenants, Users, Types, CacheGroups, CDNs,
Parameters, Profiles, Statuses, Divisions, Regions, PhysLocations, Servers,
ServerCapabilities, ServerServerCapabilities, Topologies, ServiceCategories,
DeliveryServices, DeliveryServicesRequiredCapabilities,
DeliveryServiceServerAssignments}, func() {
- methodTests := utils.V3TestCase{
+ methodTests := utils.V3TestCaseT[tc.Topology]{
"GET": {
"OK when VALID REQUEST": {
ClientSession: TOSession,
@@ -44,48 +43,48 @@ func TestTopologies(t *testing.T) {
"POST": {
"OK when MISSING DESCRIPTION": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name":
"topology-missing-description",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name:
"topology-missing-description",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
},
"BAD REQUEST when EMPTY NODES": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "topology-no-nodes",
- "nodes":
[]map[string]interface{}{},
+ RequestBody: tc.Topology{
+ Name: "topology-no-nodes",
+ Nodes: []tc.TopologyNode{},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when NODE PARENT of ITSELF": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "self-parent",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{0}}},
+ RequestBody: tc.Topology{
+ Name: "self-parent",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{0}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when TOO MANY PARENTS": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "too-many-parents",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "too-many-parents",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"parentCachegroup",
- "parents":
[]int{},
+ Cachegroup:
"parentCachegroup",
+ Parents:
[]int{},
},
{
- "cachegroup":
"secondaryCachegroup",
- "parents":
[]int{},
+ Cachegroup:
"secondaryCachegroup",
+ Parents:
[]int{},
},
{
- "cachegroup":
"parentCachegroup2",
- "parents":
[]int{},
+ Cachegroup:
"parentCachegroup2",
+ Parents:
[]int{},
},
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{0, 1, 2},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{0, 1, 2},
},
},
},
@@ -93,16 +92,16 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when EDGE_LOC PARENTS MID_LOC": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "edge-parents-mid",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "edge-parents-mid",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"parentCachegroup",
- "parents":
[]int{1},
+ Cachegroup:
"parentCachegroup",
+ Parents:
[]int{1},
},
{
- "cachegroup":
"cachegroup2",
- "parents":
[]int{},
+ Cachegroup:
"cachegroup2",
+ Parents:
[]int{},
},
},
},
@@ -110,20 +109,20 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when CYCLICAL NODES": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "cyclical-nodes",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "cyclical-nodes",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{1, 2},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{1, 2},
},
{
- "cachegroup":
"parentCachegroup",
- "parents":
[]int{2},
+ Cachegroup:
"parentCachegroup",
+ Parents:
[]int{2},
},
{
- "cachegroup":
"secondaryCachegroup",
- "parents":
[]int{1},
+ Cachegroup:
"secondaryCachegroup",
+ Parents:
[]int{1},
},
},
},
@@ -131,20 +130,20 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when CYCLES ACROSS TOPOLOGIES": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "cyclical-nodes-tiered",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "cyclical-nodes-tiered",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"parentCachegroup",
- "parents":
[]int{1},
+ Cachegroup:
"parentCachegroup",
+ Parents:
[]int{1},
},
{
- "cachegroup":
"parentCachegroup2",
- "parents":
[]int{},
+ Cachegroup:
"parentCachegroup2",
+ Parents:
[]int{},
},
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{0},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{0},
},
},
},
@@ -152,16 +151,16 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when CYCLICAL NODES BUT EMPTY
CACHE GROUPS": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name":
"cyclical-nodes-nontopology",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name:
"cyclical-nodes-nontopology",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"edge-parent1",
- "parents":
[]int{1},
+ Cachegroup:
"edge-parent1",
+ Parents:
[]int{1},
},
{
- "cachegroup":
"has-edge-parent1",
- "parents":
[]int{},
+ Cachegroup:
"has-edge-parent1",
+ Parents:
[]int{},
},
},
},
@@ -169,56 +168,56 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when OUT-OF-BOUNDS PARENT INDEX": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "outofbounds",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{7}}},
+ RequestBody: tc.Topology{
+ Name: "outofbounds",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{7}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when CACHEGROUP DOESNT EXIST": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name":
"topology-nonexistent-cachegroup",
- "nodes":
[]map[string]interface{}{{"cachegroup": "doesntexist", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name:
"topology-nonexistent-cachegroup",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "doesntexist", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when MISSING NAME": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "description": "missing name",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Description: "missing name",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when ALREADY EXISTS": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "mso-topology",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "mso-topology",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when CACHEGROUP has NO SERVERS": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "topology-empty-cg",
- "nodes":
[]map[string]interface{}{{"cachegroup": "noServers", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "topology-empty-cg",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "noServers", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when DUPLICATE PARENTS": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name":
"topology-duplicate-parents",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name:
"topology-duplicate-parents",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"parentCachegroup",
- "parents":
[]int{},
+ Cachegroup:
"parentCachegroup",
+ Parents:
[]int{},
},
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{0, 0},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{0, 0},
},
},
},
@@ -226,16 +225,16 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when ORG_LOC is CHILD NODE": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "topology-orgloc-child",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "topology-orgloc-child",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{},
},
{
- "cachegroup":
"multiOriginCachegroup",
- "parents":
[]int{0},
+ Cachegroup:
"multiOriginCachegroup",
+ Parents:
[]int{0},
},
},
},
@@ -243,25 +242,25 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when LEAF NODE is a MID_LOC": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "topology-midloc-leaf",
- "nodes":
[]map[string]interface{}{{"cachegroup": "parentCachegroup", "parents":
[]int{}}},
+ RequestBody: tc.Topology{
+ Name: "topology-midloc-leaf",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "parentCachegroup", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"WARNING LEVEL ALERT when MID PARENTING EDGE": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name":
"topology-mid-parent",
- "description": "mid parent to
edge",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name:
"topology-mid-parent",
+ Description: "mid parent to
edge",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{1},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{1},
},
{
- "cachegroup":
"cachegroup2",
- "parents":
[]int{},
+ Cachegroup:
"cachegroup2",
+ Parents:
[]int{},
},
},
},
@@ -272,10 +271,10 @@ func TestTopologies(t *testing.T) {
"OK when VALID request": {
ClientSession: TOSession,
RequestParams: url.Values{"name":
{"top-with-no-mids"}},
- RequestBody: map[string]interface{}{
- "name":
"top-with-no-mids-updated",
- "description": "Updating
fields",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup2", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name:
"top-with-no-mids-updated",
+ Description: "Updating fields",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup2", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK),
validateTopologiesUpdateCreateFields(map[string]interface{}{"Name":
"top-with-no-mids-updated", "Description": "Updating fields"})),
@@ -283,61 +282,61 @@ func TestTopologies(t *testing.T) {
"BAD REQUEST when OUT-OF-BOUNDS PARENT INDEX": {
ClientSession: TOSession,
RequestParams: url.Values{"name":
{"another-topology"}},
- RequestBody: map[string]interface{}{
- "name":
"topology-invalid-parent",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{100}}},
+ RequestBody: tc.Topology{
+ Name:
"topology-invalid-parent",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{100}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when CACHEGROUP has NO SERVERS": {
ClientSession: TOSession,
RequestParams: url.Values{"name":
{"another-topology"}},
- RequestBody: map[string]interface{}{
- "name": "topology-empty-cg",
- "nodes":
[]map[string]interface{}{{"cachegroup": "noServers", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "topology-empty-cg",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "noServers", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when CACHEGROUP SERVERS DO NOT
HAVE REQUIRED CAPABILITIES": {
ClientSession: TOSession,
RequestParams: url.Values{"name":
{"top-for-ds-req"}},
- RequestBody: map[string]interface{}{
- "name": "top-for-ds-req",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "top-for-ds-req",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when NODE PARENT of ITSELF": {
ClientSession: TOSession,
RequestParams: url.Values{"name":
{"another-topology"}},
- RequestBody: map[string]interface{}{
- "name": "another-topology",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{0}}},
+ RequestBody: tc.Topology{
+ Name: "another-topology",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{0}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when CACHEGROUP HAS NO SERVERS IN
TOPOLOGY CDN": {
ClientSession: TOSession,
RequestParams: url.Values{"name":
{"top-used-by-cdn1-and-cdn2"}},
- RequestBody: map[string]interface{}{
- "name":
"top-used-by-cdn1-and-cdn2",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cdn1-only", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name:
"top-used-by-cdn1-and-cdn2",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cdn1-only", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when ORG_LOC is CHILD NODE": {
ClientSession: TOSession,
RequestParams: url.Values{"name":
{"another-topology"}},
- RequestBody: map[string]interface{}{
- "name": "topology-orgloc-child",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "topology-orgloc-child",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{},
},
{
- "cachegroup":
"multiOriginCachegroup",
- "parents":
[]int{0},
+ Cachegroup:
"multiOriginCachegroup",
+ Parents:
[]int{0},
},
},
},
@@ -346,26 +345,26 @@ func TestTopologies(t *testing.T) {
"BAD REQUEST when LEAF NODE is a MID_LOC": {
ClientSession: TOSession,
RequestParams: url.Values{"name":
{"another-topology"}},
- RequestBody: map[string]interface{}{
- "name":
"topology-child-midloc",
- "description": "child mid_loc",
- "nodes":
[]map[string]interface{}{{"cachegroup": "parentCachegroup", "parents":
[]int{}}},
+ RequestBody: tc.Topology{
+ Name:
"topology-child-midloc",
+ Description: "child mid_loc",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "parentCachegroup", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when DUPLICATE PARENTS": {
ClientSession: TOSession,
RequestParams: url.Values{"name":
{"another-topology"}},
- RequestBody: map[string]interface{}{
- "name": "topology-same-parents",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "topology-same-parents",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{},
},
{
- "cachegroup":
"cachegroup2",
- "parents":
[]int{0, 0},
+ Cachegroup:
"cachegroup2",
+ Parents:
[]int{0, 0},
},
},
},
@@ -374,9 +373,9 @@ func TestTopologies(t *testing.T) {
"BAD REQUEST when REMOVING ORG ASSIGNED DS": {
ClientSession: TOSession,
RequestParams: url.Values{"name":
{"mso-topology"}},
- RequestBody: map[string]interface{}{
- "name": "mso-topology",
- "nodes":
[]map[string]interface{}{{"cachegroup": "topology-edge-cg-01", "parents":
[]int{}}},
+ RequestBody: tc.Topology{
+ Name: "mso-topology",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "topology-edge-cg-01", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
@@ -386,14 +385,7 @@ func TestTopologies(t *testing.T) {
for method, testCases := range methodTests {
t.Run(method, func(t *testing.T) {
for name, testCase := range testCases {
- topology := tc.Topology{}
-
- if testCase.RequestBody != nil {
- dat, err :=
json.Marshal(testCase.RequestBody)
- assert.NoError(t, err, "Error
occurred when marshalling request body: %v", err)
- err = json.Unmarshal(dat,
&topology)
- assert.NoError(t, err, "Error
occurred when unmarshalling request body: %v", err)
- }
+ topology := testCase.RequestBody
switch method {
case "GET", "GET AFTER CHANGES":
diff --git a/traffic_ops/testing/api/v4/topologies_test.go
b/traffic_ops/testing/api/v4/topologies_test.go
index 9e8850beea..6ccd639e82 100644
--- a/traffic_ops/testing/api/v4/topologies_test.go
+++ b/traffic_ops/testing/api/v4/topologies_test.go
@@ -20,7 +20,6 @@ package v4
*/
import (
- "encoding/json"
"net/http"
"net/url"
"testing"
@@ -43,7 +42,7 @@ func TestTopologies(t *testing.T) {
currentTimeRFC := currentTime.Format(time.RFC1123)
tomorrow := currentTime.AddDate(0, 0, 1).Format(time.RFC1123)
- methodTests := utils.V4TestCase{
+ methodTests := utils.TestCase[client.Session,
client.RequestOptions, tc.Topology]{
"GET": {
"NOT MODIFIED when NO CHANGES made": {
ClientSession: TOSession,
@@ -68,48 +67,48 @@ func TestTopologies(t *testing.T) {
"POST": {
"OK when MISSING DESCRIPTION": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name":
"topology-missing-description",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name:
"topology-missing-description",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
},
"BAD REQUEST when EMPTY NODES": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "topology-no-nodes",
- "nodes":
[]map[string]interface{}{},
+ RequestBody: tc.Topology{
+ Name: "topology-no-nodes",
+ Nodes: []tc.TopologyNode{},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when NODE PARENT of ITSELF": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "self-parent",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{0}}},
+ RequestBody: tc.Topology{
+ Name: "self-parent",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{0}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when TOO MANY PARENTS": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "too-many-parents",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "too-many-parents",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"parentCachegroup",
- "parents":
[]int{},
+ Cachegroup:
"parentCachegroup",
+ Parents:
[]int{},
},
{
- "cachegroup":
"secondaryCachegroup",
- "parents":
[]int{},
+ Cachegroup:
"secondaryCachegroup",
+ Parents:
[]int{},
},
{
- "cachegroup":
"parentCachegroup2",
- "parents":
[]int{},
+ Cachegroup:
"parentCachegroup2",
+ Parents:
[]int{},
},
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{0, 1, 2},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{0, 1, 2},
},
},
},
@@ -117,16 +116,16 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when EDGE_LOC PARENTS MID_LOC": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "edge-parents-mid",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "edge-parents-mid",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"parentCachegroup",
- "parents":
[]int{1},
+ Cachegroup:
"parentCachegroup",
+ Parents:
[]int{1},
},
{
- "cachegroup":
"cachegroup2",
- "parents":
[]int{},
+ Cachegroup:
"cachegroup2",
+ Parents:
[]int{},
},
},
},
@@ -134,20 +133,20 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when CYCLICAL NODES": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "cyclical-nodes",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "cyclical-nodes",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{1, 2},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{1, 2},
},
{
- "cachegroup":
"parentCachegroup",
- "parents":
[]int{2},
+ Cachegroup:
"parentCachegroup",
+ Parents:
[]int{2},
},
{
- "cachegroup":
"secondaryCachegroup",
- "parents":
[]int{1},
+ Cachegroup:
"secondaryCachegroup",
+ Parents:
[]int{1},
},
},
},
@@ -155,20 +154,20 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when CYCLES ACROSS TOPOLOGIES": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "cyclical-nodes-tiered",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "cyclical-nodes-tiered",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"parentCachegroup",
- "parents":
[]int{1},
+ Cachegroup:
"parentCachegroup",
+ Parents:
[]int{1},
},
{
- "cachegroup":
"parentCachegroup2",
- "parents":
[]int{},
+ Cachegroup:
"parentCachegroup2",
+ Parents:
[]int{},
},
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{0},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{0},
},
},
},
@@ -176,16 +175,16 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when CYCLICAL NODES BUT EMPTY
CACHE GROUPS": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name":
"cyclical-nodes-nontopology",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name:
"cyclical-nodes-nontopology",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"edge-parent1",
- "parents":
[]int{1},
+ Cachegroup:
"edge-parent1",
+ Parents:
[]int{1},
},
{
- "cachegroup":
"has-edge-parent1",
- "parents":
[]int{},
+ Cachegroup:
"has-edge-parent1",
+ Parents:
[]int{},
},
},
},
@@ -193,56 +192,56 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when OUT-OF-BOUNDS PARENT INDEX": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "outofbounds",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{7}}},
+ RequestBody: tc.Topology{
+ Name: "outofbounds",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{7}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when CACHEGROUP DOESNT EXIST": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name":
"topology-nonexistent-cachegroup",
- "nodes":
[]map[string]interface{}{{"cachegroup": "doesntexist", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name:
"topology-nonexistent-cachegroup",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "doesntexist", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when MISSING NAME": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "description": "missing name",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Description: "missing name",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when ALREADY EXISTS": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "mso-topology",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "mso-topology",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when CACHEGROUP has NO SERVERS": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "topology-empty-cg",
- "nodes":
[]map[string]interface{}{{"cachegroup": "noServers", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "topology-empty-cg",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "noServers", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when DUPLICATE PARENTS": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name":
"topology-duplicate-parents",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name:
"topology-duplicate-parents",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"parentCachegroup",
- "parents":
[]int{},
+ Cachegroup:
"parentCachegroup",
+ Parents:
[]int{},
},
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{0, 0},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{0, 0},
},
},
},
@@ -250,16 +249,16 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when ORG_LOC is CHILD NODE": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "topology-orgloc-child",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "topology-orgloc-child",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{},
},
{
- "cachegroup":
"multiOriginCachegroup",
- "parents":
[]int{0},
+ Cachegroup:
"multiOriginCachegroup",
+ Parents:
[]int{0},
},
},
},
@@ -267,25 +266,25 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when LEAF NODE is a MID_LOC": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "topology-midloc-leaf",
- "nodes":
[]map[string]interface{}{{"cachegroup": "parentCachegroup", "parents":
[]int{}}},
+ RequestBody: tc.Topology{
+ Name: "topology-midloc-leaf",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "parentCachegroup", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"WARNING LEVEL ALERT when MID PARENTING EDGE": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name":
"topology-mid-parent",
- "description": "mid parent to
edge",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name:
"topology-mid-parent",
+ Description: "mid parent to
edge",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{1},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{1},
},
{
- "cachegroup":
"cachegroup2",
- "parents":
[]int{},
+ Cachegroup:
"cachegroup2",
+ Parents:
[]int{},
},
},
},
@@ -293,9 +292,9 @@ func TestTopologies(t *testing.T) {
},
"FORBIDDEN when READ-ONLY USER": {
ClientSession: readOnlyUserSession,
- RequestBody: map[string]interface{}{
- "name": "topology-ro",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "topology-ro",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusForbidden)),
},
@@ -304,10 +303,10 @@ func TestTopologies(t *testing.T) {
"OK when VALID request": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"top-with-no-mids"}}},
- RequestBody: map[string]interface{}{
- "name":
"top-with-no-mids-updated",
- "description": "Updating
fields",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup2", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name:
"top-with-no-mids-updated",
+ Description: "Updating fields",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup2", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK),
validateTopologiesUpdateCreateFields(map[string]interface{}{"Name":
"top-with-no-mids-updated", "Description": "Updating fields"})),
@@ -315,61 +314,61 @@ func TestTopologies(t *testing.T) {
"BAD REQUEST when OUT-OF-BOUNDS PARENT INDEX": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"another-topology"}}},
- RequestBody: map[string]interface{}{
- "name":
"topology-invalid-parent",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{100}}},
+ RequestBody: tc.Topology{
+ Name:
"topology-invalid-parent",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{100}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when CACHEGROUP has NO SERVERS": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"another-topology"}}},
- RequestBody: map[string]interface{}{
- "name": "topology-empty-cg",
- "nodes":
[]map[string]interface{}{{"cachegroup": "noServers", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "topology-empty-cg",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "noServers", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when CACHEGROUP SERVERS DO NOT
HAVE REQUIRED CAPABILITIES": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name": {"top-for-ds-req"}}},
- RequestBody: map[string]interface{}{
- "name": "top-for-ds-req",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "top-for-ds-req",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when NODE PARENT of ITSELF": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"another-topology"}}},
- RequestBody: map[string]interface{}{
- "name": "another-topology",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{0}}},
+ RequestBody: tc.Topology{
+ Name: "another-topology",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{0}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when CACHEGROUP HAS NO SERVERS IN
TOPOLOGY CDN": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"top-used-by-cdn1-and-cdn2"}}},
- RequestBody: map[string]interface{}{
- "name":
"top-used-by-cdn1-and-cdn2",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cdn1-only", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name:
"top-used-by-cdn1-and-cdn2",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cdn1-only", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when ORG_LOC is CHILD NODE": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"another-topology"}}},
- RequestBody: map[string]interface{}{
- "name": "topology-orgloc-child",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "topology-orgloc-child",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{},
},
{
- "cachegroup":
"multiOriginCachegroup",
- "parents":
[]int{0},
+ Cachegroup:
"multiOriginCachegroup",
+ Parents:
[]int{0},
},
},
},
@@ -378,26 +377,26 @@ func TestTopologies(t *testing.T) {
"BAD REQUEST when LEAF NODE is a MID_LOC": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"another-topology"}}},
- RequestBody: map[string]interface{}{
- "name":
"topology-child-midloc",
- "description": "child mid_loc",
- "nodes":
[]map[string]interface{}{{"cachegroup": "parentCachegroup", "parents":
[]int{}}},
+ RequestBody: tc.Topology{
+ Name:
"topology-child-midloc",
+ Description: "child mid_loc",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "parentCachegroup", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when DUPLICATE PARENTS": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"another-topology"}}},
- RequestBody: map[string]interface{}{
- "name": "topology-same-parents",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "topology-same-parents",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{},
},
{
- "cachegroup":
"cachegroup2",
- "parents":
[]int{0, 0},
+ Cachegroup:
"cachegroup2",
+ Parents:
[]int{0, 0},
},
},
},
@@ -406,18 +405,18 @@ func TestTopologies(t *testing.T) {
"BAD REQUEST when REMOVING ORG ASSIGNED DS": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name": {"mso-topology"}}},
- RequestBody: map[string]interface{}{
- "name": "mso-topology",
- "nodes":
[]map[string]interface{}{{"cachegroup": "topology-edge-cg-01", "parents":
[]int{}}},
+ RequestBody: tc.Topology{
+ Name: "mso-topology",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "topology-edge-cg-01", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"FORBIDDEN when READ-ONLY USER": {
ClientSession: readOnlyUserSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"another-topology"}}},
- RequestBody: map[string]interface{}{
- "name": "topology-ro",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "topology-ro",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusForbidden)),
},
@@ -427,9 +426,9 @@ func TestTopologies(t *testing.T) {
QueryParameters:
url.Values{"name": {"another-topology"}},
Header:
http.Header{rfc.IfUnmodifiedSince: {currentTimeRFC}},
},
- RequestBody: map[string]interface{}{
- "name": "another-topology",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "another-topology",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(),
utils.HasStatus(http.StatusPreconditionFailed)),
},
@@ -439,9 +438,9 @@ func TestTopologies(t *testing.T) {
QueryParameters:
url.Values{"name": {"another-topology"}},
Header:
http.Header{rfc.IfUnmodifiedSince: {currentTimeRFC}},
},
- RequestBody: map[string]interface{}{
- "name": "another-topology",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "another-topology",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(),
utils.HasStatus(http.StatusPreconditionFailed)),
},
@@ -468,14 +467,7 @@ func TestTopologies(t *testing.T) {
for method, testCases := range methodTests {
t.Run(method, func(t *testing.T) {
for name, testCase := range testCases {
- topology := tc.Topology{}
-
- if testCase.RequestBody != nil {
- dat, err :=
json.Marshal(testCase.RequestBody)
- assert.NoError(t, err, "Error
occurred when marshalling request body: %v", err)
- err = json.Unmarshal(dat,
&topology)
- assert.NoError(t, err, "Error
occurred when unmarshalling request body: %v", err)
- }
+ topology := testCase.RequestBody
switch method {
case "GET", "GET AFTER CHANGES":
diff --git a/traffic_ops/testing/api/v5/topologies_test.go
b/traffic_ops/testing/api/v5/topologies_test.go
index 40fc852d96..ca436999d4 100644
--- a/traffic_ops/testing/api/v5/topologies_test.go
+++ b/traffic_ops/testing/api/v5/topologies_test.go
@@ -20,7 +20,6 @@ package v5
*/
import (
- "encoding/json"
"net/http"
"net/url"
"testing"
@@ -43,7 +42,7 @@ func TestTopologies(t *testing.T) {
currentTimeRFC := currentTime.Format(time.RFC1123)
tomorrow := currentTime.AddDate(0, 0, 1).Format(time.RFC1123)
- methodTests := utils.V5TestCase{
+ methodTests := utils.TestCase[client.Session,
client.RequestOptions, tc.Topology]{
"GET": {
"NOT MODIFIED when NO CHANGES made": {
ClientSession: TOSession,
@@ -68,48 +67,48 @@ func TestTopologies(t *testing.T) {
"POST": {
"OK when MISSING DESCRIPTION": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name":
"topology-missing-description",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name:
"topology-missing-description",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
},
"BAD REQUEST when EMPTY NODES": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "topology-no-nodes",
- "nodes":
[]map[string]interface{}{},
+ RequestBody: tc.Topology{
+ Name: "topology-no-nodes",
+ Nodes: []tc.TopologyNode{},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when NODE PARENT of ITSELF": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "self-parent",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{0}}},
+ RequestBody: tc.Topology{
+ Name: "self-parent",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{0}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when TOO MANY PARENTS": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "too-many-parents",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "too-many-parents",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"parentCachegroup",
- "parents":
[]int{},
+ Cachegroup:
"parentCachegroup",
+ Parents:
[]int{},
},
{
- "cachegroup":
"secondaryCachegroup",
- "parents":
[]int{},
+ Cachegroup:
"secondaryCachegroup",
+ Parents:
[]int{},
},
{
- "cachegroup":
"parentCachegroup2",
- "parents":
[]int{},
+ Cachegroup:
"parentCachegroup2",
+ Parents:
[]int{},
},
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{0, 1, 2},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{0, 1, 2},
},
},
},
@@ -117,16 +116,16 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when EDGE_LOC PARENTS MID_LOC": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "edge-parents-mid",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "edge-parents-mid",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"parentCachegroup",
- "parents":
[]int{1},
+ Cachegroup:
"parentCachegroup",
+ Parents:
[]int{1},
},
{
- "cachegroup":
"cachegroup2",
- "parents":
[]int{},
+ Cachegroup:
"cachegroup2",
+ Parents:
[]int{},
},
},
},
@@ -134,20 +133,20 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when CYCLICAL NODES": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "cyclical-nodes",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "cyclical-nodes",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{1, 2},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{1, 2},
},
{
- "cachegroup":
"parentCachegroup",
- "parents":
[]int{2},
+ Cachegroup:
"parentCachegroup",
+ Parents:
[]int{2},
},
{
- "cachegroup":
"secondaryCachegroup",
- "parents":
[]int{1},
+ Cachegroup:
"secondaryCachegroup",
+ Parents:
[]int{1},
},
},
},
@@ -155,20 +154,20 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when CYCLES ACROSS TOPOLOGIES": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "cyclical-nodes-tiered",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "cyclical-nodes-tiered",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"parentCachegroup",
- "parents":
[]int{1},
+ Cachegroup:
"parentCachegroup",
+ Parents:
[]int{1},
},
{
- "cachegroup":
"parentCachegroup2",
- "parents":
[]int{},
+ Cachegroup:
"parentCachegroup2",
+ Parents:
[]int{},
},
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{0},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{0},
},
},
},
@@ -176,16 +175,16 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when CYCLICAL NODES BUT EMPTY
CACHE GROUPS": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name":
"cyclical-nodes-nontopology",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name:
"cyclical-nodes-nontopology",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"edge-parent1",
- "parents":
[]int{1},
+ Cachegroup:
"edge-parent1",
+ Parents:
[]int{1},
},
{
- "cachegroup":
"has-edge-parent1",
- "parents":
[]int{},
+ Cachegroup:
"has-edge-parent1",
+ Parents:
[]int{},
},
},
},
@@ -193,56 +192,56 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when OUT-OF-BOUNDS PARENT INDEX": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "outofbounds",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{7}}},
+ RequestBody: tc.Topology{
+ Name: "outofbounds",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{7}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when CACHEGROUP DOESNT EXIST": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name":
"topology-nonexistent-cachegroup",
- "nodes":
[]map[string]interface{}{{"cachegroup": "doesntexist", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name:
"topology-nonexistent-cachegroup",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "doesntexist", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when MISSING NAME": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "description": "missing name",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Description: "missing name",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when ALREADY EXISTS": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "mso-topology",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "mso-topology",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when CACHEGROUP has NO SERVERS": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "topology-empty-cg",
- "nodes":
[]map[string]interface{}{{"cachegroup": "noServers", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "topology-empty-cg",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "noServers", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when DUPLICATE PARENTS": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name":
"topology-duplicate-parents",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name:
"topology-duplicate-parents",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"parentCachegroup",
- "parents":
[]int{},
+ Cachegroup:
"parentCachegroup",
+ Parents:
[]int{},
},
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{0, 0},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{0, 0},
},
},
},
@@ -250,16 +249,16 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when ORG_LOC is CHILD NODE": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "topology-orgloc-child",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "topology-orgloc-child",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{},
},
{
- "cachegroup":
"multiOriginCachegroup",
- "parents":
[]int{0},
+ Cachegroup:
"multiOriginCachegroup",
+ Parents:
[]int{0},
},
},
},
@@ -267,25 +266,25 @@ func TestTopologies(t *testing.T) {
},
"BAD REQUEST when LEAF NODE is a MID_LOC": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name": "topology-midloc-leaf",
- "nodes":
[]map[string]interface{}{{"cachegroup": "parentCachegroup", "parents":
[]int{}}},
+ RequestBody: tc.Topology{
+ Name: "topology-midloc-leaf",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "parentCachegroup", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"WARNING LEVEL ALERT when MID PARENTING EDGE": {
ClientSession: TOSession,
- RequestBody: map[string]interface{}{
- "name":
"topology-mid-parent",
- "description": "mid parent to
edge",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name:
"topology-mid-parent",
+ Description: "mid parent to
edge",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{1},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{1},
},
{
- "cachegroup":
"cachegroup2",
- "parents":
[]int{},
+ Cachegroup:
"cachegroup2",
+ Parents:
[]int{},
},
},
},
@@ -293,9 +292,9 @@ func TestTopologies(t *testing.T) {
},
"FORBIDDEN when READ-ONLY USER": {
ClientSession: readOnlyUserSession,
- RequestBody: map[string]interface{}{
- "name": "topology-ro",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "topology-ro",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusForbidden)),
},
@@ -304,10 +303,10 @@ func TestTopologies(t *testing.T) {
"OK when VALID request": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"top-with-no-mids"}}},
- RequestBody: map[string]interface{}{
- "name":
"top-with-no-mids-updated",
- "description": "Updating
fields",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup2", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name:
"top-with-no-mids-updated",
+ Description: "Updating fields",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup2", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK),
validateTopologiesUpdateCreateFields(map[string]interface{}{"Name":
"top-with-no-mids-updated", "Description": "Updating fields"})),
@@ -315,61 +314,61 @@ func TestTopologies(t *testing.T) {
"BAD REQUEST when OUT-OF-BOUNDS PARENT INDEX": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"another-topology"}}},
- RequestBody: map[string]interface{}{
- "name":
"topology-invalid-parent",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{100}}},
+ RequestBody: tc.Topology{
+ Name:
"topology-invalid-parent",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{100}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when CACHEGROUP has NO SERVERS": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"another-topology"}}},
- RequestBody: map[string]interface{}{
- "name": "topology-empty-cg",
- "nodes":
[]map[string]interface{}{{"cachegroup": "noServers", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "topology-empty-cg",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "noServers", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when CACHEGROUP SERVERS DO NOT
HAVE REQUIRED CAPABILITIES": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name": {"top-for-ds-req"}}},
- RequestBody: map[string]interface{}{
- "name": "top-for-ds-req",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "top-for-ds-req",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when NODE PARENT of ITSELF": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"another-topology"}}},
- RequestBody: map[string]interface{}{
- "name": "another-topology",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{0}}},
+ RequestBody: tc.Topology{
+ Name: "another-topology",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{0}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when CACHEGROUP HAS NO SERVERS IN
TOPOLOGY CDN": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"top-used-by-cdn1-and-cdn2"}}},
- RequestBody: map[string]interface{}{
- "name":
"top-used-by-cdn1-and-cdn2",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cdn1-only", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name:
"top-used-by-cdn1-and-cdn2",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cdn1-only", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when ORG_LOC is CHILD NODE": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"another-topology"}}},
- RequestBody: map[string]interface{}{
- "name": "topology-orgloc-child",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "topology-orgloc-child",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{},
},
{
- "cachegroup":
"multiOriginCachegroup",
- "parents":
[]int{0},
+ Cachegroup:
"multiOriginCachegroup",
+ Parents:
[]int{0},
},
},
},
@@ -378,26 +377,26 @@ func TestTopologies(t *testing.T) {
"BAD REQUEST when LEAF NODE is a MID_LOC": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"another-topology"}}},
- RequestBody: map[string]interface{}{
- "name":
"topology-child-midloc",
- "description": "child mid_loc",
- "nodes":
[]map[string]interface{}{{"cachegroup": "parentCachegroup", "parents":
[]int{}}},
+ RequestBody: tc.Topology{
+ Name:
"topology-child-midloc",
+ Description: "child mid_loc",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "parentCachegroup", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when DUPLICATE PARENTS": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"another-topology"}}},
- RequestBody: map[string]interface{}{
- "name": "topology-same-parents",
- "nodes":
[]map[string]interface{}{
+ RequestBody: tc.Topology{
+ Name: "topology-same-parents",
+ Nodes: []tc.TopologyNode{
{
- "cachegroup":
"cachegroup1",
- "parents":
[]int{},
+ Cachegroup:
"cachegroup1",
+ Parents:
[]int{},
},
{
- "cachegroup":
"cachegroup2",
- "parents":
[]int{0, 0},
+ Cachegroup:
"cachegroup2",
+ Parents:
[]int{0, 0},
},
},
},
@@ -406,18 +405,18 @@ func TestTopologies(t *testing.T) {
"BAD REQUEST when REMOVING ORG ASSIGNED DS": {
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name": {"mso-topology"}}},
- RequestBody: map[string]interface{}{
- "name": "mso-topology",
- "nodes":
[]map[string]interface{}{{"cachegroup": "topology-edge-cg-01", "parents":
[]int{}}},
+ RequestBody: tc.Topology{
+ Name: "mso-topology",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "topology-edge-cg-01", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"FORBIDDEN when READ-ONLY USER": {
ClientSession: readOnlyUserSession,
RequestOpts:
client.RequestOptions{QueryParameters: url.Values{"name":
{"another-topology"}}},
- RequestBody: map[string]interface{}{
- "name": "topology-ro",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "topology-ro",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusForbidden)),
},
@@ -427,9 +426,9 @@ func TestTopologies(t *testing.T) {
QueryParameters:
url.Values{"name": {"another-topology"}},
Header:
http.Header{rfc.IfUnmodifiedSince: {currentTimeRFC}},
},
- RequestBody: map[string]interface{}{
- "name": "another-topology",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "another-topology",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(),
utils.HasStatus(http.StatusPreconditionFailed)),
},
@@ -439,9 +438,9 @@ func TestTopologies(t *testing.T) {
QueryParameters:
url.Values{"name": {"another-topology"}},
Header:
http.Header{rfc.IfUnmodifiedSince: {currentTimeRFC}},
},
- RequestBody: map[string]interface{}{
- "name": "another-topology",
- "nodes":
[]map[string]interface{}{{"cachegroup": "cachegroup1", "parents": []int{}}},
+ RequestBody: tc.Topology{
+ Name: "another-topology",
+ Nodes:
[]tc.TopologyNode{{Cachegroup: "cachegroup1", Parents: []int{}}},
},
Expectations:
utils.CkRequest(utils.HasError(),
utils.HasStatus(http.StatusPreconditionFailed)),
},
@@ -468,14 +467,7 @@ func TestTopologies(t *testing.T) {
for method, testCases := range methodTests {
t.Run(method, func(t *testing.T) {
for name, testCase := range testCases {
- topology := tc.Topology{}
-
- if testCase.RequestBody != nil {
- dat, err :=
json.Marshal(testCase.RequestBody)
- assert.NoError(t, err, "Error
occurred when marshalling request body: %v", err)
- err = json.Unmarshal(dat,
&topology)
- assert.NoError(t, err, "Error
occurred when unmarshalling request body: %v", err)
- }
+ topology := testCase.RequestBody
switch method {
case "GET", "GET AFTER CHANGES":
