mirror of https://github.com/certusone/dc4bc.git
Merge pull request #8 from p2p-org/feat/client-skeleton
feat: client skeleton
This commit is contained in:
commit
6cb0f59656
|
@ -0,0 +1,9 @@
|
||||||
|
test:
|
||||||
|
@echo "Testing Go packages..."
|
||||||
|
@go test ./... -cover
|
||||||
|
|
||||||
|
mocks:
|
||||||
|
@echo "Regenerate mocks..."
|
||||||
|
@go generate ./...
|
||||||
|
|
||||||
|
.PHONY: mocks
|
|
@ -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
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -23,7 +23,7 @@ const (
|
||||||
StateGlobalDone = "__done"
|
StateGlobalDone = "__done"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FSMResponse returns result for processing with client events
|
// FSMResponse returns result for processing with clientMocks events
|
||||||
type FSMResponse struct {
|
type FSMResponse struct {
|
||||||
// Returns machine execution result state
|
// Returns machine execution result state
|
||||||
State string
|
State string
|
||||||
|
|
18
go.mod
18
go.mod
|
@ -1,23 +1,25 @@
|
||||||
module p2p.org/dc4bc
|
module github.com/p2p-org/dc4bc
|
||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/golang/mock v1.4.4
|
||||||
github.com/google/uuid v1.1.1
|
github.com/google/uuid v1.1.1
|
||||||
github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b
|
github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b
|
||||||
github.com/looplab/fsm v0.1.0
|
github.com/looplab/fsm v0.1.0
|
||||||
github.com/makiuchi-d/gozxing v0.0.0-20190830103442-eaff64b1ceb7
|
github.com/makiuchi-d/gozxing v0.0.0-20190830103442-eaff64b1ceb7
|
||||||
github.com/mattn/go-gtk v0.0.0-20191030024613-af2e013261f5
|
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f // indirect
|
||||||
github.com/p2p-org/dc4bc v0.0.0-00010101000000-000000000000
|
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||||
github.com/stretchr/testify v1.6.1
|
github.com/stretchr/testify v1.6.1
|
||||||
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
go.dedis.ch/kyber/v3 v3.0.9
|
go.dedis.ch/kyber/v3 v3.0.9
|
||||||
gocv.io/x/gocv v0.23.0
|
gocv.io/x/gocv v0.23.0
|
||||||
golang.org/x/image v0.0.0-20200618115811-c13761719519
|
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 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
|
||||||
|
)
|
||||||
replace github.com/p2p-org/dc4bc => /home/tellme/PROJECTS/go/src/github.com/p2p-org/dc4bc
|
|
||||||
|
|
|
@ -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=
|
7
main.go
7
main.go
|
@ -2,14 +2,15 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
dkg "go.dedis.ch/kyber/v3/share/dkg/pedersen"
|
|
||||||
_ "image/jpeg"
|
_ "image/jpeg"
|
||||||
"log"
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
dkg "go.dedis.ch/kyber/v3/share/dkg/pedersen"
|
||||||
|
|
||||||
"go.dedis.ch/kyber/v3"
|
"go.dedis.ch/kyber/v3"
|
||||||
|
|
||||||
dkglib "p2p.org/dc4bc/dkg"
|
dkglib "github.com/p2p-org/dc4bc/dkg"
|
||||||
|
|
||||||
_ "image/gif"
|
_ "image/gif"
|
||||||
_ "image/png"
|
_ "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" +
|
// log.Println("Please center the photo of the QR-code in front" +
|
||||||
// "of your web-camera...")
|
// "of your web-camera...")
|
||||||
//
|
//
|
||||||
// scannedData, err = qr.ReadQRFromCamera()
|
// scannedData, err = qr.ReadQR()
|
||||||
// if err == nil {
|
// if err == nil {
|
||||||
// break
|
// break
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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
|
|
@ -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)
|
||||||
|
}
|
|
@ -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))
|
||||||
|
}
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
encoder "github.com/skip2/go-qrcode"
|
||||||
|
|
||||||
"github.com/makiuchi-d/gozxing"
|
"github.com/makiuchi-d/gozxing"
|
||||||
"github.com/makiuchi-d/gozxing/qrcode"
|
"github.com/makiuchi-d/gozxing/qrcode"
|
||||||
"gocv.io/x/gocv"
|
"gocv.io/x/gocv"
|
||||||
|
@ -12,10 +14,21 @@ import (
|
||||||
|
|
||||||
const timeToScan = time.Second * 5
|
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)
|
webcam, err := gocv.OpenVideoCapture(0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to OpenVideoCapture: %w", err)
|
return nil, fmt.Errorf("failed to OpenVideoCapture: %w", err)
|
||||||
}
|
}
|
||||||
window := gocv.NewWindow("Hello")
|
window := gocv.NewWindow("Hello")
|
||||||
|
|
||||||
|
@ -50,19 +63,28 @@ loop:
|
||||||
|
|
||||||
imgObject, err := img.ToImage()
|
imgObject, err := img.ToImage()
|
||||||
if err != nil {
|
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)
|
bmp, err := gozxing.NewBinaryBitmapFromImage(imgObject)
|
||||||
if err != nil {
|
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()
|
qrReader := qrcode.NewQRCodeReader()
|
||||||
result, err := qrReader.Decode(bmp, nil)
|
result, err := qrReader.Decode(bmp, nil)
|
||||||
if err != 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
|
||||||
}
|
}
|
|
@ -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()
|
|
||||||
}
|
|
|
@ -4,10 +4,11 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/juju/fslock"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/juju/fslock"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Storage = (*FileStorage)(nil)
|
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
|
// 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 (
|
var (
|
||||||
msgs []Message
|
msgs []Message
|
||||||
err error
|
err error
|
||||||
|
|
|
@ -2,6 +2,7 @@ package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -18,12 +19,15 @@ func randomBytes(n int) []byte {
|
||||||
|
|
||||||
func TestFileStorage_GetMessages(t *testing.T) {
|
func TestFileStorage_GetMessages(t *testing.T) {
|
||||||
N := 10
|
N := 10
|
||||||
offset := 5
|
var offset uint64 = 5
|
||||||
fs, err := InitFileStorage("test")
|
var testFile = "/tmp/dc4bc_test_file_storage"
|
||||||
|
fs, err := InitFileStorage(testFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
defer fs.Close()
|
defer fs.Close()
|
||||||
|
defer os.Remove(testFile)
|
||||||
|
|
||||||
msgs := make([]Message, 0, N)
|
msgs := make([]Message, 0, N)
|
||||||
for i := 0; i < N; i++ {
|
for i := 0; i < N; i++ {
|
||||||
msg := Message{
|
msg := Message{
|
||||||
|
@ -36,10 +40,12 @@ func TestFileStorage_GetMessages(t *testing.T) {
|
||||||
}
|
}
|
||||||
msgs = append(msgs, msg)
|
msgs = append(msgs, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
offsetMsgs, err := fs.GetMessages(offset)
|
offsetMsgs, err := fs.GetMessages(offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedOffsetMsgs := msgs[offset:]
|
expectedOffsetMsgs := msgs[offset:]
|
||||||
if !reflect.DeepEqual(offsetMsgs, expectedOffsetMsgs) {
|
if !reflect.DeepEqual(offsetMsgs, expectedOffsetMsgs) {
|
||||||
t.Errorf("expected messages: %v, actual messages: %v", expectedOffsetMsgs, offsetMsgs)
|
t.Errorf("expected messages: %v, actual messages: %v", expectedOffsetMsgs, offsetMsgs)
|
||||||
|
|
|
@ -9,6 +9,6 @@ type Message struct {
|
||||||
|
|
||||||
type Storage interface {
|
type Storage interface {
|
||||||
Send(message Message) (Message, error)
|
Send(message Message) (Message, error)
|
||||||
GetMessages(offset int) ([]Message, error)
|
GetMessages(offset uint64) ([]Message, error)
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue