filesystem_e2e_test.go
1 // Copyright 2026 Alibaba Group Holding Ltd. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package e2e 16 17 import ( 18 "context" 19 "io" 20 "os" 21 "testing" 22 23 "github.com/alibaba/OpenSandbox/sdks/sandbox/go" 24 "github.com/stretchr/testify/require" 25 ) 26 27 func TestFilesystem_GetFileInfo(t *testing.T) { 28 ctx, sb := createTestSandbox(t) 29 30 info, err := sb.GetFileInfo(ctx, "/etc/os-release") 31 require.NoError(t, err) 32 33 fi, ok := info["/etc/os-release"] 34 require.True(t, ok, "expected /etc/os-release in result") 35 require.NotZero(t, fi.Size, "expected non-zero file size") 36 t.Logf("File info: path=%s size=%d owner=%s", fi.Path, fi.Size, fi.Owner) 37 } 38 39 func TestFilesystem_WriteReadDelete(t *testing.T) { 40 ctx, sb := createTestSandbox(t) 41 42 exec, err := sb.RunCommand(ctx, `echo "go-e2e-content" > /tmp/test-rw.txt`, nil) 43 require.NoError(t, err) 44 if exec.ExitCode != nil { 45 require.Equal(t, 0, *exec.ExitCode, "write exit code") 46 } 47 48 exec, err = sb.RunCommand(ctx, "cat /tmp/test-rw.txt", nil) 49 require.NoError(t, err) 50 require.Contains(t, exec.Text(), "go-e2e-content") 51 52 info, err := sb.GetFileInfo(ctx, "/tmp/test-rw.txt") 53 require.NoError(t, err) 54 _, ok := info["/tmp/test-rw.txt"] 55 require.True(t, ok, "file not found via GetFileInfo") 56 57 err = sb.DeleteFiles(ctx, []string{"/tmp/test-rw.txt"}) 58 require.NoError(t, err) 59 60 exec, err = sb.RunCommand(ctx, "test -f /tmp/test-rw.txt && echo exists || echo gone", nil) 61 require.NoError(t, err) 62 require.Contains(t, exec.Text(), "gone") 63 t.Log("Write/Read/Delete cycle passed") 64 } 65 66 func TestFilesystem_MoveFiles(t *testing.T) { 67 ctx, sb := createTestSandbox(t) 68 69 sb.RunCommand(ctx, `echo "move-me" > /tmp/move-src.txt`, nil) 70 71 err := sb.MoveFiles(ctx, opensandbox.MoveRequest{ 72 {Src: "/tmp/move-src.txt", Dest: "/tmp/move-dst.txt"}, 73 }) 74 require.NoError(t, err) 75 76 exec, err := sb.RunCommand(ctx, "cat /tmp/move-dst.txt", nil) 77 require.NoError(t, err) 78 require.Contains(t, exec.Text(), "move-me") 79 t.Log("MoveFiles passed") 80 } 81 82 func TestFilesystem_Directories(t *testing.T) { 83 ctx, sb := createTestSandbox(t) 84 85 err := sb.CreateDirectory(ctx, "/tmp/test-dir-e2e", 755) 86 require.NoError(t, err) 87 88 exec, err := sb.RunCommand(ctx, "test -d /tmp/test-dir-e2e && echo yes || echo no", nil) 89 require.NoError(t, err) 90 require.Contains(t, exec.Text(), "yes") 91 92 err = sb.DeleteDirectory(ctx, "/tmp/test-dir-e2e") 93 require.NoError(t, err) 94 t.Log("Directory create/delete passed") 95 } 96 97 func TestFilesystem_SearchFiles(t *testing.T) { 98 ctx, sb := createTestSandbox(t) 99 100 results, err := sb.SearchFiles(ctx, "/etc", "*.conf") 101 require.NoError(t, err) 102 t.Logf("Found %d files matching *.conf in /etc", len(results)) 103 } 104 105 func TestFilesystem_DownloadFile(t *testing.T) { 106 ctx, sb := createTestSandbox(t) 107 108 rc, err := sb.DownloadFile(ctx, "/etc/os-release", "") 109 require.NoError(t, err) 110 defer rc.Close() 111 112 data, err := io.ReadAll(rc) 113 require.NoError(t, err) 114 require.NotEmpty(t, data, "downloaded file is empty") 115 t.Logf("Downloaded %d bytes", len(data)) 116 } 117 118 func TestFilesystem_UploadAndDownloadFile(t *testing.T) { 119 ctx, sb := createTestSandbox(t) 120 121 tmp, err := os.CreateTemp("", "opensandbox-upload-*") 122 require.NoError(t, err) 123 defer os.Remove(tmp.Name()) 124 125 content := []byte("go-e2e-upload-download") 126 _, err = tmp.Write(content) 127 require.NoError(t, err) 128 require.NoError(t, tmp.Close()) 129 130 remotePath := "/tmp/go-e2e-upload-download.txt" 131 up, err := os.Open(tmp.Name()) 132 require.NoError(t, err) 133 defer up.Close() 134 require.NoError(t, sb.UploadFile(ctx, up, opensandbox.UploadFileOptions{ 135 FileName: "go-e2e-upload-download.txt", 136 Metadata: opensandbox.FileMetadata{Path: remotePath}, 137 })) 138 t.Cleanup(func() { 139 _ = sb.DeleteFiles(context.Background(), []string{remotePath}) 140 }) 141 142 rc, err := sb.DownloadFile(ctx, remotePath, "") 143 require.NoError(t, err) 144 defer rc.Close() 145 146 downloaded, err := io.ReadAll(rc) 147 require.NoError(t, err) 148 require.Equal(t, string(content), string(downloaded)) 149 } 150 151 func TestFilesystem_SetPermissions(t *testing.T) { 152 ctx, sb := createTestSandbox(t) 153 154 _, err := sb.RunCommand(ctx, `echo "perm-test" > /tmp/perm-e2e.txt`, nil) 155 require.NoError(t, err) 156 t.Cleanup(func() { _ = sb.DeleteFiles(context.Background(), []string{"/tmp/perm-e2e.txt"}) }) 157 158 err = sb.SetPermissions(ctx, opensandbox.PermissionsRequest{ 159 "/tmp/perm-e2e.txt": {Mode: 644}, 160 }) 161 require.NoError(t, err) 162 163 exec, err := sb.RunCommand(ctx, `stat -c "%a" /tmp/perm-e2e.txt || stat -f "%Lp" /tmp/perm-e2e.txt`, nil) 164 require.NoError(t, err) 165 require.Contains(t, exec.Text(), "644") 166 } 167 168 func TestFilesystem_ReplaceInFiles(t *testing.T) { 169 ctx, sb := createTestSandbox(t) 170 171 _, err := sb.RunCommand(ctx, `echo "hello localhost" > /tmp/replace-e2e.txt`, nil) 172 require.NoError(t, err) 173 t.Cleanup(func() { _ = sb.DeleteFiles(context.Background(), []string{"/tmp/replace-e2e.txt"}) }) 174 175 err = sb.ReplaceInFiles(ctx, opensandbox.ReplaceRequest{ 176 "/tmp/replace-e2e.txt": {Old: "localhost", New: "example.com"}, 177 }) 178 require.NoError(t, err) 179 180 exec, err := sb.RunCommand(ctx, "cat /tmp/replace-e2e.txt", nil) 181 require.NoError(t, err) 182 require.Contains(t, exec.Text(), "example.com") 183 }