imaginary/params_test.go

408 lines
9.6 KiB
Go

package main
import (
"math"
"net/url"
"testing"
"github.com/h2non/bimg"
)
const epsilon = 0.0001
func TestReadParams(t *testing.T) {
q := url.Values{}
q.Set("width", "100")
q.Add("height", "80")
q.Add("noreplicate", "1")
q.Add("opacity", "0.2")
q.Add("text", "hello")
q.Add("background", "255,10,20")
q.Add("interlace", "true")
params, err := buildParamsFromQuery(q)
if err != nil {
t.Errorf("Failed reading params, %s", err)
}
assert := params.Width == 100 &&
params.Height == 80 &&
params.NoReplicate == true &&
params.Opacity == 0.2 &&
params.Text == "hello" &&
params.Background[0] == 255 &&
params.Background[1] == 10 &&
params.Background[2] == 20 &&
params.Interlace == true
if assert == false {
t.Error("Invalid params")
}
}
func TestParseParam(t *testing.T) {
intCases := []struct {
value string
expected int
}{
{"1", 1},
{"0100", 100},
{"-100", 100},
{"99.02", 99},
{"99.9", 100},
}
for _, test := range intCases {
val, _ := parseInt(test.value)
if val != test.expected {
t.Errorf("Invalid param: %s != %d", test.value, test.expected)
}
}
floatCases := []struct {
value string
expected float64
}{
{"1.1", 1.1},
{"01.1", 1.1},
{"-1.10", 1.10},
{"99.999999", 99.999999},
}
for _, test := range floatCases {
val, _ := parseFloat(test.value)
if val != test.expected {
t.Errorf("Invalid param: %#v != %#v", val, test.expected)
}
}
boolCases := []struct {
value string
expected bool
}{
{"true", true},
{"false", false},
{"1", true},
{"1.1", false},
{"-1", false},
{"0", false},
{"0.0", false},
{"no", false},
{"yes", false},
}
for _, test := range boolCases {
val, _ := parseBool(test.value)
if val != test.expected {
t.Errorf("Invalid param: %#v != %#v", val, test.expected)
}
}
}
func TestParseColor(t *testing.T) {
cases := []struct {
value string
expected []uint8
}{
{"200,100,20", []uint8{200, 100, 20}},
{"0,280,200", []uint8{0, 255, 200}},
{" -1, 256 , 50", []uint8{0, 255, 50}},
{" a, 20 , &hel0", []uint8{0, 20, 0}},
{"", []uint8{}},
}
for _, color := range cases {
c := parseColor(color.value)
l := len(color.expected)
if len(c) != l {
t.Errorf("Invalid color length: %#v", c)
}
if l == 0 {
continue
}
assert := c[0] == color.expected[0] &&
c[1] == color.expected[1] &&
c[2] == color.expected[2]
if assert == false {
t.Errorf("Invalid color schema: %#v <> %#v", color.expected, c)
}
}
}
func TestParseExtend(t *testing.T) {
cases := []struct {
value string
expected bimg.Extend
}{
{"white", bimg.ExtendWhite},
{"black", bimg.ExtendBlack},
{"copy", bimg.ExtendCopy},
{"mirror", bimg.ExtendMirror},
{"lastpixel", bimg.ExtendLast},
{"background", bimg.ExtendBackground},
{" BACKGROUND ", bimg.ExtendBackground},
{"invalid", bimg.ExtendMirror},
{"", bimg.ExtendMirror},
}
for _, extend := range cases {
c := parseExtendMode(extend.value)
if c != extend.expected {
t.Errorf("Invalid extend value : %d != %d", c, extend.expected)
}
}
}
func TestGravity(t *testing.T) {
cases := []struct {
gravityValue string
smartCropValue bool
}{
{gravityValue: "foo", smartCropValue: false},
{gravityValue: "smart", smartCropValue: true},
}
for _, td := range cases {
io, _ := buildParamsFromQuery(url.Values{"gravity": []string{td.gravityValue}})
if (io.Gravity == bimg.GravitySmart) != td.smartCropValue {
t.Errorf("Expected %t to be %t, test data: %+v", io.Gravity == bimg.GravitySmart, td.smartCropValue, td)
}
}
}
func TestReadMapParams(t *testing.T) {
cases := []struct {
params map[string]interface{}
expected ImageOptions
}{
{
map[string]interface{}{
"width": 100,
"opacity": 0.1,
"type": "webp",
"embed": true,
"gravity": "west",
"color": "255,200,150",
},
ImageOptions{
Width: 100,
Opacity: 0.1,
Type: "webp",
Embed: true,
Gravity: bimg.GravityWest,
Color: []uint8{255, 200, 150},
},
},
}
for _, test := range cases {
opts, err := buildParamsFromOperation(PipelineOperation{Params: test.params})
if err != nil {
t.Errorf("Error reading parameters %s", err)
t.FailNow()
}
if opts.Width != test.expected.Width {
t.Errorf("Invalid width: %d != %d", opts.Width, test.expected.Width)
}
if opts.Opacity != test.expected.Opacity {
t.Errorf("Invalid opacity: %#v != %#v", opts.Opacity, test.expected.Opacity)
}
if opts.Type != test.expected.Type {
t.Errorf("Invalid type: %s != %s", opts.Type, test.expected.Type)
}
if opts.Embed != test.expected.Embed {
t.Errorf("Invalid embed: %#v != %#v", opts.Embed, test.expected.Embed)
}
if opts.Gravity != test.expected.Gravity {
t.Errorf("Invalid gravity: %#v != %#v", opts.Gravity, test.expected.Gravity)
}
if opts.Color[0] != test.expected.Color[0] || opts.Color[1] != test.expected.Color[1] || opts.Color[2] != test.expected.Color[2] {
t.Errorf("Invalid color: %#v != %#v", opts.Color, test.expected.Color)
}
}
}
func TestParseFunctions(t *testing.T) {
t.Run("parseBool", func(t *testing.T) {
if r, err := parseBool("true"); r != true {
t.Errorf("Expected string true to result a native type true %s", err)
}
if r, err := parseBool("false"); r != false {
t.Errorf("Expected string false to result a native type false %s", err)
}
// A special case that we support
if _, err := parseBool(""); err != nil {
t.Errorf("Expected blank values to default to false, it didn't! %s", err)
}
if r, err := parseBool("foo"); err == nil {
t.Errorf("Expected malformed values to result in an error, it didn't! %+v", r)
}
})
}
func TestBuildParamsFromOperation(t *testing.T) {
op := PipelineOperation{
Params: map[string]interface{}{
"width": 200,
"opacity": 2.2,
"force": true,
"stripmeta": false,
"type": "jpeg",
"background": "255,12,3",
},
}
options, err := buildParamsFromOperation(op)
if err != nil {
t.Errorf("Expected this to work! %s", err)
}
if input := op.Params["width"].(int); options.Width != 200 {
t.Errorf("Expected the Width to be coerced with the correct value of %d", input)
}
if input := op.Params["opacity"].(float64); math.Abs(input-float64(options.Opacity)) > epsilon {
t.Errorf("Expected the Opacity to be coerced with the correct value of %f", input)
}
if options.Force != true || options.StripMetadata != false {
t.Errorf("Expected boolean parameters to result in their respective value's\n%+v", options)
}
if input := op.Params["background"].(string); options.Background[0] != 255 {
t.Errorf("Expected color parameter to be coerced with the correct value of %s", input)
}
}
func TestCoerceTypeFns(t *testing.T) {
t.Run("coerceTypeInt", func(t *testing.T) {
cases := []struct {
Input interface{}
Expect int
Err error
}{
{Input: "200", Expect: 200},
{Input: int(200), Expect: 200},
{Input: float64(200), Expect: 200},
{Input: false, Expect: 0, Err: ErrUnsupportedValue},
}
for _, tc := range cases {
result, err := coerceTypeInt(tc.Input)
if err != nil && tc.Err == nil {
t.Errorf("Did not expect error %s\n%+v", err, tc)
t.FailNow()
}
if tc.Err != nil && tc.Err != err {
t.Errorf("Expected an error to be thrown\nExpected: %s\nReceived: %s", tc.Err, err)
t.FailNow()
}
if tc.Err == nil && result != tc.Expect {
t.Errorf("Expected proper coercion %s\n%+v\n%+v", err, result, tc)
}
}
})
t.Run("coerceTypeFloat", func(t *testing.T) {
cases := []struct {
Input interface{}
Expect float64
Err error
}{
{Input: "200", Expect: 200},
{Input: int(200), Expect: 200},
{Input: float64(200), Expect: 200},
{Input: false, Expect: 0, Err: ErrUnsupportedValue},
}
for _, tc := range cases {
result, err := coerceTypeFloat(tc.Input)
if err != nil && tc.Err == nil {
t.Errorf("Did not expect error %s\n%+v", err, tc)
t.FailNow()
}
if tc.Err != nil && tc.Err != err {
t.Errorf("Expected an error to be thrown\nExpected: %s\nReceived: %s", tc.Err, err)
t.FailNow()
}
if tc.Err == nil && math.Abs(result-tc.Expect) > epsilon {
t.Errorf("Expected proper coercion %s\n%+v\n%+v", err, result, tc)
}
}
})
t.Run("coerceTypeBool", func(t *testing.T) {
cases := []struct {
Input interface{}
Expect bool
Err error
}{
{Input: "true", Expect: true},
{Input: true, Expect: true},
{Input: "1", Expect: true},
{Input: "bubblegum", Expect: false, Err: ErrUnsupportedValue},
}
for _, tc := range cases {
result, err := coerceTypeBool(tc.Input)
if err != nil && tc.Err == nil {
t.Errorf("Did not expect error %s\n%+v", err, tc)
t.FailNow()
}
if tc.Err != nil && tc.Err != err {
t.Errorf("Expected an error to be thrown\nExpected: %s\nReceived: %s", tc.Err, err)
t.FailNow()
}
if tc.Err == nil && result != tc.Expect {
t.Errorf("Expected proper coercion %s\n%+v\n%+v", err, result, tc)
}
}
})
t.Run("coerceTypeString", func(t *testing.T) {
cases := []struct {
Input interface{}
Expect string
Err error
}{
{Input: "true", Expect: "true"},
{Input: false, Err: ErrUnsupportedValue},
{Input: 0.0, Err: ErrUnsupportedValue},
{Input: 0, Err: ErrUnsupportedValue},
}
for _, tc := range cases {
result, err := coerceTypeString(tc.Input)
if err != nil && tc.Err == nil {
t.Errorf("Did not expect error %s\n%+v", err, tc)
t.FailNow()
}
if tc.Err != nil && tc.Err != err {
t.Errorf("Expected an error to be thrown\nExpected: %s\nReceived: %s", tc.Err, err)
t.FailNow()
}
if tc.Err == nil && result != tc.Expect {
t.Errorf("Expected proper coercion %s\n%+v\n%+v", err, result, tc)
}
}
})
}