func TestCopySingleS3ObjectToLocalJSON(t *testing.T) {
	t.Parallel()
	bucket := s3BucketFromTestName(t)
	s3client, s5cmd, cleanup := setup(t)
	defer cleanup()
	createBucket(t, s3client, bucket)
	const (
		filename = "testfile1.txt"
		content  = "this is a file content"
	)
	putFile(t, s3client, bucket, filename, content)
	cmd := s5cmd("--json", "cp", "s3://"+bucket+"/"+filename, ".")
	result := icmd.RunCmd(cmd)
	result.Assert(t, icmd.Success)
	jsonText := `
		{
			"operation": "cp",
			"success": true,
			"source": "s3://%v/testfile1.txt",
			"destination": "testfile1.txt",
			"object": {
				"type": "file",
				"size": 22
			}
		}
	`
	assertLines(t, result.Stdout(), map[int]compareFunc{
		0: json(jsonText, bucket),
	}, jsonCheck(true))
	expected := fs.Expected(t, fs.WithFile(filename, content, fs.WithMode(0644)))
	assert.Assert(t, fs.Equal(cmd.Dir, expected))
	assert.Assert(t, ensureS3Object(s3client, bucket, filename, content))
}
--json cp s3://bucket/object .
package e2e
import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"testing"
	"time"
	"gotest.tools/v3/assert"
	"gotest.tools/v3/fs"
	"gotest.tools/v3/icmd"
)
func TestCopySingleS3ObjectToLocal(t *testing.T) {
	t.Parallel()
	const (
		bucket      = "bucket"
		fileContent = "this is a file content"
	)
	testcases := []struct {
		name           string
		src            string
		dst            string
		expected       fs.PathOp
		expectedOutput string
	}{
		{
			name:           "cp s3://bucket/object .",
			src:            "file1.txt",
			dst:            ".",
			expected:       fs.WithFile("file1.txt", fileContent, fs.WithMode(0644)),
			expectedOutput: "cp s3://bucket/file1.txt file1.txt",
		},
		{
			name:           "cp s3://bucket/object file",
			src:            "file1.txt",
			dst:            "file1.txt",
			expected:       fs.WithFile("file1.txt", fileContent, fs.WithMode(0644)),
			expectedOutput: "cp s3://bucket/file1.txt file1.txt",
		},
		{
			name:           "cp s3://bucket/object dir/",
			src:            "file1.txt",
			dst:            "dir/",
			expected:       fs.WithDir("dir", fs.WithFile("file1.txt", fileContent, fs.WithMode(0644))),
			expectedOutput: "cp s3://bucket/file1.txt dir/file1.txt",
		},
		{
			name:           "cp s3://bucket/object dir/file",
			src:            "file1.txt",
			dst:            "dir/file1.txt",
			expected:       fs.WithDir("dir", fs.WithFile("file1.txt", fileContent, fs.WithMode(0644))),
			expectedOutput: "cp s3://bucket/file1.txt dir/file1.txt",
		},
	}
	for _, tc := range testcases {
		tc := tc
		t.Run(tc.name, func(t *testing.T) {
			t.Parallel()
			s3client, s5cmd, cleanup := setup(t)
			defer cleanup()
			createBucket(t, s3client, bucket)
			putFile(t, s3client, bucket, tc.src, fileContent)
			src := fmt.Sprintf("s3://%v/%v", bucket, tc.src)
			cmd := s5cmd("cp", src, tc.dst)
			result := icmd.RunCmd(cmd)
			result.Assert(t, icmd.Success)
			assertLines(t, result.Stdout(), map[int]compareFunc{
				0: equals(tc.expectedOutput),
			})
			expected := fs.Expected(t, tc.expected)
			assert.Assert(t, fs.Equal(cmd.Dir, expected))
			assert.Assert(t, ensureS3Object(s3client, bucket, tc.src, fileContent))
		})
	}
}