summaryrefslogtreecommitdiff
path: root/tests/bulk_upload_test.go
blob: c25f2de18d639895ffe80ecfdb327d53635deada (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// SPDX-FileCopyrightText: 2018 Stefan Majewsky <majewsky@gmx.net>
// SPDX-License-Identifier: Apache-2.0

package tests

import (
	"archive/tar"
	"bytes"
	"errors"
	"strings"
	"testing"

	"go.xyrillian.de/schwift/v2"
)

func TestBulkUploadSuccess(t *testing.T) {
	testWithContainer(t, func(c *schwift.Container) {
		obj1 := c.Object("file1")
		obj2 := c.Object("file2")

		archive := buildTarArchive(map[string][]byte{
			obj1.FullName(): []byte("hello"),
			obj2.FullName(): []byte("world"),
		})
		n, err := c.Account().BulkUpload(
			t.Context(),
			"", // upload path
			schwift.BulkUploadTar,
			bytes.NewReader(archive),
			nil,
		)
		expectInt(t, n, 2)
		expectSuccess(t, err)

		expectObjectExistence(t, obj1, true)
		expectObjectExistence(t, obj2, true)
		expectObjectContent(t, obj1, []byte("hello"))
		expectObjectContent(t, obj2, []byte("world"))
	})
}

func TestBulkUploadArchiveError(t *testing.T) {
	testWithContainer(t, func(c *schwift.Container) {
		n, err := c.Account().BulkUpload(
			t.Context(),
			c.Name(), // upload path
			schwift.BulkUploadTar,
			strings.NewReader("This is not the TAR archive you're looking for."),
			nil,
		)
		expectInt(t, n, 0)
		expectError(t, err, "400 Bad Request: Invalid Tar File: truncated header")
		bulkErr, _ := errors.AsType[schwift.BulkError](err)
		expectInt(t, bulkErr.StatusCode, 400)
		expectString(t, bulkErr.OverallError, "Invalid Tar File: truncated header")
		expectInt(t, len(bulkErr.ObjectErrors), 0)
	})
}

func TestBulkUploadObjectError(t *testing.T) {
	testWithContainer(t, func(c *schwift.Container) {
		obj1 := c.Object(buildInvalidObjectName())
		obj2 := c.Object("file2")
		expectObjectExistence(t, obj2, false)

		archive := buildTarArchive(map[string][]byte{
			obj1.Name(): []byte("hello"),
			obj2.Name(): []byte("world"),
		})
		n, err := c.Account().BulkUpload(
			t.Context(),
			c.Name(), // upload path
			schwift.BulkUploadTar,
			bytes.NewReader(archive),
			nil,
		)
		expectInt(t, n, 1)
		expectError(t, err, "400 Bad Request (+1 object errors)")
		bulkErr, _ := errors.AsType[schwift.BulkError](err)
		expectInt(t, len(bulkErr.ObjectErrors), 1)
		expectString(t, bulkErr.ObjectErrors[0].ContainerName, c.Name())
		expectInt(t, bulkErr.ObjectErrors[0].StatusCode, 400)
		// ^ We cannot match the ObjectName (or use expectError, for that matter)
		// here because Swift truncates the object name to its max length.

		// even if some files cannot be processed, the other files shall be stored correctly
		expectObjectExistence(t, obj2, true)
		expectObjectContent(t, obj2, []byte("world"))
	})
}

func buildTarArchive(files map[string][]byte) []byte {
	var buf bytes.Buffer
	w := tar.NewWriter(&buf)
	for fileName, contents := range files {
		err := w.WriteHeader(&tar.Header{
			Typeflag: tar.TypeReg,
			Name:     fileName,
			Size:     int64(len(contents)),
			Mode:     0100644,
		})
		if err != nil {
			panic(err.Error())
		}
		_, err = w.Write(contents)
		if err != nil {
			panic(err.Error())
		}
	}
	err := w.Close()
	if err != nil {
		panic(err.Error())
	}
	return buf.Bytes()
}

func buildInvalidObjectName() string {
	// 5000 is more than the usual max_object_name_length of 1024
	buf := make([]byte, 5000)
	for idx := range buf {
		buf[idx] = 'a'
	}
	return string(buf)
}