You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: binder_test.go
    path of file: ./repos/echo
    
    the code of the file until where you have to start completion: // SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: Â© 2015 LabStack LLC and Echo contributors

package echo

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/stretchr/testify/assert"
	"io"
	"math/big"
	"net/http"
	"net/http/httptest"
	"strconv"
	"strings"
	"testing"
	"time"
)

func createTestContext(URL string, body io.Reader, pathParams map[string]string) Context {
	e := New()
	req := httptest.NewRequest(http.MethodGet, URL, body)
	if body != nil {
		req.Header.Set(HeaderContentType, MIMEApplicationJSON)
	}
	rec := httptest.NewRecorder()
	c := e.NewContext(req, rec)

	if len(pathParams) > 0 {
		names := make([]string, 0)
		values := make([]string, 0)
		for name, value := range pathParams {
			names = append(names, name)
			values = append(values, value)
		}
		c.SetParamNames(names...)
		c.SetParamValues(values...)
	}

	return c
}

func TestBindingError_Error(t *testing.T) {
	err := NewBindingError("id", []string{"1", "nope"}, "bind failed", errors.New("internal error"))
	assert.EqualError(t, err, `code=400, message=bind failed, internal=internal error, field=id`)

	bErr := err.(*BindingError)
	assert.Equal(t, 400, bErr.Code)
	assert.Equal(t, "bind failed", bErr.Message)
	assert.Equal(t, errors.New("internal error"), bErr.Internal)

	assert.Equal(t, "id", bErr.Field)
	assert.Equal(t, []string{"1", "nope"}, bErr.Values)
}

func TestBindingError_ErrorJSON(t *testing.T) {
	err := NewBindingError("id", []string{"1", "nope"}, "bind failed", errors.New("internal error"))

	resp, _ := json.Marshal(err)

	assert.Equal(t, `{"field":"id","message":"bind failed"}`, string(resp))
}

func TestPathParamsBinder(t *testing.T) {
	c := createTestContext("/api/user/999", nil, map[string]string{
		"id":    "1",
		"nr":    "2",
		"slice": "3",
	})
	b := PathParamsBinder(c)

	id := int64(99)
	nr := int64(88)
	var slice = make([]int64, 0)
	var notExisting = make([]int64, 0)
	err := b.Int64("id", &id).
		Int64("nr", &nr).
		Int64s("slice", &slice).
		Int64s("not_existing", &notExisting).
		BindError()

	assert.NoError(t, err)
	assert.Equal(t, int64(1), id)
	assert.Equal(t, int64(2), nr)
	assert.Equal(t, []int64{3}, slice)      // binding params to slice does not make sense but it should not panic either
	assert.Equal(t, []int64{}, not
    
func TestValueBinder_UnixTimeMilli(t *testing.T) {
	exampleTime, _ := time.Parse(time.RFC3339Nano, "2022-03-13T15:13:30.140000000+00:00") // => 1647184410140
	var testCases = []struct {
		name            string
		givenFailFast   bool
		givenBindErrors []error
		whenURL         string
		whenMust        bool
		expectValue     time.Time
		expectError     string
	}{
		{
			name:        "ok, binds value, unix time in milliseconds",
			whenURL:     "/search?param=1647184410140&param=1647184410199",
			expectValue: exampleTime,
		},
		{
			name:        "ok, params values empty, value is not changed",
			whenURL:     "/search?nope=1",
			expectValue: time.Time{},
		},
		{
			name:          "nok, previous errors fail fast without binding value",
			givenFailFast: true,
			whenURL:       "/search?param=1&param=100",
			expectValue:   time.Time{},
			expectError:   "previous error",
		},
		{
			name:        "nok, conversion fails, value is not changed",
			whenURL:     "/search?param=nope&param=100",
			expectValue: time.Time{},
			expectError: "code=400, message=failed to bind field value to Time, internal=strconv.ParseInt: parsing \"nope\": invalid syntax, field=param",
		},
		{
			name:        "ok (must), binds value",
			whenMust:    true,
			whenURL:     "/search?param=1647184410140&param=1647184410199",
			expectValue: exampleTime,
		},
		{
			name:        "ok (must), params values empty, returns error, value is not changed",
			whenMust:    true,
			whenURL:     "/search?nope=1",
			expectValue: time.Time{},
			expectError: "code=400, message=required field value is empty, field=param",
		},
		{
			name:          "nok (must), previous errors fail fast without binding value",
			givenFailFast: true,
			whenMust:      true,
			whenURL:       "/search?param=1&param=100",
			expectValue:   time.Time{},
			expectError:   "previous error",
		},
		{
			name:        "nok (must), conversion fails, value is not changed",
			whenMust:    true,
			whenURL:     "/search?param=nope&param=100",
			expectValue: time.Time{},
			expectError: "code=400, message=failed to bind field value to Time, internal=strconv.ParseInt: parsing \"nope\": invalid syntax, field=param",
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			c := createTestContext(tc.whenURL, nil, nil)
			b := QueryParamsBinder(c).FailFast(tc.givenFailFast)
			if tc.givenFailFast {
				b.errors = []error{errors.New("previous error")}
			}

			dest := time.Time{}
			var err error
			if tc.whenMust {
				err = b.MustUnixTimeMilli("param", &dest).BindError()
			} else {
				err = b.UnixTimeMilli("param", &dest).BindError()
			}

			assert.Equal(t, tc.expectValue.UnixNano(), dest.UnixNano())
			assert.Equal(t, tc.expectValue.In(time.UTC), dest.In(time.UTC))
			if tc.expectError != "" {
				assert.EqualError(t, err, tc.expectError)
			} else {
				assert.NoError(t, err)
			}
		})
	}
}