Merge pull request #8 from p2p-org/feat/client-skeleton

feat: client skeleton
This commit is contained in:
Andrew Zavgorodny 2020-07-30 15:08:25 +03:00 committed by GitHub
commit 6cb0f59656
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 1062 additions and 87 deletions

9
Makefile Normal file
View File

@ -0,0 +1,9 @@
test:
@echo "Testing Go packages..."
@go test ./... -cover
mocks:
@echo "Regenerate mocks..."
@go generate ./...
.PHONY: mocks

153
client/client.go Normal file
View File

@ -0,0 +1,153 @@
package client
import (
"context"
"encoding/json"
"fmt"
"log"
"path/filepath"
"time"
"github.com/p2p-org/dc4bc/qr"
"github.com/p2p-org/dc4bc/storage"
)
const (
pollingPeriod = time.Second
QrCodesDir = "/tmp"
)
type Client struct {
ctx context.Context
fsm interface{}
state State
storage storage.Storage
qrProcessor qr.Processor
}
func NewClient(
ctx context.Context,
fsm interface{},
state State,
storage storage.Storage,
qrProcessor qr.Processor,
) (*Client, error) {
return &Client{
ctx: ctx,
fsm: fsm,
state: state,
storage: storage,
qrProcessor: qrProcessor,
}, nil
}
func (c *Client) SendMessage(message storage.Message) error {
if _, err := c.storage.Send(message); err != nil {
return fmt.Errorf("failed to post message: %w", err)
}
return nil
}
func (c *Client) Poll() {
tk := time.NewTicker(pollingPeriod)
for {
select {
case <-tk.C:
offset, err := c.state.LoadOffset()
if err != nil {
panic(err)
}
messages, err := c.storage.GetMessages(offset)
if err != nil {
panic(err)
}
for _, message := range messages {
log.Println("Message:", message)
// Feed the message to the FSM, get a possibly empty operation.
var operation *Operation
// I.e., if FSM returned an Operation for us.
if operation != nil {
if err := c.state.PutOperation(operation); err != nil {
panic(err)
}
}
if err := c.state.SaveOffset(message.Offset); err != nil {
panic(err)
}
if err := c.state.SaveFSM(c.fsm); err != nil {
panic(err)
}
}
case <-c.ctx.Done():
return
}
}
}
func (c *Client) GetOperations() (map[string]*Operation, error) {
return c.state.GetOperations()
}
// GetOperationQRPath returns a path to the image with the QR generated
// for the specified operation. It is supposed that the user will open
// this file herself.
func (c *Client) GetOperationQRPath(operationID string) (string, error) {
operation, err := c.state.GetOperationByID(operationID)
if err != nil {
return "", fmt.Errorf("failed to get operation: %w", err)
}
operationJSON, err := json.Marshal(operation)
if err != nil {
return "", fmt.Errorf("failed to marshal operation: %w", err)
}
operationQRPath := filepath.Join(QrCodesDir, operationID)
if err := c.qrProcessor.WriteQR(operationQRPath, operationJSON); err != nil {
return "", fmt.Errorf("failed to WriteQR: %w", err)
}
return operationQRPath, nil
}
// ReadProcessedOperation reads the processed operation from camera, checks that
// the processed operation has its unprocessed counterpart in our state,
// posts a Message to the storage and deletes the operation from our state.
func (c *Client) ReadProcessedOperation() error {
bz, err := c.qrProcessor.ReadQR()
if err != nil {
return fmt.Errorf("failed to ReadQR: %s", err)
}
var operation Operation
if err = json.Unmarshal(bz, &operation); err != nil {
return fmt.Errorf("failed to unmarshal processed operation")
}
storedOperation, err := c.state.GetOperationByID(operation.ID)
if err != nil {
return fmt.Errorf("failed to find matching operation: %w", err)
}
if err := storedOperation.Check(&operation); err != nil {
return fmt.Errorf("processed operation does not match stored operation: %w", err)
}
var message storage.Message
if _, err := c.storage.Send(message); err != nil {
return fmt.Errorf("failed to post message: %w", err)
}
if err := c.state.DeleteOperation(operation.ID); err != nil {
return fmt.Errorf("failed to DeleteOperation: %w", err)
}
return nil
}

132
client/client_test.go Normal file
View File

@ -0,0 +1,132 @@
package client_test
import (
"context"
"encoding/json"
"errors"
"os"
"path/filepath"
"testing"
"time"
"github.com/p2p-org/dc4bc/mocks/qrMocks"
"github.com/p2p-org/dc4bc/client"
"github.com/golang/mock/gomock"
"github.com/p2p-org/dc4bc/mocks/clientMocks"
"github.com/p2p-org/dc4bc/mocks/storageMocks"
"github.com/stretchr/testify/require"
)
func TestClient_GetOperationsList(t *testing.T) {
var (
ctx = context.Background()
req = require.New(t)
ctrl = gomock.NewController(t)
)
defer ctrl.Finish()
state := clientMocks.NewMockState(ctrl)
storage := storageMocks.NewMockStorage(ctrl)
qrProcessor := qrMocks.NewMockProcessor(ctrl)
clt, err := client.NewClient(ctx, nil, state, storage, qrProcessor)
req.NoError(err)
state.EXPECT().GetOperations().Times(1).Return(map[string]*client.Operation{}, nil)
operations, err := clt.GetOperations()
req.NoError(err)
req.Len(operations, 0)
operation := &client.Operation{
ID: "operation_id",
Type: client.DKGCommits,
Payload: []byte("operation_payload"),
CreatedAt: time.Now(),
}
state.EXPECT().GetOperations().Times(1).Return(
map[string]*client.Operation{operation.ID: operation}, nil)
operations, err = clt.GetOperations()
req.NoError(err)
req.Len(operations, 1)
req.Equal(operation, operations[operation.ID])
}
func TestClient_GetOperationQRPath(t *testing.T) {
var (
ctx = context.Background()
req = require.New(t)
ctrl = gomock.NewController(t)
)
defer ctrl.Finish()
state := clientMocks.NewMockState(ctrl)
storage := storageMocks.NewMockStorage(ctrl)
qrProcessor := qrMocks.NewMockProcessor(ctrl)
clt, err := client.NewClient(ctx, nil, state, storage, qrProcessor)
req.NoError(err)
operation := &client.Operation{
ID: "operation_id",
Type: client.DKGCommits,
Payload: []byte("operation_payload"),
CreatedAt: time.Now(),
}
var expectedQrPath = filepath.Join(client.QrCodesDir, operation.ID)
defer os.Remove(expectedQrPath)
state.EXPECT().GetOperationByID(operation.ID).Times(1).Return(
nil, errors.New(""))
_, err = clt.GetOperationQRPath(operation.ID)
req.Error(err)
state.EXPECT().GetOperationByID(operation.ID).Times(1).Return(
operation, nil)
qrProcessor.EXPECT().WriteQR(expectedQrPath, gomock.Any()).Times(1).Return(nil)
qrPath, err := clt.GetOperationQRPath(operation.ID)
req.NoError(err)
req.Equal(expectedQrPath, qrPath)
}
func TestClient_ReadProcessedOperation(t *testing.T) {
var (
ctx = context.Background()
req = require.New(t)
ctrl = gomock.NewController(t)
)
defer ctrl.Finish()
state := clientMocks.NewMockState(ctrl)
storage := storageMocks.NewMockStorage(ctrl)
qrProcessor := qrMocks.NewMockProcessor(ctrl)
clt, err := client.NewClient(ctx, nil, state, storage, qrProcessor)
req.NoError(err)
operation := &client.Operation{
ID: "operation_id",
Type: client.DKGCommits,
Payload: []byte("operation_payload"),
Result: []byte("operation_result"),
CreatedAt: time.Now(),
}
processedOperation := &client.Operation{
ID: "operation_id",
Type: client.DKGCommits,
Payload: []byte("operation_payload"),
Result: []byte("operation_result"),
CreatedAt: time.Now(),
}
processedOperationBz, err := json.Marshal(processedOperation)
req.NoError(err)
qrProcessor.EXPECT().ReadQR().Return(processedOperationBz, nil).Times(1)
state.EXPECT().GetOperationByID(processedOperation.ID).Times(1).Return(operation, nil)
state.EXPECT().DeleteOperation(processedOperation.ID).Times(1)
storage.EXPECT().Send(gomock.Any()).Times(1)
err = clt.ReadProcessedOperation()
req.NoError(err)
}

184
client/state.go Normal file
View File

@ -0,0 +1,184 @@
package client
import (
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"sync"
"github.com/syndtr/goleveldb/leveldb"
)
const (
offsetKey = "offset"
operationsKey = "operations"
)
type State interface {
SaveOffset(uint64) error
LoadOffset() (uint64, error)
SaveFSM(interface{}) error
LoadFSM() (interface{}, error)
PutOperation(operation *Operation) error
DeleteOperation(operationID string) error
GetOperations() (map[string]*Operation, error)
GetOperationByID(operationID string) (*Operation, error)
}
type LevelDBState struct {
sync.Mutex
stateDb *leveldb.DB
}
func NewLevelDBState(stateDbPath string) (State, error) {
db, err := leveldb.OpenFile(stateDbPath, nil)
if err != nil {
return nil, fmt.Errorf("failed to open stateDB: %w", err)
}
state := &LevelDBState{
stateDb: db,
}
if err := state.initKey(operationsKey, map[string]*Operation{}); err != nil {
return nil, fmt.Errorf("failed to init %s storage: %w", operationsKey, err)
}
return state, nil
}
func (s *LevelDBState) initKey(key string, data interface{}) error {
if _, err := s.stateDb.Get([]byte(key), nil); err != nil {
operationsBz, err := json.Marshal(data)
if err != nil {
return fmt.Errorf("failed to marshal storage structure: %w", err)
}
err = s.stateDb.Put([]byte(key), operationsBz, nil)
if err != nil {
return fmt.Errorf("failed to init state: %w", err)
}
}
return nil
}
func (s *LevelDBState) SaveOffset(offset uint64) error {
bz := make([]byte, 8)
binary.LittleEndian.PutUint64(bz, offset)
if err := s.stateDb.Put([]byte(offsetKey), bz, nil); err != nil {
return fmt.Errorf("failed to set offset: %w", err)
}
return nil
}
func (s *LevelDBState) LoadOffset() (uint64, error) {
bz, err := s.stateDb.Get([]byte(offsetKey), nil)
if err != nil {
return 0, fmt.Errorf("failed to read offset: %w", err)
}
offset := binary.LittleEndian.Uint64(bz)
return offset, nil
}
// TODO: implement.
func (s *LevelDBState) SaveFSM(interface{}) error {
return nil
}
// TODO: implement.
func (s *LevelDBState) LoadFSM() (interface{}, error) {
return nil, nil
}
func (s *LevelDBState) PutOperation(operation *Operation) error {
s.Lock()
defer s.Unlock()
operations, err := s.getOperations()
if err != nil {
return fmt.Errorf("failed to getOperations: %w", err)
}
if _, ok := operations[operation.ID]; ok {
return fmt.Errorf("operation %s already exists", operation.ID)
}
operations[operation.ID] = operation
operationsJSON, err := json.Marshal(operations)
if err != nil {
return fmt.Errorf("failed to marshal operations: %w", err)
}
if err := s.stateDb.Put([]byte(operationsKey), operationsJSON, nil); err != nil {
return fmt.Errorf("failed to put operations: %w", err)
}
return nil
}
func (s *LevelDBState) DeleteOperation(operationID string) error {
s.Lock()
defer s.Unlock()
operations, err := s.getOperations()
if err != nil {
return fmt.Errorf("failed to getOperations: %w", err)
}
delete(operations, operationID)
operationsJSON, err := json.Marshal(operations)
if err != nil {
return fmt.Errorf("failed to marshal operations: %w", err)
}
if err := s.stateDb.Put([]byte(operationsKey), operationsJSON, nil); err != nil {
return fmt.Errorf("failed to put operations: %w", err)
}
return nil
}
func (s *LevelDBState) GetOperations() (map[string]*Operation, error) {
s.Lock()
defer s.Unlock()
return s.getOperations()
}
func (s *LevelDBState) GetOperationByID(operationID string) (*Operation, error) {
s.Lock()
defer s.Unlock()
operations, err := s.getOperations()
if err != nil {
return nil, fmt.Errorf("failed to getOperations: %w", err)
}
operation, ok := operations[operationID]
if !ok {
return nil, errors.New("operation not found")
}
return operation, nil
}
func (s *LevelDBState) getOperations() (map[string]*Operation, error) {
bz, err := s.stateDb.Get([]byte(operationsKey), nil)
if err != nil {
return nil, fmt.Errorf("failed to get Operations (key: %s): %w", operationsKey, err)
}
var operations map[string]*Operation
if err := json.Unmarshal(bz, &operations); err != nil {
return nil, fmt.Errorf("failed to unmarshal Operations: %w", err)
}
return operations, nil
}

119
client/state_test.go Normal file
View File

@ -0,0 +1,119 @@
package client_test
import (
"os"
"testing"
"time"
"github.com/p2p-org/dc4bc/client"
"github.com/stretchr/testify/require"
)
func TestLevelDBState_SaveOffset(t *testing.T) {
var (
req = require.New(t)
dbPath = "/tmp/dc4bc_test_SaveOffset"
)
defer os.RemoveAll(dbPath)
stg, err := client.NewLevelDBState(dbPath)
req.NoError(err)
var offset uint64 = 1
err = stg.SaveOffset(offset)
req.NoError(err)
loadedOffset, err := stg.LoadOffset()
req.NoError(err)
req.Equal(offset, loadedOffset)
}
func TestLevelDBState_PutOperation(t *testing.T) {
var (
req = require.New(t)
dbPath = "/tmp/dc4bc_test_PutOperation"
)
defer os.RemoveAll(dbPath)
stg, err := client.NewLevelDBState(dbPath)
req.NoError(err)
operation := &client.Operation{
ID: "operation_id",
Type: client.DKGCommits,
Payload: []byte("operation_payload"),
Result: []byte("operation_result"),
CreatedAt: time.Now(),
}
err = stg.PutOperation(operation)
req.NoError(err)
loadedOperation, err := stg.GetOperationByID(operation.ID)
req.NoError(err)
req.Equal(operation.ID, loadedOperation.ID)
req.Equal(operation.Type, loadedOperation.Type)
req.Equal(operation.Payload, loadedOperation.Payload)
req.Equal(operation.Result, loadedOperation.Result)
err = stg.PutOperation(operation)
req.Error(err)
}
func TestLevelDBState_GetOperations(t *testing.T) {
var (
req = require.New(t)
dbPath = "/tmp/dc4bc_test_PutOperation"
)
defer os.RemoveAll(dbPath)
stg, err := client.NewLevelDBState(dbPath)
req.NoError(err)
operation := &client.Operation{
ID: "operation_1",
Type: client.DKGCommits,
Payload: []byte("operation_payload"),
Result: []byte("operation_result"),
CreatedAt: time.Now(),
}
err = stg.PutOperation(operation)
req.NoError(err)
operation.ID = "operation_2"
err = stg.PutOperation(operation)
req.NoError(err)
operations, err := stg.GetOperations()
req.NoError(err)
req.Len(operations, 2)
}
func TestLevelDBState_DeleteOperation(t *testing.T) {
var (
req = require.New(t)
dbPath = "/tmp/dc4bc_test_DeleteOperation"
)
defer os.RemoveAll(dbPath)
stg, err := client.NewLevelDBState(dbPath)
req.NoError(err)
operation := &client.Operation{
ID: "operation_id",
Type: client.DKGCommits,
Payload: []byte("operation_payload"),
Result: []byte("operation_result"),
CreatedAt: time.Now(),
}
err = stg.PutOperation(operation)
req.NoError(err)
_, err = stg.GetOperationByID(operation.ID)
req.NoError(err)
err = stg.DeleteOperation(operation.ID)
req.NoError(err)
_, err = stg.GetOperationByID(operation.ID)
req.Error(err)
}

37
client/types.go Normal file
View File

@ -0,0 +1,37 @@
package client
import (
"bytes"
"fmt"
"time"
)
type OperationType string
const (
DKGCommits OperationType = "dkg_commits"
)
type Operation struct {
ID string // UUID4
Type OperationType
Payload []byte
Result []byte
CreatedAt time.Time
}
func (o *Operation) Check(o2 *Operation) error {
if o.ID != o2.ID {
return fmt.Errorf("o1.ID (%s) != o2.ID (%s)", o.ID, o2.ID)
}
if o.Type != o2.Type {
return fmt.Errorf("o1.Type (%s) != o2.Type (%s)", o.Type, o2.Type)
}
if !bytes.Equal(o.Payload, o2.Payload) {
return fmt.Errorf("o1.Payload (%v) != o2.Payload (%v)", o.Payload, o2.Payload)
}
return nil
}

View File

@ -23,7 +23,7 @@ const (
StateGlobalDone = "__done"
)
// FSMResponse returns result for processing with client events
// FSMResponse returns result for processing with clientMocks events
type FSMResponse struct {
// Returns machine execution result state
State string

18
go.mod
View File

@ -1,23 +1,25 @@
module p2p.org/dc4bc
module github.com/p2p-org/dc4bc
go 1.13
require (
github.com/golang/mock v1.4.4
github.com/google/uuid v1.1.1
github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b
github.com/looplab/fsm v0.1.0
github.com/makiuchi-d/gozxing v0.0.0-20190830103442-eaff64b1ceb7
github.com/mattn/go-gtk v0.0.0-20191030024613-af2e013261f5
github.com/p2p-org/dc4bc v0.0.0-00010101000000-000000000000
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f // indirect
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.6.1
github.com/syndtr/goleveldb v1.0.0
go.dedis.ch/kyber/v3 v3.0.9
gocv.io/x/gocv v0.23.0
golang.org/x/image v0.0.0-20200618115811-c13761719519
golang.org/x/text v0.3.3 // indirect
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
)
replace golang.org/x/crypto => github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5
replace go.dedis.ch/kyber/v3 => github.com/corestario/kyber/v3 v3.0.0-20200218082721-8ed10c357c05
replace github.com/p2p-org/dc4bc => /home/tellme/PROJECTS/go/src/github.com/p2p-org/dc4bc
replace (
go.dedis.ch/kyber/v3 => github.com/corestario/kyber/v3 v3.0.0-20200218082721-8ed10c357c05
golang.org/x/crypto => github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5
)

77
go.sum Normal file
View File

@ -0,0 +1,77 @@
github.com/corestario/kyber/v3 v3.0.0-20200218082721-8ed10c357c05 h1:ICuDs+sbQzDem2pIAFyI+u6s0RiETzMc2IhnobgHkvE=
github.com/corestario/kyber/v3 v3.0.0-20200218082721-8ed10c357c05/go.mod h1:kXy7p3STAurkADD+/aZcsznZGKVHEqbtmdIzvPfrs1U=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b h1:FQ7+9fxhyp82ks9vAuyPzG0/vVbWwMwLJ+P6yJI5FN8=
github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b/go.mod h1:HMcgvsgd0Fjj4XXDkbjdmlbI505rUPBs6WBMYg2pXks=
github.com/looplab/fsm v0.1.0 h1:Qte7Zdn/5hBNbXzP7yxVU4OIFHWXBovyTT2LaBTyC20=
github.com/looplab/fsm v0.1.0/go.mod h1:m2VaOfDHxqXBBMgc26m6yUOwkFn8H2AlJDE+jd/uafI=
github.com/makiuchi-d/gozxing v0.0.0-20190830103442-eaff64b1ceb7 h1:CfWnkHgRG8zmxQI7RAhLIUFPkg+RfDdWiEtoE3y1+4w=
github.com/makiuchi-d/gozxing v0.0.0-20190830103442-eaff64b1ceb7/go.mod h1:WoI7z45M7ZNA5BJxiJHaB+x7+k8S/3phW5Y13IR4yWY=
github.com/mattn/go-gtk v0.0.0-20191030024613-af2e013261f5 h1:GMB3MVJnxysGrSvjWGsgK8L3XGI3F4etQQq37Py6W5A=
github.com/mattn/go-gtk v0.0.0-20191030024613-af2e013261f5/go.mod h1:PwzwfeB5syFHXORC3MtPylVcjIoTDT/9cvkKpEndGVI=
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f h1:QTRRO+ozoYgT3CQRIzNVYJRU3DB8HRnkZv6mr4ISmMA=
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5 h1:u8i49c+BxloX3XQ55cvzFNXplizZP/q00i+IlttUjAU=
github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk=
go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs=
go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw=
go.dedis.ch/protobuf v1.0.11 h1:FTYVIEzY/bfl37lu3pR4lIj+F9Vp1jE8oh91VmxKgLo=
go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4=
gocv.io/x/gocv v0.23.0 h1:3Fgbt06/uR8Zf9emWndhjbUjdrw+nto69R/b4noFydY=
gocv.io/x/gocv v0.23.0/go.mod h1:Rar2PS6DV+T4FL+PM535EImD/h13hGVaHhnCu1xarBs=
golang.org/x/image v0.0.0-20200618115811-c13761719519 h1:1e2ufUJNM3lCHEY5jIgac/7UTjd6cgJNdatjPdFWf34=
golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e h1:3GIlrlVLfkoipSReOMNAgApI0ajnalyLa/EZHHca/XI=
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -2,14 +2,15 @@ package main
import (
"fmt"
dkg "go.dedis.ch/kyber/v3/share/dkg/pedersen"
_ "image/jpeg"
"log"
"sync"
dkg "go.dedis.ch/kyber/v3/share/dkg/pedersen"
"go.dedis.ch/kyber/v3"
dkglib "p2p.org/dc4bc/dkg"
dkglib "github.com/p2p-org/dc4bc/dkg"
_ "image/gif"
_ "image/png"
@ -162,7 +163,7 @@ func runStep(transport *Transport, cb func(participantID string, participant *dk
// log.Println("Please center the photo of the QR-code in front" +
// "of your web-camera...")
//
// scannedData, err = qr.ReadQRFromCamera()
// scannedData, err = qr.ReadQR()
// if err == nil {
// break
// }

View File

@ -0,0 +1,150 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: ./../client/state.go
// Package clientMocks is a generated GoMock package.
package clientMocks
import (
gomock "github.com/golang/mock/gomock"
client "github.com/p2p-org/dc4bc/client"
reflect "reflect"
)
// MockState is a mock of State interface
type MockState struct {
ctrl *gomock.Controller
recorder *MockStateMockRecorder
}
// MockStateMockRecorder is the mock recorder for MockState
type MockStateMockRecorder struct {
mock *MockState
}
// NewMockState creates a new mock instance
func NewMockState(ctrl *gomock.Controller) *MockState {
mock := &MockState{ctrl: ctrl}
mock.recorder = &MockStateMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockState) EXPECT() *MockStateMockRecorder {
return m.recorder
}
// SaveOffset mocks base method
func (m *MockState) SaveOffset(arg0 uint64) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SaveOffset", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SaveOffset indicates an expected call of SaveOffset
func (mr *MockStateMockRecorder) SaveOffset(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SaveOffset", reflect.TypeOf((*MockState)(nil).SaveOffset), arg0)
}
// LoadOffset mocks base method
func (m *MockState) LoadOffset() (uint64, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "LoadOffset")
ret0, _ := ret[0].(uint64)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// LoadOffset indicates an expected call of LoadOffset
func (mr *MockStateMockRecorder) LoadOffset() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadOffset", reflect.TypeOf((*MockState)(nil).LoadOffset))
}
// SaveFSM mocks base method
func (m *MockState) SaveFSM(arg0 interface{}) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SaveFSM", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SaveFSM indicates an expected call of SaveFSM
func (mr *MockStateMockRecorder) SaveFSM(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SaveFSM", reflect.TypeOf((*MockState)(nil).SaveFSM), arg0)
}
// LoadFSM mocks base method
func (m *MockState) LoadFSM() (interface{}, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "LoadFSM")
ret0, _ := ret[0].(interface{})
ret1, _ := ret[1].(error)
return ret0, ret1
}
// LoadFSM indicates an expected call of LoadFSM
func (mr *MockStateMockRecorder) LoadFSM() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadFSM", reflect.TypeOf((*MockState)(nil).LoadFSM))
}
// PutOperation mocks base method
func (m *MockState) PutOperation(operation *client.Operation) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PutOperation", operation)
ret0, _ := ret[0].(error)
return ret0
}
// PutOperation indicates an expected call of PutOperation
func (mr *MockStateMockRecorder) PutOperation(operation interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutOperation", reflect.TypeOf((*MockState)(nil).PutOperation), operation)
}
// DeleteOperation mocks base method
func (m *MockState) DeleteOperation(operationID string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DeleteOperation", operationID)
ret0, _ := ret[0].(error)
return ret0
}
// DeleteOperation indicates an expected call of DeleteOperation
func (mr *MockStateMockRecorder) DeleteOperation(operationID interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteOperation", reflect.TypeOf((*MockState)(nil).DeleteOperation), operationID)
}
// GetOperations mocks base method
func (m *MockState) GetOperations() (map[string]*client.Operation, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetOperations")
ret0, _ := ret[0].(map[string]*client.Operation)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetOperations indicates an expected call of GetOperations
func (mr *MockStateMockRecorder) GetOperations() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOperations", reflect.TypeOf((*MockState)(nil).GetOperations))
}
// GetOperationByID mocks base method
func (m *MockState) GetOperationByID(operationID string) (*client.Operation, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetOperationByID", operationID)
ret0, _ := ret[0].(*client.Operation)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetOperationByID indicates an expected call of GetOperationByID
func (mr *MockStateMockRecorder) GetOperationByID(operationID interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOperationByID", reflect.TypeOf((*MockState)(nil).GetOperationByID), operationID)
}

5
mocks/gomock.go Normal file
View File

@ -0,0 +1,5 @@
package mocks
//go:generate mockgen -source=./../client/state.go -destination=./clientMocks/state_mock.go -package=clientMocks
//go:generate mockgen -source=./../storage/types.go -destination=./storageMocks/storage_mock.go -package=storageMocks
//go:generate mockgen -source=./../qr/qr.go -destination=./qrMocks/qr_mock.go -package=qrMocks

62
mocks/qrMocks/qr_mock.go Normal file
View File

@ -0,0 +1,62 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: ./../qr/qr.go
// Package qrMocks is a generated GoMock package.
package qrMocks
import (
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
// MockProcessor is a mock of Processor interface
type MockProcessor struct {
ctrl *gomock.Controller
recorder *MockProcessorMockRecorder
}
// MockProcessorMockRecorder is the mock recorder for MockProcessor
type MockProcessorMockRecorder struct {
mock *MockProcessor
}
// NewMockProcessor creates a new mock instance
func NewMockProcessor(ctrl *gomock.Controller) *MockProcessor {
mock := &MockProcessor{ctrl: ctrl}
mock.recorder = &MockProcessorMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockProcessor) EXPECT() *MockProcessorMockRecorder {
return m.recorder
}
// ReadQR mocks base method
func (m *MockProcessor) ReadQR() ([]byte, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ReadQR")
ret0, _ := ret[0].([]byte)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ReadQR indicates an expected call of ReadQR
func (mr *MockProcessorMockRecorder) ReadQR() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadQR", reflect.TypeOf((*MockProcessor)(nil).ReadQR))
}
// WriteQR mocks base method
func (m *MockProcessor) WriteQR(path string, data []byte) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "WriteQR", path, data)
ret0, _ := ret[0].(error)
return ret0
}
// WriteQR indicates an expected call of WriteQR
func (mr *MockProcessorMockRecorder) WriteQR(path, data interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteQR", reflect.TypeOf((*MockProcessor)(nil).WriteQR), path, data)
}

View File

@ -0,0 +1,78 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: ./../storage/types.go
// Package storageMocks is a generated GoMock package.
package storageMocks
import (
gomock "github.com/golang/mock/gomock"
storage "github.com/p2p-org/dc4bc/storage"
reflect "reflect"
)
// MockStorage is a mock of Storage interface
type MockStorage struct {
ctrl *gomock.Controller
recorder *MockStorageMockRecorder
}
// MockStorageMockRecorder is the mock recorder for MockStorage
type MockStorageMockRecorder struct {
mock *MockStorage
}
// NewMockStorage creates a new mock instance
func NewMockStorage(ctrl *gomock.Controller) *MockStorage {
mock := &MockStorage{ctrl: ctrl}
mock.recorder = &MockStorageMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockStorage) EXPECT() *MockStorageMockRecorder {
return m.recorder
}
// Send mocks base method
func (m *MockStorage) Send(message storage.Message) (storage.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Send", message)
ret0, _ := ret[0].(storage.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Send indicates an expected call of Send
func (mr *MockStorageMockRecorder) Send(message interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Send", reflect.TypeOf((*MockStorage)(nil).Send), message)
}
// GetMessages mocks base method
func (m *MockStorage) GetMessages(offset uint64) ([]storage.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetMessages", offset)
ret0, _ := ret[0].([]storage.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetMessages indicates an expected call of GetMessages
func (mr *MockStorageMockRecorder) GetMessages(offset interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMessages", reflect.TypeOf((*MockStorage)(nil).GetMessages), offset)
}
// Close mocks base method
func (m *MockStorage) Close() error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Close")
ret0, _ := ret[0].(error)
return ret0
}
// Close indicates an expected call of Close
func (mr *MockStorageMockRecorder) Close() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockStorage)(nil).Close))
}

View File

@ -5,6 +5,8 @@ import (
"log"
"time"
encoder "github.com/skip2/go-qrcode"
"github.com/makiuchi-d/gozxing"
"github.com/makiuchi-d/gozxing/qrcode"
"gocv.io/x/gocv"
@ -12,10 +14,21 @@ import (
const timeToScan = time.Second * 5
func ReadQRFromCamera() (string, error) {
type Processor interface {
ReadQR() ([]byte, error)
WriteQR(path string, data []byte) error
}
type CameraProcessor struct{}
func NewCameraProcessor() *CameraProcessor {
return &CameraProcessor{}
}
func (p *CameraProcessor) ReadQR() ([]byte, error) {
webcam, err := gocv.OpenVideoCapture(0)
if err != nil {
return "", fmt.Errorf("failed to OpenVideoCapture: %w", err)
return nil, fmt.Errorf("failed to OpenVideoCapture: %w", err)
}
window := gocv.NewWindow("Hello")
@ -50,19 +63,28 @@ loop:
imgObject, err := img.ToImage()
if err != nil {
return "", fmt.Errorf("failed to get image object: %w", err)
return nil, fmt.Errorf("failed to get image object: %w", err)
}
bmp, err := gozxing.NewBinaryBitmapFromImage(imgObject)
if err != nil {
return "", fmt.Errorf("failed to get NewBinaryBitmapFromImage: %w", err)
return nil, fmt.Errorf("failed to get NewBinaryBitmapFromImage: %w", err)
}
qrReader := qrcode.NewQRCodeReader()
result, err := qrReader.Decode(bmp, nil)
if err != nil {
return "", fmt.Errorf("failed to decode the QR-code contents: %w", err)
return nil, fmt.Errorf("failed to decode the QR-code contents: %w", err)
}
return result.String(), err
return result.GetRawBytes(), err
}
func (p *CameraProcessor) WriteQR(path string, data []byte) error {
err := encoder.WriteFile(string(data), encoder.Medium, 512, path)
if err != nil {
return fmt.Errorf("failed to encode the data: %w", err)
}
return nil
}

View File

@ -1,63 +0,0 @@
package qr
import (
"fmt"
_ "image/gif"
_ "image/jpeg"
_ "image/png"
"os"
"github.com/mattn/go-gtk/glib"
"github.com/mattn/go-gtk/gtk"
encoder "github.com/skip2/go-qrcode"
_ "golang.org/x/image/bmp"
_ "golang.org/x/image/tiff"
)
const tmpImageFile = "/tmp/qr.png"
func ShowQR(data string) error {
defer func() {
_ = os.Remove(tmpImageFile)
}()
err := encoder.WriteFile(data, encoder.Medium, 512, tmpImageFile)
if err != nil {
return fmt.Errorf("failed to encode the data: %w", err)
}
showImage(tmpImageFile)
return nil
}
func showImage(imageFile string) {
gtk.Init(nil)
window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
window.SetPosition(gtk.WIN_POS_CENTER)
window.SetTitle("p2p.org QR Viewer")
window.SetIconName("p2p.org QR Viewer")
window.Connect("destroy", func(ctx *glib.CallbackContext) {
gtk.MainQuit()
})
hbox := gtk.NewHBox(false, 1)
hpaned := gtk.NewHPaned()
hbox.Add(hpaned)
frame1 := gtk.NewFrame("QR Code")
framebox1 := gtk.NewHBox(false, 1)
frame1.Add(framebox1)
hpaned.Pack1(frame1, false, false)
image := gtk.NewImageFromFile(imageFile)
framebox1.Add(image)
window.Add(hbox)
imagePixBuffer := image.GetPixbuf()
horizontalSize := imagePixBuffer.GetWidth()
verticalSize := imagePixBuffer.GetHeight()
window.SetSizeRequest(horizontalSize, verticalSize)
window.ShowAll()
gtk.Main()
}

View File

@ -4,10 +4,11 @@ import (
"bufio"
"encoding/json"
"fmt"
"github.com/google/uuid"
"github.com/juju/fslock"
"io"
"os"
"github.com/google/uuid"
"github.com/juju/fslock"
)
var _ Storage = (*FileStorage)(nil)
@ -81,7 +82,7 @@ func (fs *FileStorage) Send(m Message) (Message, error) {
}
// GetMessages returns a slice of messages from append-only data file with given offset
func (fs *FileStorage) GetMessages(offset int) ([]Message, error) {
func (fs *FileStorage) GetMessages(offset uint64) ([]Message, error) {
var (
msgs []Message
err error

View File

@ -2,6 +2,7 @@ package storage
import (
"math/rand"
"os"
"reflect"
"testing"
"time"
@ -18,12 +19,15 @@ func randomBytes(n int) []byte {
func TestFileStorage_GetMessages(t *testing.T) {
N := 10
offset := 5
fs, err := InitFileStorage("test")
var offset uint64 = 5
var testFile = "/tmp/dc4bc_test_file_storage"
fs, err := InitFileStorage(testFile)
if err != nil {
t.Error(err)
}
defer fs.Close()
defer os.Remove(testFile)
msgs := make([]Message, 0, N)
for i := 0; i < N; i++ {
msg := Message{
@ -36,10 +40,12 @@ func TestFileStorage_GetMessages(t *testing.T) {
}
msgs = append(msgs, msg)
}
offsetMsgs, err := fs.GetMessages(offset)
if err != nil {
t.Error(err)
}
expectedOffsetMsgs := msgs[offset:]
if !reflect.DeepEqual(offsetMsgs, expectedOffsetMsgs) {
t.Errorf("expected messages: %v, actual messages: %v", expectedOffsetMsgs, offsetMsgs)

View File

@ -9,6 +9,6 @@ type Message struct {
type Storage interface {
Send(message Message) (Message, error)
GetMessages(offset int) ([]Message, error)
GetMessages(offset uint64) ([]Message, error)
Close() error
}