2015-01-15 03:29:13 +00:00
/ *
2015-05-01 16:19:44 +00:00
Copyright 2014 The Kubernetes Authors All rights reserved .
2015-01-15 03:29:13 +00:00
Licensed 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 .
* /
2015-02-05 00:14:48 +00:00
package util
2015-01-15 03:29:13 +00:00
import (
2015-06-30 02:30:14 +00:00
"fmt"
2015-03-07 10:00:45 +00:00
"io/ioutil"
"net/http"
"net/http/httptest"
2015-01-15 03:29:13 +00:00
"reflect"
2015-07-15 12:10:47 +00:00
"strings"
2015-03-07 10:00:45 +00:00
"syscall"
2015-01-15 03:29:13 +00:00
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
2015-06-03 16:13:01 +00:00
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
2015-06-30 02:30:14 +00:00
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
2015-01-15 03:29:13 +00:00
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
2015-06-03 16:13:01 +00:00
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/fielderrors"
2015-01-15 03:29:13 +00:00
)
func TestMerge ( t * testing . T ) {
tests := [ ] struct {
obj runtime . Object
fragment string
expected runtime . Object
expectErr bool
2015-01-31 18:59:08 +00:00
kind string
2015-01-15 03:29:13 +00:00
} {
{
2015-01-31 18:59:08 +00:00
kind : "Pod" ,
2015-01-15 03:29:13 +00:00
obj : & api . Pod {
ObjectMeta : api . ObjectMeta {
Name : "foo" ,
} ,
} ,
2015-06-30 02:30:14 +00:00
fragment : fmt . Sprintf ( ` { "apiVersion": "%s" } ` , testapi . Version ( ) ) ,
2015-01-15 03:29:13 +00:00
expected : & api . Pod {
ObjectMeta : api . ObjectMeta {
Name : "foo" ,
} ,
2015-01-26 17:52:50 +00:00
Spec : api . PodSpec {
2015-06-02 21:40:05 +00:00
RestartPolicy : api . RestartPolicyAlways ,
DNSPolicy : api . DNSClusterFirst ,
2015-01-26 17:52:50 +00:00
} ,
2015-01-15 03:29:13 +00:00
} ,
} ,
2015-05-29 00:25:44 +00:00
/ * TODO : uncomment this test once Merge is updated to use
2015-06-04 17:35:10 +00:00
strategic - merge - patch . See # 8449.
2015-05-29 00:25:44 +00:00
{
kind : "Pod" ,
obj : & api . Pod {
ObjectMeta : api . ObjectMeta {
Name : "foo" ,
} ,
Spec : api . PodSpec {
Containers : [ ] api . Container {
api . Container {
Name : "c1" ,
Image : "red-image" ,
} ,
api . Container {
Name : "c2" ,
Image : "blue-image" ,
} ,
} ,
} ,
} ,
2015-06-30 02:30:14 +00:00
fragment : fmt . Sprintf ( ` { "apiVersion": "%s", "spec": { "containers": [ { "name": "c1", "image": "green-image" } ] } } ` , testapi . Version ( ) ) ,
2015-05-29 00:25:44 +00:00
expected : & api . Pod {
ObjectMeta : api . ObjectMeta {
Name : "foo" ,
} ,
Spec : api . PodSpec {
Containers : [ ] api . Container {
api . Container {
Name : "c1" ,
Image : "green-image" ,
} ,
api . Container {
Name : "c2" ,
Image : "blue-image" ,
} ,
} ,
} ,
} ,
} , * /
2015-01-15 03:29:13 +00:00
{
2015-01-31 18:59:08 +00:00
kind : "Pod" ,
2015-01-15 03:29:13 +00:00
obj : & api . Pod {
ObjectMeta : api . ObjectMeta {
Name : "foo" ,
} ,
} ,
2015-06-30 02:30:14 +00:00
fragment : fmt . Sprintf ( ` { "apiVersion": "%s", "spec": { "volumes": [ { "name": "v1"}, { "name": "v2"} ] } } ` , testapi . Version ( ) ) ,
2015-01-15 03:29:13 +00:00
expected : & api . Pod {
ObjectMeta : api . ObjectMeta {
Name : "foo" ,
} ,
Spec : api . PodSpec {
Volumes : [ ] api . Volume {
{
2015-03-03 22:48:55 +00:00
Name : "v1" ,
VolumeSource : api . VolumeSource { EmptyDir : & api . EmptyDirVolumeSource { } } ,
2015-01-15 03:29:13 +00:00
} ,
{
2015-03-03 22:48:55 +00:00
Name : "v2" ,
VolumeSource : api . VolumeSource { EmptyDir : & api . EmptyDirVolumeSource { } } ,
2015-01-15 03:29:13 +00:00
} ,
} ,
2015-06-02 21:40:05 +00:00
RestartPolicy : api . RestartPolicyAlways ,
DNSPolicy : api . DNSClusterFirst ,
2015-01-15 03:29:13 +00:00
} ,
} ,
} ,
{
2015-01-31 18:59:08 +00:00
kind : "Pod" ,
2015-01-15 03:29:13 +00:00
obj : & api . Pod { } ,
fragment : "invalid json" ,
expected : & api . Pod { } ,
expectErr : true ,
} ,
2015-02-25 18:06:18 +00:00
{
kind : "Service" ,
obj : & api . Service { } ,
fragment : ` { "apiVersion": "badVersion" } ` ,
expectErr : true ,
} ,
2015-01-31 18:59:08 +00:00
{
kind : "Service" ,
obj : & api . Service {
2015-03-13 15:16:41 +00:00
Spec : api . ServiceSpec { } ,
2015-01-31 18:59:08 +00:00
} ,
2015-06-30 02:30:14 +00:00
fragment : fmt . Sprintf ( ` { "apiVersion": "%s", "spec": { "ports": [ { "port": 0 } ] } } ` , testapi . Version ( ) ) ,
2015-01-31 18:59:08 +00:00
expected : & api . Service {
Spec : api . ServiceSpec {
SessionAffinity : "None" ,
2015-05-22 21:49:26 +00:00
Type : api . ServiceTypeClusterIP ,
2015-05-22 15:20:27 +00:00
Ports : [ ] api . ServicePort {
{
Protocol : api . ProtocolTCP ,
Port : 0 ,
} ,
} ,
2015-01-31 18:59:08 +00:00
} ,
} ,
} ,
{
kind : "Service" ,
obj : & api . Service {
Spec : api . ServiceSpec {
Selector : map [ string ] string {
"version" : "v1" ,
} ,
} ,
} ,
2015-06-30 02:30:14 +00:00
fragment : fmt . Sprintf ( ` { "apiVersion": "%s", "spec": { "selector": { "version": "v2" } } } ` , testapi . Version ( ) ) ,
2015-06-03 18:54:50 +00:00
expected : & api . Service {
Spec : api . ServiceSpec {
SessionAffinity : "None" ,
Type : api . ServiceTypeClusterIP ,
Selector : map [ string ] string {
"version" : "v2" ,
} ,
} ,
} ,
} ,
2015-01-15 03:29:13 +00:00
}
2015-01-26 17:52:50 +00:00
for i , test := range tests {
2015-01-31 18:59:08 +00:00
out , err := Merge ( test . obj , test . fragment , test . kind )
2015-01-15 03:29:13 +00:00
if ! test . expectErr {
if err != nil {
2015-01-31 18:59:08 +00:00
t . Errorf ( "testcase[%d], unexpected error: %v" , i , err )
} else if ! reflect . DeepEqual ( out , test . expected ) {
t . Errorf ( "\n\ntestcase[%d]\nexpected:\n%+v\nsaw:\n%+v" , i , test . expected , out )
2015-01-15 03:29:13 +00:00
}
}
if test . expectErr && err == nil {
2015-01-31 18:59:08 +00:00
t . Errorf ( "testcase[%d], unexpected non-error" , i )
2015-01-15 03:29:13 +00:00
}
}
2015-03-07 10:00:45 +00:00
}
type fileHandler struct {
data [ ] byte
}
func ( f * fileHandler ) ServeHTTP ( res http . ResponseWriter , req * http . Request ) {
if req . URL . Path == "/error" {
res . WriteHeader ( http . StatusNotFound )
return
}
res . WriteHeader ( http . StatusOK )
res . Write ( f . data )
}
func TestReadConfigData ( t * testing . T ) {
httpData := [ ] byte { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }
server := httptest . NewServer ( & fileHandler { data : httpData } )
fileData := [ ] byte { 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 }
f , err := ioutil . TempFile ( "" , "config" )
if err != nil {
t . Errorf ( "unexpected error setting up config file" )
t . Fail ( )
}
defer syscall . Unlink ( f . Name ( ) )
ioutil . WriteFile ( f . Name ( ) , fileData , 0644 )
// TODO: test TLS here, requires making it possible to inject the HTTP client.
2015-01-15 03:29:13 +00:00
2015-03-07 10:00:45 +00:00
tests := [ ] struct {
config string
data [ ] byte
expectErr bool
} {
{
config : server . URL ,
data : httpData ,
} ,
{
config : server . URL + "/error" ,
expectErr : true ,
} ,
{
2015-03-09 21:31:39 +00:00
config : "http://some.non.existent.foobar" ,
2015-03-07 10:00:45 +00:00
expectErr : true ,
} ,
{
config : f . Name ( ) ,
data : fileData ,
} ,
{
config : "some-non-existent-file" ,
expectErr : true ,
} ,
{
config : "" ,
expectErr : true ,
} ,
}
for _ , test := range tests {
dataOut , err := ReadConfigData ( test . config )
if err != nil && ! test . expectErr {
t . Errorf ( "unexpected err: %v for %s" , err , test . config )
}
if err == nil && test . expectErr {
t . Errorf ( "unexpected non-error for %s" , test . config )
}
if ! test . expectErr && ! reflect . DeepEqual ( test . data , dataOut ) {
t . Errorf ( "unexpected data: %v, expected %v" , dataOut , test . data )
}
}
2015-01-15 03:29:13 +00:00
}
2015-06-03 16:13:01 +00:00
func TestCheckInvalidErr ( t * testing . T ) {
tests := [ ] struct {
err error
expected string
} {
{
errors . NewInvalid ( "Invalid1" , "invalidation" , fielderrors . ValidationErrorList { fielderrors . NewFieldInvalid ( "Cause" , "single" , "details" ) } ) ,
2015-07-31 23:43:39 +00:00
` Error from server: Invalid1 "invalidation" is invalid: Cause: invalid value 'single', Details: details ` ,
2015-06-03 16:13:01 +00:00
} ,
{
errors . NewInvalid ( "Invalid2" , "invalidation" , fielderrors . ValidationErrorList { fielderrors . NewFieldInvalid ( "Cause" , "multi1" , "details" ) , fielderrors . NewFieldInvalid ( "Cause" , "multi2" , "details" ) } ) ,
2015-07-31 23:43:39 +00:00
` Error from server: Invalid2 "invalidation" is invalid: [Cause: invalid value 'multi1', Details: details, Cause: invalid value 'multi2', Details: details] ` ,
2015-06-03 16:13:01 +00:00
} ,
{
errors . NewInvalid ( "Invalid3" , "invalidation" , fielderrors . ValidationErrorList { } ) ,
` Error from server: Invalid3 "invalidation" is invalid: <nil> ` ,
} ,
}
var errReturned string
errHandle := func ( err string ) {
errReturned = err
}
for _ , test := range tests {
checkErr ( test . err , errHandle )
if errReturned != test . expected {
t . Fatalf ( "Got: %s, expected: %s" , errReturned , test . expected )
}
}
}
2015-07-15 12:10:47 +00:00
func TestDumpReaderToFile ( t * testing . T ) {
testString := "TEST STRING"
tempFile , err := ioutil . TempFile ( "" , "hlpers_test_dump_" )
if err != nil {
t . Errorf ( "unexpected error setting up a temporary file %v" , err )
}
defer syscall . Unlink ( tempFile . Name ( ) )
defer tempFile . Close ( )
err = DumpReaderToFile ( strings . NewReader ( testString ) , tempFile . Name ( ) )
if err != nil {
t . Errorf ( "error in DumpReaderToFile: %v" , err )
}
data , err := ioutil . ReadFile ( tempFile . Name ( ) )
if err != nil {
t . Errorf ( "error when reading %s: %v" , tempFile , err )
}
stringData := string ( data )
if stringData != testString {
t . Fatalf ( "Wrong file content %s != %s" , testString , stringData )
}
}