github.com/MontFerret/ferret@v0.18.0/pkg/stdlib/io/fs/write_test.go (about) 1 package fs_test 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "testing" 8 9 "github.com/MontFerret/ferret/pkg/runtime/core" 10 "github.com/MontFerret/ferret/pkg/runtime/values" 11 "github.com/MontFerret/ferret/pkg/stdlib/io/fs" 12 13 . "github.com/smartystreets/goconvey/convey" 14 ) 15 16 func TestWrite(t *testing.T) { 17 18 Convey("Invalid arguments", t, func() { 19 20 path := values.NewString("path.txt") 21 data := values.NewBinary([]byte("3timeslazy")) 22 params := values.NewObjectWith( 23 values.NewObjectProperty("mode", values.NewString("w")), 24 ) 25 someInt := values.NewInt(0) 26 27 Convey("All arguments", func() { 28 29 testCases := []struct { 30 Name string 31 Args []core.Value 32 }{ 33 { 34 Name: "Arguments Number: No arguments passed", 35 Args: []core.Value{}, 36 }, 37 { 38 Name: "Arguments Number: Only `path` passed", 39 Args: []core.Value{path}, 40 }, 41 { 42 Name: "Arguments Number: more than 3 arguments passed", 43 Args: []core.Value{path, data, params, someInt}, 44 }, 45 { 46 Name: "Arguments Type: `path` not a string", 47 Args: []core.Value{someInt}, 48 }, 49 { 50 Name: "Arguments Type: `params` not an object", 51 Args: []core.Value{path, data, someInt}, 52 }, 53 } 54 55 for _, tC := range testCases { 56 tC := tC 57 58 Convey(tC.Name, func() { 59 none, err := fs.Write(context.Background(), tC.Args...) 60 So(err, ShouldBeError) 61 So(none, ShouldResemble, values.None) 62 }) 63 } 64 }) 65 66 Convey("Argument `params`", func() { 67 68 Convey("Key `mode`", func() { 69 70 testCases := []core.Value{ 71 // empty mode string 72 values.NewString(""), 73 74 // `a` and `w` cannot be used together 75 values.NewString("aw"), 76 77 // two equal letters 78 values.NewString("ww"), 79 80 // mode string is too long 81 values.NewString("awx"), 82 83 // the `x` mode only 84 values.NewString("x"), 85 86 // mode is not a string 87 values.NewInt(1), 88 } 89 90 for _, mode := range testCases { 91 mode := mode 92 name := fmt.Sprintf("mode `%s`", mode) 93 94 Convey(name, func() { 95 params := values.NewObjectWith( 96 values.NewObjectProperty("mode", mode), 97 ) 98 99 none, err := fs.Write(context.Background(), path, data, params) 100 So(err, ShouldBeError) 101 So(none, ShouldResemble, values.None) 102 }) 103 } 104 }) 105 }) 106 }) 107 108 Convey("Error cases", t, func() { 109 110 Convey("Write into existing file with `x` mode", func() { 111 file, delFile := tempFile() 112 defer delFile() 113 114 none, err := fs.Write( 115 context.Background(), 116 values.NewString(file.Name()), 117 values.NewBinary([]byte("3timeslazy")), 118 values.NewObjectWith( 119 values.NewObjectProperty("mode", values.NewString("wx")), 120 ), 121 ) 122 So(none, ShouldResemble, values.None) 123 So(err, ShouldBeError) 124 }) 125 126 Convey("Filepath is empty", func() { 127 none, err := fs.Write( 128 context.Background(), 129 values.NewString(""), 130 values.NewBinary([]byte("3timeslazy")), 131 ) 132 So(none, ShouldResemble, values.None) 133 So(err, ShouldBeError) 134 }) 135 }) 136 137 Convey("Success cases", t, func() { 138 139 Convey("Mode `w` should truncate file", func() { 140 file, delFile := tempFile() 141 defer delFile() 142 143 data := values.NewBinary([]byte("3timeslazy")) 144 fpath := values.NewString(file.Name()) 145 params := values.NewObjectWith( 146 values.NewObjectProperty("mode", values.NewString("w")), 147 ) 148 149 for _ = range [2]struct{}{} { 150 // at first iteration check that `Write` creates file and writes `data`. 151 // At second iteration check that `Write` truncates the file and 152 // writes `data` again 153 154 _, err := fs.Write(context.Background(), fpath, data, params) 155 So(err, ShouldBeNil) 156 157 read, err := fs.Read(context.Background(), fpath) 158 So(err, ShouldBeNil) 159 So(read, ShouldResemble, data) 160 } 161 }) 162 163 Convey("Mode `a` should append into file", func() { 164 file, delFile := tempFile() 165 defer delFile() 166 167 data := values.NewBinary([]byte("3timeslazy")) 168 fpath := values.NewString(file.Name()) 169 params := values.NewObjectWith( 170 values.NewObjectProperty("mode", values.NewString("a")), 171 ) 172 173 for i := range [2]struct{}{} { 174 // at first iteration check that `Write` creates file and appends `data` 175 // into it. 176 // At second iteration check that `Write` appends `data` into file 177 // one more time using bytes.Repeat 178 179 _, err := fs.Write(context.Background(), fpath, data, params) 180 So(err, ShouldBeNil) 181 182 read, err := fs.Read(context.Background(), fpath) 183 So(err, ShouldBeNil) 184 185 readBytes := read.Unwrap().([]byte) 186 So(readBytes, ShouldResemble, bytes.Repeat(data, i+1)) 187 } 188 }) 189 }) 190 }