Skip to content

Commit 00793b2

Browse files
author
Kaan Yalti
committed
enhancement(5235): added unpack error handling tests in upgrade_test
enhancement(5235): updated the unpack tests
1 parent b5c24c9 commit 00793b2

File tree

1 file changed

+135
-0
lines changed

1 file changed

+135
-0
lines changed

internal/pkg/agent/application/upgrade/upgrade_test.go

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@
55
package upgrade
66

77
import (
8+
"bytes"
89
"context"
910
"crypto/tls"
1011
"fmt"
12+
"io"
13+
"net/http"
14+
"net/http/httptest"
1115
"os"
1216
"path/filepath"
1317
"runtime"
@@ -26,6 +30,8 @@ import (
2630
"github.com/elastic/elastic-agent-libs/transport/tlscommon"
2731
"github.com/elastic/elastic-agent/internal/pkg/agent/application/paths"
2832
"github.com/elastic/elastic-agent/internal/pkg/agent/application/upgrade/artifact"
33+
downloadErrors "github.com/elastic/elastic-agent/internal/pkg/agent/application/upgrade/artifact/download/errors"
34+
"github.com/elastic/elastic-agent/internal/pkg/agent/application/upgrade/common"
2935
"github.com/elastic/elastic-agent/internal/pkg/agent/application/upgrade/details"
3036
"github.com/elastic/elastic-agent/internal/pkg/agent/errors"
3137
"github.com/elastic/elastic-agent/internal/pkg/config"
@@ -38,6 +44,7 @@ import (
3844
"github.com/elastic/elastic-agent/pkg/core/logger"
3945
"github.com/elastic/elastic-agent/pkg/core/logger/loggertest"
4046
agtversion "github.com/elastic/elastic-agent/pkg/version"
47+
"github.com/elastic/elastic-agent/testing/mocks/internal_/pkg/agent/application/info"
4148
mocks "github.com/elastic/elastic-agent/testing/mocks/pkg/control/v2/client"
4249
)
4350

@@ -1365,3 +1372,131 @@ func createArchive(t *testing.T, archiveName string, archiveFiles []files) (stri
13651372
}
13661373
return createTarArchive(t, archiveName, archiveFiles)
13671374
}
1375+
1376+
func TestUpgradeUnpackErrors(t *testing.T) {
1377+
log, _ := loggertest.New("test")
1378+
1379+
targetVersion := agtversion.NewParsedSemVer(3, 4, 5, "SNAPSHOT", "")
1380+
targetArtifactName, targetArchiveFiles := buildArchiveFiles(t, archiveFilesWithMoreComponents, targetVersion, "ghijkl")
1381+
1382+
// Get the content of the component file to be used in copy function
1383+
// assertions. It will be used to make sure the error gets triggered in the
1384+
// copy call in the unpacker and not the downloader.
1385+
targetArchiveComponentsFileContent := ""
1386+
for _, file := range targetArchiveFiles {
1387+
if file.fType == REGULAR {
1388+
dir := filepath.Dir(file.path)
1389+
if strings.HasSuffix(dir, "components") {
1390+
targetArchiveComponentsFileContent = file.content
1391+
break
1392+
}
1393+
}
1394+
}
1395+
1396+
// dir name of the versioned home
1397+
// used to calculate component paths
1398+
newVersionedDirName := "elastic-agent-3.4.5-SNAPSHOT-ghijkl"
1399+
1400+
mockAgentInfo := info.NewAgent(t)
1401+
mockAgentInfo.On("Version").Return(targetVersion.String())
1402+
1403+
upgradeDetails := details.NewDetails(targetVersion.String(), details.StateRequested, "test")
1404+
1405+
mockStdlibFuncs := []common.MockStdLibFuncName{common.CopyFuncName, common.OpenFileFuncName, common.MkdirAllFuncName}
1406+
1407+
testCases := map[string]struct {
1408+
mockStdlibFunc common.MockStdLibFuncName
1409+
mockReturnedError error
1410+
expectedError error
1411+
}{}
1412+
1413+
for _, mockStdlibFunc := range mockStdlibFuncs {
1414+
for _, te := range downloadErrors.OS_DiskSpaceErrors {
1415+
testCases[fmt.Sprintf("unpack_should_return_error_if_unpack_%s_fails: %v", mockStdlibFunc, te)] = struct {
1416+
mockStdlibFunc common.MockStdLibFuncName
1417+
mockReturnedError error
1418+
expectedError error
1419+
}{
1420+
mockStdlibFunc: mockStdlibFunc,
1421+
mockReturnedError: te,
1422+
expectedError: downloadErrors.ErrInsufficientDiskSpace,
1423+
}
1424+
}
1425+
}
1426+
1427+
for name, tc := range testCases {
1428+
t.Run(name, func(t *testing.T) {
1429+
tempDir := t.TempDir()
1430+
paths.SetTop(tempDir)
1431+
paths.SetDownloads(filepath.Join(tempDir, "downloads"))
1432+
1433+
targetArchive, err := createArchive(t, targetArtifactName, targetArchiveFiles)
1434+
require.NoError(t, err)
1435+
1436+
// Used to assert that the mkdirAll error is triggered in the
1437+
// unpacker and not the downloader
1438+
newComponentsDir := filepath.Join(paths.Data(), newVersionedDirName, "components")
1439+
// Used to assert that the openFile error is triggered in the
1440+
// unpacker and not the downloader
1441+
newComponentsFile := filepath.Join(newComponentsDir, "comp1")
1442+
1443+
t.Logf("Created archive: %s", targetArchive)
1444+
1445+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1446+
http.ServeFile(w, r, targetArchive)
1447+
}))
1448+
t.Cleanup(server.Close)
1449+
1450+
config := artifact.Config{
1451+
TargetDirectory: paths.Downloads(),
1452+
SourceURI: server.URL,
1453+
RetrySleepInitDuration: 1 * time.Second,
1454+
HTTPTransportSettings: httpcommon.HTTPTransportSettings{
1455+
Timeout: 1 * time.Second,
1456+
},
1457+
}
1458+
1459+
stdlibMocker := common.PrepareStdLibMocks(common.StdLibMocks{
1460+
CopyMock: func(dst io.Writer, src io.Reader) (int64, error) {
1461+
// If the content is not the same as the target archive components file content,
1462+
// write the content to the destination. This is to make
1463+
// sure that the error is triggered in unpacker and not in downloader
1464+
buf, err := io.ReadAll(src)
1465+
require.NoError(t, err)
1466+
if !bytes.Equal(buf, []byte(targetArchiveComponentsFileContent)) {
1467+
return io.Copy(dst, bytes.NewReader(buf))
1468+
}
1469+
1470+
return 0, tc.mockReturnedError
1471+
},
1472+
OpenFileMock: func(name string, flag int, perm os.FileMode) (*os.File, error) {
1473+
// Make sure that the openFile error is triggered in the
1474+
// unpacker and not the downloader
1475+
if name != newComponentsFile {
1476+
return os.OpenFile(name, flag, perm)
1477+
}
1478+
1479+
return nil, tc.mockReturnedError
1480+
},
1481+
MkdirAllMock: func(path string, perm os.FileMode) error {
1482+
// Make sure that the mkdirAll error is triggered in the
1483+
// unpacker and not the downloader
1484+
if path != newComponentsDir {
1485+
return os.MkdirAll(path, perm)
1486+
}
1487+
1488+
return tc.mockReturnedError
1489+
},
1490+
})
1491+
1492+
stdlibMocker(t, tc.mockStdlibFunc)
1493+
1494+
upgrader, err := NewUpgrader(log, &config, mockAgentInfo)
1495+
require.NoError(t, err)
1496+
1497+
_, err = upgrader.Upgrade(context.Background(), targetVersion.String(), server.URL, nil, upgradeDetails, true, true)
1498+
require.ErrorIs(t, err, tc.expectedError, "expected error mismatch")
1499+
require.Equal(t, upgradeDetails.State, details.StateExtracting)
1500+
})
1501+
}
1502+
}

0 commit comments

Comments
 (0)