-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Drop receiver from writeFile Signed-off-by: Atanas Dinov <[email protected]> * Extract writeFile to fileio package Signed-off-by: Atanas Dinov <[email protected]> * Restructure file writing Signed-off-by: Atanas Dinov <[email protected]> * Test file writing Signed-off-by: Atanas Dinov <[email protected]> * Extract copyFile to fileio package Signed-off-by: Atanas Dinov <[email protected]> * Test file copying Signed-off-by: Atanas Dinov <[email protected]> * Drop unused copy function Signed-off-by: Atanas Dinov <[email protected]> * Use temporary dir in tests Signed-off-by: Atanas Dinov <[email protected]> --------- Signed-off-by: Atanas Dinov <[email protected]>
- Loading branch information
1 parent
57878ba
commit d9780ce
Showing
6 changed files
with
217 additions
and
105 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package fileio | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"os" | ||
"text/template" | ||
) | ||
|
||
func WriteFile(filename string, contents string, templateData any) error { | ||
if templateData == nil { | ||
if err := os.WriteFile(filename, []byte(contents), os.ModePerm); err != nil { | ||
return fmt.Errorf("writing file: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
tmpl, err := template.New(filename).Parse(contents) | ||
if err != nil { | ||
return fmt.Errorf("parsing template: %w", err) | ||
} | ||
|
||
file, err := os.Create(filename) | ||
if err != nil { | ||
return fmt.Errorf("creating file: %w", err) | ||
} | ||
defer func() { | ||
_ = file.Close() | ||
}() | ||
|
||
if err = tmpl.Execute(file, templateData); err != nil { | ||
return fmt.Errorf("applying template: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func CopyFile(src string, dest string) error { | ||
sourceFile, err := os.Open(src) | ||
if err != nil { | ||
return fmt.Errorf("opening source file: %w", err) | ||
} | ||
defer func() { | ||
_ = sourceFile.Close() | ||
}() | ||
|
||
destFile, err := os.Create(dest) | ||
if err != nil { | ||
return fmt.Errorf("creating destination file: %w", err) | ||
} | ||
defer func() { | ||
_ = destFile.Close() | ||
}() | ||
|
||
if _, err = io.Copy(destFile, sourceFile); err != nil { | ||
return fmt.Errorf("copying file: %w", err) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package fileio | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestWriteFile(t *testing.T) { | ||
const tmpDirPrefix = "eib-write-file-test-" | ||
|
||
tmpDir, err := os.MkdirTemp("", tmpDirPrefix) | ||
require.NoError(t, err) | ||
defer os.RemoveAll(tmpDir) | ||
|
||
tests := []struct { | ||
name string | ||
filename string | ||
contents string | ||
templateData any | ||
expectedContents string | ||
expectedErr string | ||
}{ | ||
{ | ||
name: "Standard file is successfully written", | ||
filename: "standard", | ||
contents: "this is a non-templated file", | ||
expectedContents: "this is a non-templated file", | ||
}, | ||
{ | ||
name: "Templated file is successfully written", | ||
filename: "template", | ||
contents: "{{.Foo}} and {{.Bar}}", | ||
templateData: struct { | ||
Foo string | ||
Bar string | ||
}{ | ||
Foo: "ooF", | ||
Bar: "raB", | ||
}, | ||
expectedContents: "ooF and raB", | ||
}, | ||
{ | ||
name: "Templated file is not written due to invalid syntax", | ||
filename: "invalid-syntax", | ||
contents: "{{.Foo and ", | ||
templateData: struct{}{}, | ||
expectedErr: fmt.Sprintf("parsing template: template: %s/invalid-syntax:1: unclosed action", tmpDir), | ||
}, | ||
{ | ||
name: "Templated file is not written due to missing field", | ||
filename: "invalid-data", | ||
contents: "{{.Foo}} and {{.Bar}}", | ||
templateData: struct { | ||
Foo string | ||
}{ | ||
Foo: "ooF", | ||
}, | ||
expectedErr: fmt.Sprintf("applying template: template: %[1]s/invalid-data:1:15: "+ | ||
"executing \"%[1]s/invalid-data\" at <.Bar>: can't evaluate field Bar in type struct { Foo string }", tmpDir), | ||
}, | ||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
filename := filepath.Join(tmpDir, test.filename) | ||
|
||
err := WriteFile(filename, test.contents, test.templateData) | ||
|
||
if test.expectedErr != "" { | ||
assert.EqualError(t, err, test.expectedErr) | ||
} else { | ||
require.Nil(t, err) | ||
|
||
contents, err := os.ReadFile(filename) | ||
require.NoError(t, err) | ||
|
||
assert.Equal(t, test.expectedContents, string(contents)) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestCopyFile(t *testing.T) { | ||
const ( | ||
source = "file_io.go" // use the source code file as a valid input | ||
destDirPrefix = "eib-copy-file-test-" | ||
) | ||
|
||
tmpDir, err := os.MkdirTemp("", destDirPrefix) | ||
require.NoError(t, err) | ||
defer os.RemoveAll(tmpDir) | ||
|
||
tests := []struct { | ||
name string | ||
source string | ||
destination string | ||
expectedErr string | ||
}{ | ||
{ | ||
name: "Source file does not exist", | ||
source: "<missing>", | ||
expectedErr: "opening source file: open <missing>: no such file or directory", | ||
}, | ||
{ | ||
name: "Destination is an empty file", | ||
source: source, | ||
destination: "", | ||
expectedErr: "creating destination file: open : no such file or directory", | ||
}, | ||
{ | ||
name: "Destination is a directory", | ||
source: source, | ||
destination: tmpDir, | ||
expectedErr: fmt.Sprintf("creating destination file: open %s: is a directory", tmpDir), | ||
}, | ||
{ | ||
name: "File is successfully copied", | ||
source: source, | ||
destination: fmt.Sprintf("%s/copy.go", tmpDir), | ||
}, | ||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
err := CopyFile(test.source, test.destination) | ||
|
||
if test.expectedErr != "" { | ||
assert.EqualError(t, err, test.expectedErr) | ||
} else { | ||
require.Nil(t, err) | ||
|
||
src, err := os.ReadFile(test.source) | ||
require.NoError(t, err) | ||
|
||
dest, err := os.ReadFile(test.destination) | ||
require.NoError(t, err) | ||
|
||
assert.Equal(t, src, dest) | ||
} | ||
}) | ||
} | ||
} |