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  }