Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Features/general repo helper #1

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions generic_repository/generic_item.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package generic_repository

type GenericItemInterface interface {
GetId() string
SetId(id string)
GetSerializedItem() ([]byte, error)
SetItem(serializedItem []byte) error
Clone() *GenericItemInterface
}
104 changes: 104 additions & 0 deletions generic_repository/generic_leveldb_repo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package generic_repository

import (
"errors"

"github.com/it-chain/leveldb-wrapper"
)

var NoDataError string = "NoDataError"
var AlreadyDataError string = "NoDataError"
type GenericLevelDBRepository struct {
leveldb *leveldbwrapper.DB
}

func NewGenericLevelDBRepository(path string) *GenericLevelDBRepository {
db := leveldbwrapper.CreateNewDB(path)
db.Open()
return &GenericLevelDBRepository{
leveldb: db,
}
}

func (gr GenericLevelDBRepository) Insert(item GenericItemInterface) error{
if item.GetId() == "" {
return errors.New("item ID is empty")
}

b, err := gr.leveldb.Get([]byte(item.GetId()))
if len(b) != 0 {
return errors.New(AlreadyDataError)
}

b, err = item.GetSerializedItem()
if err != nil {
return err
}
if err = gr.leveldb.Put([]byte(item.GetId()), b, true); err != nil {
return err
}

return nil
}

func (gr GenericLevelDBRepository) Update(item GenericItemInterface) error {
oldItem := item.Clone()
err := gr.FindById(oldItem, item.GetId())
if err != nil {
return err
}
b, err := item.GetSerializedItem()
if err != nil {
return err
}
err = gr.leveldb.Put([]byte(item.GetId()), b, true)
if err != nil {
return err
}
return nil
}

func (gr GenericLevelDBRepository) FindById(receiver *GenericItemInterface, id string) error {
b, err := gr.leveldb.Get([]byte(id))
if err != nil {
return err
}
if len(b) == 0 {
return errors.New(NoDataError)
}
err = (*receiver).SetItem(b)
if err != nil {
return err
}

return nil
}

func (gr GenericLevelDBRepository) FindAll(receiverType GenericItemInterface) ([]*GenericItemInterface, error) {
iter := gr.leveldb.GetIteratorWithPrefix([]byte(""))
genericItems := []*GenericItemInterface{}
for iter.Next() {
if len(iter.Value()) == 0{
continue
}
cloneData := receiverType.Clone()
(*cloneData).SetId(string(iter.Key()))
err := (*cloneData).SetItem(iter.Value())

if err != nil {
return nil, err
}

genericItems = append(genericItems, cloneData)
}

return genericItems, nil
}

func (gr GenericLevelDBRepository) Delete(item GenericItemInterface) error {
return gr.leveldb.Delete([]byte(item.GetId()), true)
}

func (gr GenericLevelDBRepository) Close () {
gr.leveldb.Close()
}
249 changes: 249 additions & 0 deletions generic_repository/generic_leveldb_repo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
package generic_repository

import (
"testing"
"encoding/json"
"fmt"
"github.com/stretchr/testify/assert"
"os"
)

//setting data for testing
type FooItem struct {
Id string
Data1 string
Data2 int
Data3 float32
}

func (f FooItem) GetId() string {
return f.Id
}

func (f FooItem) SetId(id string) {
f.Id = id
}

func (f FooItem) GetSerializedItem() ([]byte, error) {
data, err := json.Marshal(f)
if err != nil {
panic(fmt.Sprintf("Error encoding : %s", err))
}
return data, nil
}

func (f *FooItem) SetItem(serializedItem []byte) error {
err := json.Unmarshal(serializedItem, f)
if err != nil {
panic(fmt.Sprintf("Error decoding : %s", err))
}
return nil
}

func (f FooItem) Clone() *GenericItemInterface {
var cloneInterface GenericItemInterface = &f
return &cloneInterface
}

func Deserialize(serializedBytes []byte, object interface{}) error {
if len(serializedBytes) == 0 {
return nil
}
err := json.Unmarshal(serializedBytes, object)
if err != nil {
panic(fmt.Sprintf("Error decoding : %s", err))
}
return err
}
func Serialize(object interface{}) ([]byte, error) {
data, err := json.Marshal(object)
if err != nil {
panic(fmt.Sprintf("Error encoding : %s", err))
}
return data, nil
}

func newRepo() *GenericLevelDBRepository {
path := "test_db_path"
repo := NewGenericLevelDBRepository(path)
return repo
}


//testing
func TestNewGenericLevelDBRepository(t *testing.T) {
path := "test_db_path"
defer os.RemoveAll(path)
repo := NewGenericLevelDBRepository(path)
defer repo.Close()
assert.DirExists(t,path)
}

func TestGenericLevelDBRepository_Insert(t *testing.T) {
path := "test_db_path"
r := newRepo()
defer os.RemoveAll(path)
defer r.Close()
inputItem := &FooItem{
Id: "first",
Data1: "data1",
Data2: 2,
Data3: 3,
}

//case 1 not exist data
err := r.Insert(inputItem)
assert.NoError(t,err)

data, err := r.leveldb.Get([]byte(inputItem.Id))
readItem := &FooItem{}
err = Deserialize(data,readItem)
assert.NoError(t,err)

assert.Equal(t,inputItem.Id,readItem.Id)
assert.Equal(t,inputItem.Data1,readItem.Data1)
assert.Equal(t,inputItem.Data2,readItem.Data2)
assert.Equal(t,inputItem.Data3,readItem.Data3)

//case 2 already exist data
err = r.Insert(inputItem)
assert.EqualError(t,err,AlreadyDataError)

os.RemoveAll(path)
}

func TestGenericLevelDBRepository_Update(t *testing.T) {
path := "test_db_path"
r := newRepo()
defer os.RemoveAll(path)
defer r.Close()

//case 1 data is exist
inputItem := &FooItem{
Id: "first",
Data1: "data1",
Data2: 2,
Data3: 3,
}
b,err := Serialize(inputItem)
assert.NoError(t,err)
err = r.leveldb.Put([]byte(inputItem.Id),b,true)
assert.NoError(t,err)
inputItem.Data1="updated"
err = r.Update(inputItem)
assert.NoError(t,err)
data, err := r.leveldb.Get([]byte(inputItem.Id))
readItem := &FooItem{}
err = Deserialize(data,readItem)
assert.NoError(t,err)
assert.Equal(t,"updated",inputItem.Data1)

//case 2 data is not exist
inputItem.Id = "notExistId"
err = r.Update(inputItem)
assert.EqualError(t,err,NoDataError)

}

func TestGenericLevelDBRepository_FindAll(t *testing.T) {

path := "test_db_path"
r := newRepo()
defer os.RemoveAll(path)
defer r.Close()

inputItem1 := &FooItem{
Id: "first",
Data1: "data1",
Data2: 2,
Data3: 3,
}
inputItem2 := &FooItem{
Id: "second",
Data1: "data1",
Data2: 2,
Data3: 3,
}
inputItem3 := &FooItem{
Id: "third",
Data1: "data1",
Data2: 2,
Data3: 3,
}

err := r.Insert(inputItem1)
assert.NoError(t, err)

err = r.Insert(inputItem2)
assert.NoError(t, err)

err = r.Insert(inputItem3)
assert.NoError(t, err)


readDatas, err := r.FindAll(&FooItem{})
assert.NoError(t, err)


assert.Equal(t,(*readDatas[0]).GetId(),inputItem1.GetId())
get , err := (*readDatas[0]).GetSerializedItem()
assert.NoError(t,err)
inputSerial, err := inputItem1.GetSerializedItem()
assert.NoError(t,err)
assert.Equal(t,get,inputSerial)

assert.Equal(t,(*readDatas[1]).GetId(),inputItem2.GetId())
get , err = (*readDatas[1]).GetSerializedItem()
assert.NoError(t,err)
inputSerial, err = inputItem2.GetSerializedItem()
assert.NoError(t,err)
assert.Equal(t,get,inputSerial)

assert.Equal(t,(*readDatas[2]).GetId(),inputItem3.GetId())
get , err = (*readDatas[2]).GetSerializedItem()
assert.NoError(t,err)
inputSerial, err = inputItem3.GetSerializedItem()
assert.NoError(t,err)
assert.Equal(t,get,inputSerial)

}

func TestGenericLevelDBRepository_Delete(t *testing.T) {
path := "test_db_path"
r := newRepo()
defer os.RemoveAll(path)
defer r.Close()


inputItem := &FooItem{
Id: "first",
Data1: "data1",
Data2: 2,
Data3: 3,
}
b,err := Serialize(inputItem)
assert.NoError(t,err)
err = r.leveldb.Put([]byte(inputItem.Id),b,true)
assert.NoError(t,err)


err = r.Delete(inputItem)
assert.NoError(t,err)

data,err := r.leveldb.Get([]byte(inputItem.Id))
assert.NoError(t,err)
assert.Nil(t,data)
}













9 changes: 9 additions & 0 deletions generic_repository/generic_repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package generic_repository

type GenericRepositoryInterface interface {
Insert(item GenericItemInterface) error
Update(item GenericItemInterface) error
FindById(receiver *GenericItemInterface, id string) (error)
FindAll(receiverType GenericItemInterface) ([]*GenericItemInterface ,error)
Delete(item GenericItemInterface) error
}
6 changes: 4 additions & 2 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import:
- leveldb/iterator
- leveldb/opt
- leveldb/util
- package: github.com/jinzhu/copier
testImport:
- package: github.com/stretchr/testify
version: v1.2.1
Expand Down
Loading