blob: 5c387479da3ed9cf439a9b2c307f3bdcd9d78e1a [file] [log] [blame]
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 (
"context"
"net/http"
"reflect"
"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/auth"
"github.com/jmoiron/sqlx"
"github.com/lib/pq"
sqlmock "gopkg.in/DATA-DOG/go-sqlmock.v1"
)
func TestAssignDsesToServer(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()
newDses := []int{4, 5, 6}
pqNewDses := pq.Array(newDses)
mock.ExpectBegin()
mock.ExpectExec("DELETE").WithArgs(100).WillReturnResult(sqlmock.NewResult(1, 3))
mock.ExpectExec("INSERT").WithArgs(pqNewDses, 100).WillReturnResult(sqlmock.NewResult(1, 3))
//fetch remap config location
remapConfigLocation := "a/path/to/a/remap.config"
remapConfigRow := sqlmock.NewRows([]string{"value"})
remapConfigRow.AddRow(remapConfigLocation + "/") // verifies we strip off the trailing slash
mock.ExpectQuery("SELECT").WillReturnRows(remapConfigRow) //remap.config
//select xmlids and edge_header_rewrite, regex_remap, and cache_url for each ds
dsFieldRows := sqlmock.NewRows([]string{"xml_id", "edge_header_rewrite", "regex_remap", "cacheurl"})
dsFieldRows.AddRow("ds1", nil, "regexRemapPlaceholder", "cacheurlPlaceholder")
dsFieldRows.AddRow("ds2", "edgeHeaderRewritePlaceholder2", "regexRemapPlaceholder", "cacheurlPlaceholder")
dsFieldRows.AddRow("ds3", "", nil, "cacheurlPlaceholder")
mock.ExpectQuery("SELECT").WithArgs(pqNewDses).WillReturnRows(dsFieldRows)
//prepare the insert and delete parameter slices as they should be constructed in the function
headerRewritePrefix := "hdr_rw_"
regexRemapPrefix := "regex_remap_"
cacheurlPrefix := "cacheurl_"
configPostfix := ".config"
insert := []string{regexRemapPrefix + "ds1" + configPostfix, cacheurlPrefix + "ds1" + configPostfix, headerRewritePrefix + "ds2" + configPostfix, regexRemapPrefix + "ds2" + configPostfix, cacheurlPrefix + "ds2" + configPostfix, cacheurlPrefix + "ds3" + configPostfix}
delete := []string{headerRewritePrefix + "ds1" + configPostfix, headerRewritePrefix + "ds3" + configPostfix, regexRemapPrefix + "ds3" + configPostfix}
fileNamesPq := pq.Array(insert)
//insert the parameters
mock.ExpectExec("INSERT").WithArgs(fileNamesPq, "location", remapConfigLocation).WillReturnResult(sqlmock.NewResult(1, 6))
//select out the parameterIDs we just inserted
parameterIDRows := sqlmock.NewRows([]string{"id"})
parameterIDs := []int64{1, 2, 3, 4, 5, 6}
for _, i := range parameterIDs {
parameterIDRows.AddRow(i)
}
mock.ExpectQuery("SELECT").WithArgs(fileNamesPq).WillReturnRows(parameterIDRows)
//insert those ids as profile_parameters
mock.ExpectExec("INSERT").WithArgs(pqNewDses, pq.Array(parameterIDs)).WillReturnResult(sqlmock.NewResult(6, 6))
//delete the parameters in the delete list
mock.ExpectExec("DELETE").WithArgs(pq.Array(delete)).WillReturnResult(sqlmock.NewResult(1, 3))
mock.ExpectCommit()
dbCtx, cancelTx := context.WithTimeout(context.TODO(), 10*time.Second)
defer cancelTx()
tx, err := db.BeginTx(dbCtx, nil)
if err != nil {
t.Fatalf("creating transaction: %v", err)
}
defer tx.Commit()
result, err := assignDeliveryServicesToServer(100, newDses, true, tx)
if err != nil {
t.Errorf("error assigning deliveryservice: %v", err)
}
if !reflect.DeepEqual(result, newDses) {
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)
}
}
func TestValidateDSCapabilities(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()
mock.ExpectBegin()
rows := sqlmock.NewRows([]string{"server_capability"})
rows.AddRow([]byte("{eas}"))
mock.ExpectQuery("SELECT").WithArgs("eas").WillReturnRows(rows)
dsIDs := []int64{1}
rows1 := sqlmock.NewRows([]string{"id", "required_capabilities"})
rows1.AddRow(1, []byte("{eas}"))
mock.ExpectQuery("SELECT ").WithArgs(pq.Array(dsIDs)).WillReturnRows(rows1)
mock.ExpectCommit()
usrErr, sysErr, code := ValidateDSCapabilities([]int{1}, "eas", db.MustBegin().Tx)
if usrErr != nil {
t.Errorf("unable to validate DS capability, most likely cache doesn't have the DS capability, error: %v", usrErr)
}
if sysErr != nil {
t.Errorf("unable to validate DS Capability, system error: %v", sysErr)
}
if code != http.StatusOK {
t.Errorf("DS validation failed with status code:%d", code)
}
}