gcs_test.go - afero - [fork] go afero port for 9front
 (HTM) git clone https://git.drkhsh.at/afero.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       gcs_test.go (19073B)
       ---
            1 // Copyright © 2021 Vasily Ovchinnikov <vasily@remerge.io>.
            2 //
            3 // Most of the tests are "derived" from the Afero's own tarfs implementation.
            4 // Write-oriented tests and/or checks have been added on top of that
            5 
            6 package gcsfs
            7 
            8 import (
            9         "context"
           10         "errors"
           11         "fmt"
           12         "io"
           13         "os"
           14         "path/filepath"
           15         "reflect"
           16         "strings"
           17         "syscall"
           18         "testing"
           19 
           20         "cloud.google.com/go/storage"
           21         "golang.org/x/oauth2/google"
           22 
           23         "github.com/spf13/afero"
           24         "github.com/spf13/afero/gcsfs/internal/stiface"
           25 )
           26 
           27 const (
           28         testBytes = 8
           29         dirSize   = 42
           30 )
           31 
           32 var bucketName = "a-test-bucket"
           33 
           34 var files = []struct {
           35         name            string
           36         exists          bool
           37         isdir           bool
           38         size            int64
           39         content         string
           40         offset          int64
           41         contentAtOffset string
           42 }{
           43         {"sub", true, true, dirSize, "", 0, ""},
           44         {"sub/testDir2", true, true, dirSize, "", 0, ""},
           45         {"sub/testDir2/testFile", true, false, 8 * 1024, "c", 4 * 1024, "d"},
           46         {"testFile", true, false, 12 * 1024, "a", 7 * 1024, "b"},
           47         {"testDir1/testFile", true, false, 3 * 512, "b", 512, "c"},
           48 
           49         {"", false, true, dirSize, "", 0, ""}, // special case
           50 
           51         {"nonExisting", false, false, dirSize, "", 0, ""},
           52 }
           53 
           54 var dirs = []struct {
           55         name     string
           56         children []string
           57 }{
           58         {"", []string{"sub", "testDir1", "testFile"}}, // in this case it will be prepended with bucket name
           59         {"sub", []string{"testDir2"}},
           60         {"sub/testDir2", []string{"testFile"}},
           61         {"testDir1", []string{"testFile"}},
           62 }
           63 
           64 var gcsAfs *afero.Afero
           65 
           66 func TestMain(m *testing.M) {
           67         ctx := context.Background()
           68         var err error
           69 
           70         // in order to respect deferring
           71         var exitCode int
           72         defer os.Exit(exitCode)
           73 
           74         defer func() {
           75                 err := recover()
           76                 if err != nil {
           77                         fmt.Print(err)
           78                         exitCode = 2
           79                 }
           80         }()
           81 
           82         // Check if any credentials are present. If not, a fake service account, taken from the link
           83         // would be used: https://github.com/google/oauth2l/blob/master/integration/fixtures/fake-service-account.json
           84         cred, err := google.FindDefaultCredentials(ctx)
           85         if err != nil && !strings.HasPrefix(err.Error(), "google: could not find default credentials") {
           86                 panic(err)
           87         }
           88 
           89         if cred == nil {
           90                 var fakeCredentialsAbsPath string
           91                 fakeCredentialsAbsPath, err = filepath.Abs("gcs-fake-service-account.json")
           92                 if err != nil {
           93                         panic(err)
           94                 }
           95 
           96                 err = os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", fakeCredentialsAbsPath)
           97                 if err != nil {
           98                         panic(err)
           99                 }
          100 
          101                 // reset it after the run
          102                 defer func() {
          103                         err = os.Remove("GOOGLE_APPLICATION_CREDENTIALS")
          104                         if err != nil {
          105                                 // it's worth printing it out explicitly, since it might have implications further down the road
          106                                 fmt.Print("failed to clear fake GOOGLE_APPLICATION_CREDENTIALS", err)
          107                         }
          108                 }()
          109         }
          110 
          111         var c *storage.Client
          112         c, err = storage.NewClient(ctx)
          113         if err != nil {
          114                 panic(err)
          115         }
          116         client := stiface.AdaptClient(c)
          117 
          118         // This block is mocking the client for the sake of isolated testing
          119         mockClient := newClientMock()
          120         mockClient.Client = client
          121 
          122         gcsAfs = &afero.Afero{Fs: &GcsFs{NewGcsFs(ctx, mockClient)}}
          123 
          124         // Uncomment to use the real, not mocked, client
          125         // gcsAfs = &Afero{Fs: &GcsFs{gcsfs.NewGcsFs(ctx, client)}}
          126 
          127         exitCode = m.Run()
          128 }
          129 
          130 func createFiles(t *testing.T) {
          131         t.Helper()
          132         var err error
          133 
          134         // the files have to be created first
          135         for _, f := range files {
          136                 if !f.isdir && f.exists {
          137                         name := filepath.Join(bucketName, f.name)
          138 
          139                         var freshFile afero.File
          140                         freshFile, err = gcsAfs.Create(name)
          141                         if err != nil {
          142                                 t.Fatalf("failed to create a file \"%s\": %s", f.name, err)
          143                         }
          144 
          145                         var written int
          146                         var totalWritten int64
          147                         for totalWritten < f.size {
          148                                 if totalWritten < f.offset {
          149                                         writeBuf := []byte(strings.Repeat(f.content, int(f.offset)))
          150                                         written, err = freshFile.WriteAt(writeBuf, totalWritten)
          151                                 } else {
          152                                         writeBuf := []byte(strings.Repeat(f.contentAtOffset, int(f.size-f.offset)))
          153                                         written, err = freshFile.WriteAt(writeBuf, totalWritten)
          154                                 }
          155                                 if err != nil {
          156                                         t.Fatalf("failed to write a file \"%s\": %s", f.name, err)
          157                                 }
          158 
          159                                 totalWritten += int64(written)
          160                         }
          161 
          162                         err = freshFile.Close()
          163                         if err != nil {
          164                                 t.Fatalf("failed to close a file \"%s\": %s", f.name, err)
          165                         }
          166                 }
          167         }
          168 }
          169 
          170 func removeFiles(t *testing.T) {
          171         t.Helper()
          172         var err error
          173 
          174         // the files have to be created first
          175         for _, f := range files {
          176                 if !f.isdir && f.exists {
          177                         name := filepath.Join(bucketName, f.name)
          178 
          179                         err = gcsAfs.Remove(name)
          180                         if err != nil && err == syscall.ENOENT {
          181                                 t.Errorf("failed to remove file \"%s\": %s", f.name, err)
          182                         }
          183                 }
          184         }
          185 }
          186 
          187 func TestGcsFsOpen(t *testing.T) {
          188         createFiles(t)
          189         defer removeFiles(t)
          190 
          191         for _, f := range files {
          192                 nameBase := filepath.Join(bucketName, f.name)
          193 
          194                 names := []string{
          195                         nameBase,
          196                         string(os.PathSeparator) + nameBase,
          197                 }
          198                 if f.name == "" {
          199                         names = []string{f.name}
          200                 }
          201 
          202                 for _, name := range names {
          203                         file, err := gcsAfs.Open(name)
          204                         if (err == nil) != f.exists {
          205                                 t.Errorf("%v exists = %v, but got err = %v", name, f.exists, err)
          206                         }
          207 
          208                         if !f.exists {
          209                                 continue
          210                         }
          211                         if err != nil {
          212                                 t.Fatalf("%v: %v", name, err)
          213                         }
          214 
          215                         if file.Name() != filepath.FromSlash(nameBase) {
          216                                 t.Errorf("Name(), got %v, expected %v", file.Name(), filepath.FromSlash(nameBase))
          217                         }
          218 
          219                         s, err := file.Stat()
          220                         if err != nil {
          221                                 t.Fatalf("stat %v: got error '%v'", file.Name(), err)
          222                         }
          223 
          224                         if isdir := s.IsDir(); isdir != f.isdir {
          225                                 t.Errorf("%v directory, got: %v, expected: %v", file.Name(), isdir, f.isdir)
          226                         }
          227 
          228                         if size := s.Size(); size != f.size {
          229                                 t.Errorf("%v size, got: %v, expected: %v", file.Name(), size, f.size)
          230                         }
          231                 }
          232         }
          233 }
          234 
          235 func TestGcsRead(t *testing.T) {
          236         createFiles(t)
          237         defer removeFiles(t)
          238 
          239         for _, f := range files {
          240                 if !f.exists {
          241                         continue
          242                 }
          243 
          244                 nameBase := filepath.Join(bucketName, f.name)
          245 
          246                 names := []string{
          247                         nameBase,
          248                         string(os.PathSeparator) + nameBase,
          249                 }
          250                 if f.name == "" {
          251                         names = []string{f.name}
          252                 }
          253 
          254                 for _, name := range names {
          255                         file, err := gcsAfs.Open(name)
          256                         if err != nil {
          257                                 t.Fatalf("opening %v: %v", name, err)
          258                         }
          259 
          260                         buf := make([]byte, 8)
          261                         n, err := file.Read(buf)
          262                         if err != nil {
          263                                 if f.isdir && (err != syscall.EISDIR) {
          264                                         t.Errorf("%v got error %v, expected EISDIR", name, err)
          265                                 } else if !f.isdir {
          266                                         t.Errorf("%v: %v", name, err)
          267                                 }
          268                         } else if n != 8 {
          269                                 t.Errorf("%v: got %d read bytes, expected 8", name, n)
          270                         } else if string(buf) != strings.Repeat(f.content, testBytes) {
          271                                 t.Errorf("%v: got <%s>, expected <%s>", f.name, f.content, string(buf))
          272                         }
          273                 }
          274         }
          275 }
          276 
          277 func TestGcsReadAt(t *testing.T) {
          278         createFiles(t)
          279         defer removeFiles(t)
          280 
          281         for _, f := range files {
          282                 if !f.exists {
          283                         continue
          284                 }
          285 
          286                 nameBase := filepath.Join(bucketName, f.name)
          287 
          288                 names := []string{
          289                         nameBase,
          290                         string(os.PathSeparator) + nameBase,
          291                 }
          292                 if f.name == "" {
          293                         names = []string{f.name}
          294                 }
          295 
          296                 for _, name := range names {
          297                         file, err := gcsAfs.Open(name)
          298                         if err != nil {
          299                                 t.Fatalf("opening %v: %v", name, err)
          300                         }
          301 
          302                         buf := make([]byte, testBytes)
          303                         n, err := file.ReadAt(buf, f.offset-testBytes/2)
          304                         if err != nil {
          305                                 if f.isdir && (err != syscall.EISDIR) {
          306                                         t.Errorf("%v got error %v, expected EISDIR", name, err)
          307                                 } else if !f.isdir {
          308                                         t.Errorf("%v: %v", name, err)
          309                                 }
          310                         } else if n != 8 {
          311                                 t.Errorf("%v: got %d read bytes, expected 8", f.name, n)
          312                         } else if string(buf) != strings.Repeat(f.content, testBytes/2)+strings.Repeat(f.contentAtOffset, testBytes/2) {
          313                                 t.Errorf("%v: got <%s>, expected <%s>", f.name, f.contentAtOffset, string(buf))
          314                         }
          315                 }
          316         }
          317 }
          318 
          319 func TestGcsSeek(t *testing.T) {
          320         createFiles(t)
          321         defer removeFiles(t)
          322 
          323         for _, f := range files {
          324                 if !f.exists {
          325                         continue
          326                 }
          327 
          328                 nameBase := filepath.Join(bucketName, f.name)
          329 
          330                 names := []string{
          331                         nameBase,
          332                         string(os.PathSeparator) + nameBase,
          333                 }
          334                 if f.name == "" {
          335                         names = []string{f.name}
          336                 }
          337 
          338                 for _, name := range names {
          339                         file, err := gcsAfs.Open(name)
          340                         if err != nil {
          341                                 t.Fatalf("opening %v: %v", name, err)
          342                         }
          343 
          344                         tests := []struct {
          345                                 offIn  int64
          346                                 whence int
          347                                 offOut int64
          348                         }{
          349                                 {0, io.SeekStart, 0},
          350                                 {10, io.SeekStart, 10},
          351                                 {1, io.SeekCurrent, 11},
          352                                 {10, io.SeekCurrent, 21},
          353                                 {0, io.SeekEnd, f.size},
          354                                 {-1, io.SeekEnd, f.size - 1},
          355                         }
          356 
          357                         for _, s := range tests {
          358                                 n, err := file.Seek(s.offIn, s.whence)
          359                                 if err != nil {
          360                                         if f.isdir && err == syscall.EISDIR {
          361                                                 continue
          362                                         }
          363 
          364                                         t.Errorf("%v: %v", name, err)
          365                                 }
          366 
          367                                 if n != s.offOut {
          368                                         t.Errorf("%v: (off: %v, whence: %v): got %v, expected %v", f.name, s.offIn, s.whence, n, s.offOut)
          369                                 }
          370                         }
          371                 }
          372 
          373         }
          374 }
          375 
          376 func TestGcsName(t *testing.T) {
          377         createFiles(t)
          378         defer removeFiles(t)
          379 
          380         for _, f := range files {
          381                 if !f.exists {
          382                         continue
          383                 }
          384 
          385                 nameBase := filepath.Join(bucketName, f.name)
          386 
          387                 names := []string{
          388                         nameBase,
          389                         string(os.PathSeparator) + nameBase,
          390                 }
          391                 if f.name == "" {
          392                         names = []string{f.name}
          393                 }
          394 
          395                 for _, name := range names {
          396                         file, err := gcsAfs.Open(name)
          397                         if err != nil {
          398                                 t.Fatalf("opening %v: %v", name, err)
          399                         }
          400 
          401                         n := file.Name()
          402                         if n != filepath.FromSlash(nameBase) {
          403                                 t.Errorf("got: %v, expected: %v", n, filepath.FromSlash(nameBase))
          404                         }
          405                 }
          406 
          407         }
          408 }
          409 
          410 func TestGcsClose(t *testing.T) {
          411         createFiles(t)
          412         defer removeFiles(t)
          413 
          414         for _, f := range files {
          415                 if !f.exists {
          416                         continue
          417                 }
          418 
          419                 nameBase := filepath.Join(bucketName, f.name)
          420 
          421                 names := []string{
          422                         nameBase,
          423                         string(os.PathSeparator) + nameBase,
          424                 }
          425                 if f.name == "" {
          426                         names = []string{f.name}
          427                 }
          428 
          429                 for _, name := range names {
          430                         file, err := gcsAfs.Open(name)
          431                         if err != nil {
          432                                 t.Fatalf("opening %v: %v", name, err)
          433                         }
          434 
          435                         err = file.Close()
          436                         if err != nil {
          437                                 t.Errorf("%v: %v", name, err)
          438                         }
          439 
          440                         err = file.Close()
          441                         if err == nil {
          442                                 t.Errorf("%v: closing twice should return an error", name)
          443                         }
          444 
          445                         buf := make([]byte, 8)
          446                         n, err := file.Read(buf)
          447                         if n != 0 || err == nil {
          448                                 t.Errorf("%v: could read from a closed file", name)
          449                         }
          450 
          451                         n, err = file.ReadAt(buf, 256)
          452                         if n != 0 || err == nil {
          453                                 t.Errorf("%v: could readAt from a closed file", name)
          454                         }
          455 
          456                         off, err := file.Seek(0, io.SeekStart)
          457                         if off != 0 || err == nil {
          458                                 t.Errorf("%v: could seek from a closed file", name)
          459                         }
          460                 }
          461         }
          462 }
          463 
          464 func TestGcsOpenFile(t *testing.T) {
          465         createFiles(t)
          466         defer removeFiles(t)
          467 
          468         for _, f := range files {
          469                 nameBase := filepath.Join(bucketName, f.name)
          470 
          471                 names := []string{
          472                         nameBase,
          473                         string(os.PathSeparator) + nameBase,
          474                 }
          475                 if f.name == "" {
          476                         names = []string{f.name}
          477                 }
          478 
          479                 for _, name := range names {
          480                         file, err := gcsAfs.OpenFile(name, os.O_RDONLY, 0o400)
          481                         if !f.exists {
          482                                 if (f.name != "" && !errors.Is(err, syscall.ENOENT)) ||
          483                                         (f.name == "" && !errors.Is(err, ErrNoBucketInName)) {
          484                                         t.Errorf("%v: got %v, expected%v", name, err, syscall.ENOENT)
          485                                 }
          486 
          487                                 continue
          488                         }
          489 
          490                         if err != nil {
          491                                 t.Fatalf("%v: %v", name, err)
          492                         }
          493 
          494                         err = file.Close()
          495                         if err != nil {
          496                                 t.Fatalf("failed to close a file \"%s\": %s", name, err)
          497                         }
          498 
          499                         _, err = gcsAfs.OpenFile(name, os.O_CREATE, 0o600)
          500                         if !errors.Is(err, syscall.EPERM) {
          501                                 t.Errorf("%v: open for write: got %v, expected %v", name, err, syscall.EPERM)
          502                         }
          503                 }
          504         }
          505 }
          506 
          507 func TestGcsFsStat(t *testing.T) {
          508         createFiles(t)
          509         defer removeFiles(t)
          510 
          511         for _, f := range files {
          512                 nameBase := filepath.Join(bucketName, f.name)
          513 
          514                 names := []string{
          515                         nameBase,
          516                         string(os.PathSeparator) + nameBase,
          517                 }
          518                 if f.name == "" {
          519                         names = []string{f.name}
          520                 }
          521 
          522                 for _, name := range names {
          523                         fi, err := gcsAfs.Stat(name)
          524                         if !f.exists {
          525                                 if (f.name != "" && !errors.Is(err, syscall.ENOENT)) ||
          526                                         (f.name == "" && !errors.Is(err, ErrNoBucketInName)) {
          527                                         t.Errorf("%v: got %v, expected%v", name, err, syscall.ENOENT)
          528                                 }
          529 
          530                                 continue
          531                         }
          532 
          533                         if err != nil {
          534                                 t.Fatalf("stat %v: got error '%v'", name, err)
          535                         }
          536 
          537                         if isdir := fi.IsDir(); isdir != f.isdir {
          538                                 t.Errorf("%v directory, got: %v, expected: %v", name, isdir, f.isdir)
          539                         }
          540 
          541                         if size := fi.Size(); size != f.size {
          542                                 t.Errorf("%v size, got: %v, expected: %v", name, size, f.size)
          543                         }
          544                 }
          545         }
          546 }
          547 
          548 func TestGcsReaddir(t *testing.T) {
          549         createFiles(t)
          550         defer removeFiles(t)
          551 
          552         for _, d := range dirs {
          553                 nameBase := filepath.Join(bucketName, d.name)
          554 
          555                 names := []string{
          556                         nameBase,
          557                         string(os.PathSeparator) + nameBase,
          558                 }
          559 
          560                 for _, name := range names {
          561                         dir, err := gcsAfs.Open(name)
          562                         if err != nil {
          563                                 t.Fatal(err)
          564                         }
          565 
          566                         fi, err := dir.Readdir(0)
          567                         if err != nil {
          568                                 t.Fatal(err)
          569                         }
          570                         var fileNames []string
          571                         for _, f := range fi {
          572                                 fileNames = append(fileNames, f.Name())
          573                         }
          574 
          575                         if !reflect.DeepEqual(fileNames, d.children) {
          576                                 t.Errorf("%v: children, got '%v', expected '%v'", name, fileNames, d.children)
          577                         }
          578 
          579                         fi, err = dir.Readdir(1)
          580                         if err != nil {
          581                                 t.Fatal(err)
          582                         }
          583 
          584                         fileNames = []string{}
          585                         for _, f := range fi {
          586                                 fileNames = append(fileNames, f.Name())
          587                         }
          588 
          589                         if !reflect.DeepEqual(fileNames, d.children[0:1]) {
          590                                 t.Errorf("%v: children, got '%v', expected '%v'", name, fileNames, d.children[0:1])
          591                         }
          592                 }
          593         }
          594 
          595         nameBase := filepath.Join(bucketName, "testFile")
          596 
          597         names := []string{
          598                 nameBase,
          599                 string(os.PathSeparator) + nameBase,
          600         }
          601 
          602         for _, name := range names {
          603                 dir, err := gcsAfs.Open(name)
          604                 if err != nil {
          605                         t.Fatal(err)
          606                 }
          607 
          608                 _, err = dir.Readdir(-1)
          609                 if err != syscall.ENOTDIR {
          610                         t.Fatal("Expected error")
          611                 }
          612         }
          613 }
          614 
          615 func TestGcsReaddirnames(t *testing.T) {
          616         createFiles(t)
          617         defer removeFiles(t)
          618 
          619         for _, d := range dirs {
          620                 nameBase := filepath.Join(bucketName, d.name)
          621 
          622                 names := []string{
          623                         nameBase,
          624                         string(os.PathSeparator) + nameBase,
          625                 }
          626 
          627                 for _, name := range names {
          628                         dir, err := gcsAfs.Open(name)
          629                         if err != nil {
          630                                 t.Fatal(err)
          631                         }
          632 
          633                         fileNames, err := dir.Readdirnames(0)
          634                         if err != nil {
          635                                 t.Fatal(err)
          636                         }
          637 
          638                         if !reflect.DeepEqual(fileNames, d.children) {
          639                                 t.Errorf("%v: children, got '%v', expected '%v'", name, fileNames, d.children)
          640                         }
          641 
          642                         fileNames, err = dir.Readdirnames(1)
          643                         if err != nil {
          644                                 t.Fatal(err)
          645                         }
          646 
          647                         if !reflect.DeepEqual(fileNames, d.children[0:1]) {
          648                                 t.Errorf("%v: children, got '%v', expected '%v'", name, fileNames, d.children[0:1])
          649                         }
          650                 }
          651         }
          652 
          653         nameBase := filepath.Join(bucketName, "testFile")
          654 
          655         names := []string{
          656                 nameBase,
          657                 string(os.PathSeparator) + nameBase,
          658         }
          659 
          660         for _, name := range names {
          661                 dir, err := gcsAfs.Open(name)
          662                 if err != nil {
          663                         t.Fatal(err)
          664                 }
          665 
          666                 _, err = dir.Readdirnames(-1)
          667                 if err != syscall.ENOTDIR {
          668                         t.Fatal("Expected error")
          669                 }
          670         }
          671 }
          672 
          673 func TestGcsGlob(t *testing.T) {
          674         createFiles(t)
          675         defer removeFiles(t)
          676 
          677         for _, s := range []struct {
          678                 glob    string
          679                 entries []string
          680         }{
          681                 {filepath.FromSlash("*"), []string{filepath.FromSlash("sub"), filepath.FromSlash("testDir1"), filepath.FromSlash("testFile")}},
          682                 {filepath.FromSlash("sub/*"), []string{filepath.FromSlash("sub/testDir2")}},
          683                 {filepath.FromSlash("sub/testDir2/*"), []string{filepath.FromSlash("sub/testDir2/testFile")}},
          684                 {filepath.FromSlash("testDir1/*"), []string{filepath.FromSlash("testDir1/testFile")}},
          685         } {
          686                 nameBase := filepath.Join(bucketName, s.glob)
          687 
          688                 prefixedGlobs := []string{
          689                         nameBase,
          690                         string(os.PathSeparator) + nameBase,
          691                 }
          692 
          693                 prefixedEntries := [][]string{{}, {}}
          694                 for _, entry := range s.entries {
          695                         prefixedEntries[0] = append(prefixedEntries[0], filepath.Join(bucketName, entry))
          696                         prefixedEntries[1] = append(prefixedEntries[1], string(os.PathSeparator)+filepath.Join(bucketName, entry))
          697                 }
          698 
          699                 for i, prefixedGlob := range prefixedGlobs {
          700                         entries, err := afero.Glob(gcsAfs.Fs, prefixedGlob)
          701                         if err != nil {
          702                                 t.Error(err)
          703                         }
          704                         if reflect.DeepEqual(entries, prefixedEntries[i]) {
          705                                 t.Logf("glob: %s: glob ok", prefixedGlob)
          706                         } else {
          707                                 t.Errorf("glob: %s: got %#v, expected %#v", prefixedGlob, entries, prefixedEntries)
          708                         }
          709                 }
          710         }
          711 }
          712 
          713 func TestGcsMkdir(t *testing.T) {
          714         t.Run("empty", func(t *testing.T) {
          715                 emptyDirName := bucketName
          716 
          717                 err := gcsAfs.Mkdir(emptyDirName, 0o755)
          718                 if err == nil {
          719                         t.Fatal("did not fail upon creation of an empty folder")
          720                 }
          721         })
          722         t.Run("success", func(t *testing.T) {
          723                 dirName := filepath.Join(bucketName, "a-test-dir")
          724                 var err error
          725 
          726                 err = gcsAfs.Mkdir(dirName, 0o755)
          727                 if err != nil {
          728                         t.Fatal("failed to create a folder with error", err)
          729                 }
          730 
          731                 info, err := gcsAfs.Stat(dirName)
          732                 if err != nil {
          733                         t.Fatal("failed to get info", err)
          734                 }
          735                 if !info.IsDir() {
          736                         t.Fatalf("%s: not a dir", dirName)
          737                 }
          738                 if !info.Mode().IsDir() {
          739                         t.Errorf("%s: mode is not directory", dirName)
          740                 }
          741 
          742                 if info.Mode() != os.ModeDir|0o755 {
          743                         t.Errorf("%s: wrong permissions, expected drwxr-xr-x, got %s", dirName, info.Mode())
          744                 }
          745 
          746                 err = gcsAfs.Remove(dirName)
          747                 if err != nil {
          748                         t.Fatalf("could not delete the folder %s after the test with error: %s", dirName, err)
          749                 }
          750         })
          751 }
          752 
          753 func TestGcsMkdirAll(t *testing.T) {
          754         t.Run("empty", func(t *testing.T) {
          755                 emptyDirName := bucketName
          756 
          757                 err := gcsAfs.MkdirAll(emptyDirName, 0o755)
          758                 if err == nil {
          759                         t.Fatal("did not fail upon creation of an empty folder")
          760                 }
          761         })
          762         t.Run("success", func(t *testing.T) {
          763                 dirName := filepath.Join(bucketName, "a/b/c")
          764 
          765                 err := gcsAfs.MkdirAll(dirName, 0o755)
          766                 if err != nil {
          767                         t.Fatal(err)
          768                 }
          769 
          770                 info, err := gcsAfs.Stat(filepath.Join(bucketName, "a"))
          771                 if err != nil {
          772                         t.Fatal(err)
          773                 }
          774                 if !info.Mode().IsDir() {
          775                         t.Errorf("%s: mode is not directory", filepath.Join(bucketName, "a"))
          776                 }
          777                 if info.Mode() != os.ModeDir|0o755 {
          778                         t.Errorf("%s: wrong permissions, expected drwxr-xr-x, got %s", filepath.Join(bucketName, "a"), info.Mode())
          779                 }
          780                 info, err = gcsAfs.Stat(filepath.Join(bucketName, "a/b"))
          781                 if err != nil {
          782                         t.Fatal(err)
          783                 }
          784                 if !info.Mode().IsDir() {
          785                         t.Errorf("%s: mode is not directory", filepath.Join(bucketName, "a/b"))
          786                 }
          787                 if info.Mode() != os.ModeDir|0o755 {
          788                         t.Errorf("%s: wrong permissions, expected drwxr-xr-x, got %s", filepath.Join(bucketName, "a/b"), info.Mode())
          789                 }
          790                 info, err = gcsAfs.Stat(dirName)
          791                 if err != nil {
          792                         t.Fatal(err)
          793                 }
          794                 if !info.Mode().IsDir() {
          795                         t.Errorf("%s: mode is not directory", dirName)
          796                 }
          797                 if info.Mode() != os.ModeDir|0o755 {
          798                         t.Errorf("%s: wrong permissions, expected drwxr-xr-x, got %s", dirName, info.Mode())
          799                 }
          800 
          801                 err = gcsAfs.RemoveAll(filepath.Join(bucketName, "a"))
          802                 if err != nil {
          803                         t.Fatalf("failed to remove the folder %s with error: %s", filepath.Join(bucketName, "a"), err)
          804                 }
          805         })
          806 }
          807 
          808 func TestGcsRemoveAll(t *testing.T) {
          809         t.Run("non-existent", func(t *testing.T) {
          810                 err := gcsAfs.RemoveAll(filepath.Join(bucketName, "a"))
          811                 if err != nil {
          812                         t.Fatal("error should be nil when removing non-existent file")
          813                 }
          814         })
          815         t.Run("success", func(t *testing.T) {
          816                 aDir := filepath.Join(bucketName, "a")
          817                 bDir := filepath.Join(aDir, "b")
          818 
          819                 err := gcsAfs.MkdirAll(bDir, 0o755)
          820                 if err != nil {
          821                         t.Fatal(err)
          822                 }
          823                 _, err = gcsAfs.Stat(bDir)
          824                 if err != nil {
          825                         t.Fatal(err)
          826                 }
          827 
          828                 err = gcsAfs.RemoveAll(aDir)
          829                 if err != nil {
          830                         t.Fatalf("failed to remove the folder %s with error: %s", aDir, err)
          831                 }
          832 
          833                 _, err = gcsAfs.Stat(aDir)
          834                 if err == nil {
          835                         t.Fatalf("folder %s wasn't removed", aDir)
          836                 }
          837         })
          838 }