321 lines
6.6 KiB
Go
321 lines
6.6 KiB
Go
|
package ecs
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"errors"
|
||
|
"io"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
"os"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/docker/docker/api/types/container"
|
||
|
"github.com/stretchr/testify/require"
|
||
|
)
|
||
|
|
||
|
type pollMock struct {
|
||
|
getTask func() (*ecsTask, error)
|
||
|
getStats func() (map[string]*container.StatsResponse, error)
|
||
|
}
|
||
|
|
||
|
func (p *pollMock) task() (*ecsTask, error) {
|
||
|
return p.getTask()
|
||
|
}
|
||
|
|
||
|
func (p *pollMock) containerStats() (map[string]*container.StatsResponse, error) {
|
||
|
return p.getStats()
|
||
|
}
|
||
|
|
||
|
func TestEcsClient_PollSync(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
mock *pollMock
|
||
|
want *ecsTask
|
||
|
want1 map[string]*container.StatsResponse
|
||
|
wantErr bool
|
||
|
}{
|
||
|
{
|
||
|
name: "success",
|
||
|
mock: &pollMock{
|
||
|
getTask: func() (*ecsTask, error) {
|
||
|
return &validMeta, nil
|
||
|
},
|
||
|
getStats: func() (map[string]*container.StatsResponse, error) {
|
||
|
return validStats, nil
|
||
|
},
|
||
|
},
|
||
|
want: &validMeta,
|
||
|
want1: validStats,
|
||
|
},
|
||
|
{
|
||
|
name: "task err",
|
||
|
mock: &pollMock{
|
||
|
getTask: func() (*ecsTask, error) {
|
||
|
return nil, errors.New("err")
|
||
|
},
|
||
|
getStats: func() (map[string]*container.StatsResponse, error) {
|
||
|
return validStats, nil
|
||
|
},
|
||
|
},
|
||
|
wantErr: true,
|
||
|
},
|
||
|
{
|
||
|
name: "stats err",
|
||
|
mock: &pollMock{
|
||
|
getTask: func() (*ecsTask, error) {
|
||
|
return &validMeta, nil
|
||
|
},
|
||
|
getStats: func() (map[string]*container.StatsResponse, error) {
|
||
|
return nil, errors.New("err")
|
||
|
},
|
||
|
},
|
||
|
wantErr: true,
|
||
|
},
|
||
|
}
|
||
|
for _, tt := range tests {
|
||
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
got, got1, err := pollSync(tt.mock)
|
||
|
|
||
|
if (err != nil) != tt.wantErr {
|
||
|
t.Errorf("ecsClient.pollSync() error = %v, wantErr %v", err, tt.wantErr)
|
||
|
return
|
||
|
}
|
||
|
require.Equal(t, tt.want, got, "ecsClient.pollSync() got = %v, want %v", got, tt.want)
|
||
|
require.Equal(t, tt.want1, got1, "ecsClient.pollSync() got1 = %v, want %v", got1, tt.want1)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type mockDo struct {
|
||
|
do func() (*http.Response, error)
|
||
|
}
|
||
|
|
||
|
func (m mockDo) Do(*http.Request) (*http.Response, error) {
|
||
|
return m.do()
|
||
|
}
|
||
|
|
||
|
func TestEcsClient_Task(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
client httpClient
|
||
|
want *ecsTask
|
||
|
wantErr bool
|
||
|
}{
|
||
|
{
|
||
|
name: "happy",
|
||
|
client: mockDo{
|
||
|
do: func() (*http.Response, error) {
|
||
|
rc, err := os.Open("testdata/metadata.golden")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return &http.Response{
|
||
|
StatusCode: http.StatusOK,
|
||
|
Body: io.NopCloser(rc),
|
||
|
}, nil
|
||
|
},
|
||
|
},
|
||
|
want: &validMeta,
|
||
|
},
|
||
|
{
|
||
|
name: "do err",
|
||
|
client: mockDo{
|
||
|
do: func() (*http.Response, error) {
|
||
|
return nil, errors.New("err")
|
||
|
},
|
||
|
},
|
||
|
wantErr: true,
|
||
|
},
|
||
|
{
|
||
|
name: "malformed 500 resp",
|
||
|
client: mockDo{
|
||
|
do: func() (*http.Response, error) {
|
||
|
return &http.Response{
|
||
|
StatusCode: http.StatusInternalServerError,
|
||
|
Body: io.NopCloser(bytes.NewReader([]byte("foo"))),
|
||
|
}, nil
|
||
|
},
|
||
|
},
|
||
|
wantErr: true,
|
||
|
},
|
||
|
{
|
||
|
name: "malformed 200 resp",
|
||
|
client: mockDo{
|
||
|
do: func() (*http.Response, error) {
|
||
|
return &http.Response{
|
||
|
StatusCode: http.StatusOK,
|
||
|
Body: io.NopCloser(bytes.NewReader([]byte("foo"))),
|
||
|
}, nil
|
||
|
},
|
||
|
},
|
||
|
wantErr: true,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, tt := range tests {
|
||
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
c := &ecsClient{
|
||
|
client: tt.client,
|
||
|
taskURL: "abc",
|
||
|
}
|
||
|
got, err := c.task()
|
||
|
if (err != nil) != tt.wantErr {
|
||
|
t.Errorf("ecsClient.task() error = %v, wantErr %v", err, tt.wantErr)
|
||
|
return
|
||
|
}
|
||
|
require.Equal(t, tt.want, got, "ecsClient.task() = %v, want %v", got, tt.want)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestEcsClient_ContainerStats(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
client httpClient
|
||
|
want map[string]*container.StatsResponse
|
||
|
wantErr bool
|
||
|
}{
|
||
|
{
|
||
|
name: "happy",
|
||
|
client: mockDo{
|
||
|
do: func() (*http.Response, error) {
|
||
|
rc, err := os.Open("testdata/stats.golden")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return &http.Response{
|
||
|
StatusCode: http.StatusOK,
|
||
|
Body: io.NopCloser(rc),
|
||
|
}, nil
|
||
|
},
|
||
|
},
|
||
|
want: validStats,
|
||
|
},
|
||
|
{
|
||
|
name: "do err",
|
||
|
client: mockDo{
|
||
|
do: func() (*http.Response, error) {
|
||
|
return nil, errors.New("err")
|
||
|
},
|
||
|
},
|
||
|
want: nil,
|
||
|
wantErr: true,
|
||
|
},
|
||
|
{
|
||
|
name: "malformed 200 resp",
|
||
|
client: mockDo{
|
||
|
do: func() (*http.Response, error) {
|
||
|
return &http.Response{
|
||
|
StatusCode: http.StatusOK,
|
||
|
Body: io.NopCloser(bytes.NewReader([]byte("foo"))),
|
||
|
}, nil
|
||
|
},
|
||
|
},
|
||
|
want: nil,
|
||
|
wantErr: true,
|
||
|
},
|
||
|
{
|
||
|
name: "malformed 500 resp",
|
||
|
client: mockDo{
|
||
|
do: func() (*http.Response, error) {
|
||
|
return &http.Response{
|
||
|
StatusCode: http.StatusInternalServerError,
|
||
|
Body: io.NopCloser(bytes.NewReader([]byte("foo"))),
|
||
|
}, nil
|
||
|
},
|
||
|
},
|
||
|
want: nil,
|
||
|
wantErr: true,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, tt := range tests {
|
||
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
c := &ecsClient{
|
||
|
client: tt.client,
|
||
|
statsURL: "abc",
|
||
|
}
|
||
|
got, err := c.containerStats()
|
||
|
if (err != nil) != tt.wantErr {
|
||
|
t.Errorf("ecsClient.containerStats() error = %v, wantErr %v", err, tt.wantErr)
|
||
|
return
|
||
|
}
|
||
|
require.Equal(t, tt.want, got, "ecsClient.containerStats() = %v, want %v", got, tt.want)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestResolveTaskURL(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
base string
|
||
|
ver int
|
||
|
exp string
|
||
|
}{
|
||
|
{
|
||
|
name: "default v2 endpoint",
|
||
|
base: v2Endpoint,
|
||
|
ver: 2,
|
||
|
exp: "http://169.254.170.2/v2/metadata",
|
||
|
},
|
||
|
{
|
||
|
name: "custom v2 endpoint",
|
||
|
base: "http://192.168.0.1",
|
||
|
ver: 2,
|
||
|
exp: "http://192.168.0.1/v2/metadata",
|
||
|
},
|
||
|
{
|
||
|
name: "theoretical v3 endpoint",
|
||
|
base: "http://169.254.170.2/v3/metadata",
|
||
|
ver: 3,
|
||
|
exp: "http://169.254.170.2/v3/metadata/task",
|
||
|
},
|
||
|
}
|
||
|
for _, tt := range tests {
|
||
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
baseURL, err := url.Parse(tt.base)
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
act := resolveTaskURL(baseURL, tt.ver)
|
||
|
require.Equal(t, tt.exp, act)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestResolveStatsURL(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
base string
|
||
|
ver int
|
||
|
exp string
|
||
|
}{
|
||
|
{
|
||
|
name: "default v2 endpoint",
|
||
|
base: v2Endpoint,
|
||
|
ver: 2,
|
||
|
exp: "http://169.254.170.2/v2/stats",
|
||
|
},
|
||
|
{
|
||
|
name: "custom v2 endpoint",
|
||
|
base: "http://192.168.0.1",
|
||
|
ver: 2,
|
||
|
exp: "http://192.168.0.1/v2/stats",
|
||
|
},
|
||
|
{
|
||
|
name: "theoretical v3 endpoint",
|
||
|
base: "http://169.254.170.2/v3/metadata",
|
||
|
ver: 3,
|
||
|
exp: "http://169.254.170.2/v3/metadata/task/stats",
|
||
|
},
|
||
|
}
|
||
|
for _, tt := range tests {
|
||
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
baseURL, err := url.Parse(tt.base)
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
act := resolveStatsURL(baseURL, tt.ver)
|
||
|
require.Equal(t, tt.exp, act)
|
||
|
})
|
||
|
}
|
||
|
}
|