Skip to content

Commit

Permalink
Merge pull request #34 from keep-network/max-file-length
Browse files Browse the repository at this point in the history
Max file length of 128 characters, moveAll error handling improvements
  • Loading branch information
lukasz-zimnoch authored May 4, 2020
2 parents 07d2a79 + 892c8da commit fc13282
Show file tree
Hide file tree
Showing 2 changed files with 195 additions and 28 deletions.
75 changes: 58 additions & 17 deletions pkg/persistence/disk_persistence.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
const (
currentDir = "current"
archiveDir = "archive"

maxFileNameLength = 128
)

// NewDiskHandle creates on-disk data persistence handle
Expand Down Expand Up @@ -38,20 +40,44 @@ type diskPersistence struct {
}

func (ds *diskPersistence) Save(data []byte, dirName, fileName string) error {
if len(dirName) > maxFileNameLength {
return fmt.Errorf(
"the maximum directory name length of [%v] exceeded for [%v]",
maxFileNameLength,
dirName,
)
}

if len(fileName) > maxFileNameLength {
return fmt.Errorf(
"the maximum file name length of [%v] exceeded for [%v]",
maxFileNameLength,
fileName,
)
}

dirPath := ds.getStorageCurrentDirPath()
err := createDir(dirPath, dirName)
if err != nil {
return err
}

return write(fmt.Sprintf("%s/%s%s", dirPath, dirName, fileName), data)
return write(fmt.Sprintf("%s/%s/%s", dirPath, dirName, fileName), data)
}

func (ds *diskPersistence) ReadAll() (<-chan DataDescriptor, <-chan error) {
return readAll(ds.getStorageCurrentDirPath())
}

func (ds *diskPersistence) Archive(directory string) error {
if len(directory) > maxFileNameLength {
return fmt.Errorf(
"the maximum directory name length of [%v] exceeded for [%v]",
maxFileNameLength,
directory,
)
}

from := fmt.Sprintf("%s/%s/%s", ds.dataDir, currentDir, directory)
to := fmt.Sprintf("%s/%s/%s", ds.dataDir, archiveDir, directory)

Expand Down Expand Up @@ -184,26 +210,41 @@ func readAll(directoryPath string) (<-chan DataDescriptor, <-chan error) {
}

func moveAll(directoryFromPath, directoryToPath string) error {
if _, err := os.Stat(directoryToPath); !os.IsNotExist(err) {
files, _ := ioutil.ReadDir(directoryFromPath)
for _, file := range files {
from := fmt.Sprintf("%s/%s", directoryFromPath, file.Name())
to := fmt.Sprintf("%s/%s", directoryToPath, file.Name())
err := os.Rename(from, to)
if err != nil {
return err
}
}
err = os.RemoveAll(directoryFromPath)
if err != nil {
return fmt.Errorf("error occurred while removing archived dir: [%v]", err)
}
} else {
_, err := os.Stat(directoryToPath)

// target directory does not exist, we can move everything
if os.IsNotExist(err) {
err := os.Rename(directoryFromPath, directoryToPath)
if err != nil {
return fmt.Errorf("error occurred while moving a dir: [%v]", err)
}

return nil
}

// unexpected error occurred while checking target directory existence,
// returning
if err != nil {
return fmt.Errorf("could not stat target directory: [%v]", err)
}

// target directory does exit, we need to append files
files, err := ioutil.ReadDir(directoryFromPath)
if err != nil {
return fmt.Errorf("could not read directory [%v]: [%v]", directoryFromPath, err)
}
for _, file := range files {
from := fmt.Sprintf("%s/%s", directoryFromPath, file.Name())
to := fmt.Sprintf("%s/%s", directoryToPath, file.Name())
err := os.Rename(from, to)
if err != nil {
return err
}
}
err = os.RemoveAll(directoryFromPath)
if err != nil {
return fmt.Errorf("error occurred while removing archived dir: [%v]", err)
}

return nil
}
}
148 changes: 137 additions & 11 deletions pkg/persistence/disk_persistence_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package persistence

import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
Expand All @@ -18,37 +17,97 @@ var (
dirArchive = "archive"

dirName1 = "0x424242"
fileName11 = "/file11"
fileName12 = "/file12"
fileName11 = "file11"
fileName12 = "file12"

dirName2 = "0x777777"
fileName21 = "/file21"
fileName21 = "file21"

pathToCurrent = fmt.Sprintf("%s/%s", dataDir, dirCurrent)
pathToArchive = fmt.Sprintf("%s/%s", dataDir, dirArchive)

errExpectedRead = errors.New("cannot read from the storage directory: ")
errExpectedWrite = errors.New("cannot write to the storage directory: ")
errExpectedRead = fmt.Errorf("cannot read from the storage directory: ")
errExpectedWrite = fmt.Errorf("cannot write to the storage directory: ")

// 128 characters
maxAllowedName = "0cc2abf49e067b3bede8426d9369c6952655d33629f44610536445c00c974c7e2740dfac967dbfceeeec0af88cd48a5d8c1c167df93cad1b8301a4a204c9f235"
// 129 charactes
notAllowedName = "0cc2abf49e067b3bede8426d9369c6952655d33629f44610536445c00c974c7e2740dfac967dbfceeeec0af88cd48a5d8c1c167df93cad1b8301a4a204c9f235a"

errDirectoryNameLength = fmt.Errorf("the maximum directory name length of [128] exceeded for [%v]", notAllowedName)
errFileNameLength = fmt.Errorf("the maximum file name length of [128] exceeded for [%v]", notAllowedName)
)

func TestMain(m *testing.M) {
code := m.Run()
func cleanup() {
os.RemoveAll(pathToCurrent)
os.RemoveAll(pathToArchive)
os.Exit(code)
}

func TestDiskPersistence_Save(t *testing.T) {
diskPersistence, _ := NewDiskHandle(dataDir)
bytesToTest := []byte{115, 111, 109, 101, 10}

diskPersistence.Save(bytesToTest, dirName1, fileName11)
err := diskPersistence.Save(bytesToTest, dirName1, fileName11)
if err != nil {
t.Fatal(err)
}

pathToFile := fmt.Sprintf("%s/%s%s", pathToCurrent, dirName1, fileName11)
pathToFile := fmt.Sprintf("%s/%s/%s", pathToCurrent, dirName1, fileName11)

if _, err := os.Stat(pathToFile); os.IsNotExist(err) {
t.Fatalf("file [%+v] was supposed to be created", pathToFile)
}

cleanup()
}

func TestDiskPersistence_SaveMaxAllowed(t *testing.T) {
diskPersistence, _ := NewDiskHandle(dataDir)
bytesToTest := []byte{115, 111, 109, 101, 10}

err := diskPersistence.Save(bytesToTest, maxAllowedName, maxAllowedName)
if err != nil {
t.Fatal(err)
}

pathToFile := fmt.Sprintf("%s/%s/%s", pathToCurrent, maxAllowedName, maxAllowedName)

if _, err := os.Stat(pathToFile); os.IsNotExist(err) {
t.Fatalf("file [%+v] was supposed to be created", pathToFile)
}

cleanup()
}

func TestDiskPersistence_RefuseSave(t *testing.T) {
diskPersistence, _ := NewDiskHandle(dataDir)
bytesToTest := []byte{115, 111, 109, 101, 10}

err := diskPersistence.Save(bytesToTest, notAllowedName, fileName11)
if err == nil {
t.Fatalf("expected error")
}
if errDirectoryNameLength.Error() != err.Error() {
t.Fatalf(
"unexpected error returned\nexpected: [%v]\nactual: [%v]",
errDirectoryNameLength.Error(),
err.Error(),
)
}

err = diskPersistence.Save(bytesToTest, dirName1, notAllowedName)
if err == nil {
t.Fatalf("expected error")
}
if errFileNameLength.Error() != err.Error() {
t.Fatalf(
"unexpected error returned\nexpected: [%v]\nactual: [%v]",
errFileNameLength.Error(),
err.Error(),
)
}

cleanup()
}

func TestDiskPersistence_StoragePermission(t *testing.T) {
Expand All @@ -71,6 +130,8 @@ func TestDiskPersistence_StoragePermission(t *testing.T) {
if err == nil || !strings.Contains(err.Error(), errExpectedWrite.Error()) {
t.Fatalf("error on write was supposed to be returned")
}

cleanup()
}

func TestDiskPersistence_ReadAll(t *testing.T) {
Expand Down Expand Up @@ -134,6 +195,8 @@ func TestDiskPersistence_ReadAll(t *testing.T) {
)
}
}

cleanup()
}

func TestDiskPersistence_Archive(t *testing.T) {
Expand Down Expand Up @@ -171,6 +234,68 @@ func TestDiskPersistence_Archive(t *testing.T) {
t.Fatalf("Dir [%+v] was supposed to be created", pathMoveTo)
}
}

cleanup()
}

func TestDiskPersistence_ArchiveMaxAllowed(t *testing.T) {
diskPersistence, _ := NewDiskHandle(dataDir)

pathMoveFrom := fmt.Sprintf("%s/%s", pathToCurrent, maxAllowedName)
pathMoveTo := fmt.Sprintf("%s/%s", pathToArchive, maxAllowedName)

bytesToTest := []byte{115, 111, 109, 101, 10}

diskPersistence.Save(bytesToTest, maxAllowedName, maxAllowedName)

if _, err := os.Stat(pathMoveFrom); os.IsNotExist(err) {
if err != nil {
t.Fatalf("Dir [%+v] was supposed to be created", pathMoveFrom)
}
}

if _, err := os.Stat(pathMoveTo); !os.IsNotExist(err) {
if err != nil {
t.Fatalf("Dir [%+v] was supposed to be empty", pathMoveTo)
}
}

err := diskPersistence.Archive(maxAllowedName)
if err != nil {
t.Fatal(err)
}

if _, err := os.Stat(pathMoveFrom); !os.IsNotExist(err) {
if err != nil {
t.Fatalf("Dir [%+v] was supposed to be moved", pathMoveFrom)
}
}

if _, err := os.Stat(pathMoveTo); os.IsNotExist(err) {
if err != nil {
t.Fatalf("Dir [%+v] was supposed to be created", pathMoveTo)
}
}

cleanup()
}

func TestDiskPersistence_RefuseArchive(t *testing.T) {
diskPersistence, _ := NewDiskHandle(dataDir)

err := diskPersistence.Archive(notAllowedName)
if err == nil {
t.Fatalf("expected error")
}
if errDirectoryNameLength.Error() != err.Error() {
t.Fatalf(
"unexpected error returned\nexpected: [%v]\nactual: [%v]",
errDirectoryNameLength.Error(),
err.Error(),
)
}

cleanup()
}

func TestDiskPersistence_AppendToArchive(t *testing.T) {
Expand Down Expand Up @@ -198,4 +323,5 @@ func TestDiskPersistence_AppendToArchive(t *testing.T) {
t.Fatalf("Number of all files was supposed to be [%+v]", 4)
}

cleanup()
}

0 comments on commit fc13282

Please sign in to comment.