Move accountant to it's own deployment using gRCP

This commit is contained in:
Marc Di Luzio 2020-06-10 23:23:09 +01:00
parent 8f25f55658
commit 99da6c5d67
14 changed files with 868 additions and 64 deletions

View file

@ -1,75 +0,0 @@
package accounts
import (
"fmt"
)
const kAccountsFileName = "rove-accounts.json"
// Account represents a registered user
type Account struct {
// Name simply describes the account and must be unique
Name string `json:"name"`
// Data represents internal account data
Data map[string]string `json:"data"`
}
// Represents the accountant data to store
type accountantData struct {
}
// Accountant manages a set of accounts
type Accountant struct {
Accounts map[string]Account `json:"accounts"`
}
// NewAccountant creates a new accountant
func NewAccountant() *Accountant {
return &Accountant{
Accounts: make(map[string]Account),
}
}
// RegisterAccount adds an account to the set of internal accounts
func (a *Accountant) RegisterAccount(name string) (acc Account, err error) {
// Set the account name
acc.Name = name
// Verify this acount isn't already registered
for _, a := range a.Accounts {
if a.Name == acc.Name {
return Account{}, fmt.Errorf("Account name already registered")
}
}
// Simply add the account to the map
a.Accounts[acc.Name] = acc
return
}
// AssignRover assigns data to an account
func (a *Accountant) AssignData(account string, key string, value string) error {
// Find the account matching the ID
if this, ok := a.Accounts[account]; ok {
this.Data[key] = value
a.Accounts[account] = this
} else {
return fmt.Errorf("no account found for id: %s", account)
}
return nil
}
// GetRover gets the rover rover for the account
func (a *Accountant) GetData(account string, key string) (string, error) {
// Find the account matching the ID
if this, ok := a.Accounts[account]; !ok {
return "", fmt.Errorf("no account found for id: %s", account)
} else {
return this.Data[key], nil
}
}

503
pkg/accounts/accounts.pb.go Normal file
View file

@ -0,0 +1,503 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: accounts.proto
package accounts
import (
context "context"
fmt "fmt"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type RegisterInfo struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *RegisterInfo) Reset() { *m = RegisterInfo{} }
func (m *RegisterInfo) String() string { return proto.CompactTextString(m) }
func (*RegisterInfo) ProtoMessage() {}
func (*RegisterInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_e1e7723af4c007b7, []int{0}
}
func (m *RegisterInfo) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RegisterInfo.Unmarshal(m, b)
}
func (m *RegisterInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_RegisterInfo.Marshal(b, m, deterministic)
}
func (m *RegisterInfo) XXX_Merge(src proto.Message) {
xxx_messageInfo_RegisterInfo.Merge(m, src)
}
func (m *RegisterInfo) XXX_Size() int {
return xxx_messageInfo_RegisterInfo.Size(m)
}
func (m *RegisterInfo) XXX_DiscardUnknown() {
xxx_messageInfo_RegisterInfo.DiscardUnknown(m)
}
var xxx_messageInfo_RegisterInfo proto.InternalMessageInfo
func (m *RegisterInfo) GetName() string {
if m != nil {
return m.Name
}
return ""
}
type RegisterResponse struct {
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *RegisterResponse) Reset() { *m = RegisterResponse{} }
func (m *RegisterResponse) String() string { return proto.CompactTextString(m) }
func (*RegisterResponse) ProtoMessage() {}
func (*RegisterResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_e1e7723af4c007b7, []int{1}
}
func (m *RegisterResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RegisterResponse.Unmarshal(m, b)
}
func (m *RegisterResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_RegisterResponse.Marshal(b, m, deterministic)
}
func (m *RegisterResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_RegisterResponse.Merge(m, src)
}
func (m *RegisterResponse) XXX_Size() int {
return xxx_messageInfo_RegisterResponse.Size(m)
}
func (m *RegisterResponse) XXX_DiscardUnknown() {
xxx_messageInfo_RegisterResponse.DiscardUnknown(m)
}
var xxx_messageInfo_RegisterResponse proto.InternalMessageInfo
func (m *RegisterResponse) GetSuccess() bool {
if m != nil {
return m.Success
}
return false
}
func (m *RegisterResponse) GetError() string {
if m != nil {
return m.Error
}
return ""
}
type DataKeyValue struct {
Account string `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *DataKeyValue) Reset() { *m = DataKeyValue{} }
func (m *DataKeyValue) String() string { return proto.CompactTextString(m) }
func (*DataKeyValue) ProtoMessage() {}
func (*DataKeyValue) Descriptor() ([]byte, []int) {
return fileDescriptor_e1e7723af4c007b7, []int{2}
}
func (m *DataKeyValue) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DataKeyValue.Unmarshal(m, b)
}
func (m *DataKeyValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_DataKeyValue.Marshal(b, m, deterministic)
}
func (m *DataKeyValue) XXX_Merge(src proto.Message) {
xxx_messageInfo_DataKeyValue.Merge(m, src)
}
func (m *DataKeyValue) XXX_Size() int {
return xxx_messageInfo_DataKeyValue.Size(m)
}
func (m *DataKeyValue) XXX_DiscardUnknown() {
xxx_messageInfo_DataKeyValue.DiscardUnknown(m)
}
var xxx_messageInfo_DataKeyValue proto.InternalMessageInfo
func (m *DataKeyValue) GetAccount() string {
if m != nil {
return m.Account
}
return ""
}
func (m *DataKeyValue) GetKey() string {
if m != nil {
return m.Key
}
return ""
}
func (m *DataKeyValue) GetValue() string {
if m != nil {
return m.Value
}
return ""
}
type Response struct {
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Response) Reset() { *m = Response{} }
func (m *Response) String() string { return proto.CompactTextString(m) }
func (*Response) ProtoMessage() {}
func (*Response) Descriptor() ([]byte, []int) {
return fileDescriptor_e1e7723af4c007b7, []int{3}
}
func (m *Response) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Response.Unmarshal(m, b)
}
func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Response.Marshal(b, m, deterministic)
}
func (m *Response) XXX_Merge(src proto.Message) {
xxx_messageInfo_Response.Merge(m, src)
}
func (m *Response) XXX_Size() int {
return xxx_messageInfo_Response.Size(m)
}
func (m *Response) XXX_DiscardUnknown() {
xxx_messageInfo_Response.DiscardUnknown(m)
}
var xxx_messageInfo_Response proto.InternalMessageInfo
func (m *Response) GetSuccess() bool {
if m != nil {
return m.Success
}
return false
}
func (m *Response) GetError() string {
if m != nil {
return m.Error
}
return ""
}
type DataKey struct {
Account string `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *DataKey) Reset() { *m = DataKey{} }
func (m *DataKey) String() string { return proto.CompactTextString(m) }
func (*DataKey) ProtoMessage() {}
func (*DataKey) Descriptor() ([]byte, []int) {
return fileDescriptor_e1e7723af4c007b7, []int{4}
}
func (m *DataKey) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DataKey.Unmarshal(m, b)
}
func (m *DataKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_DataKey.Marshal(b, m, deterministic)
}
func (m *DataKey) XXX_Merge(src proto.Message) {
xxx_messageInfo_DataKey.Merge(m, src)
}
func (m *DataKey) XXX_Size() int {
return xxx_messageInfo_DataKey.Size(m)
}
func (m *DataKey) XXX_DiscardUnknown() {
xxx_messageInfo_DataKey.DiscardUnknown(m)
}
var xxx_messageInfo_DataKey proto.InternalMessageInfo
func (m *DataKey) GetAccount() string {
if m != nil {
return m.Account
}
return ""
}
func (m *DataKey) GetKey() string {
if m != nil {
return m.Key
}
return ""
}
type DataResponse struct {
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *DataResponse) Reset() { *m = DataResponse{} }
func (m *DataResponse) String() string { return proto.CompactTextString(m) }
func (*DataResponse) ProtoMessage() {}
func (*DataResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_e1e7723af4c007b7, []int{5}
}
func (m *DataResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DataResponse.Unmarshal(m, b)
}
func (m *DataResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_DataResponse.Marshal(b, m, deterministic)
}
func (m *DataResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_DataResponse.Merge(m, src)
}
func (m *DataResponse) XXX_Size() int {
return xxx_messageInfo_DataResponse.Size(m)
}
func (m *DataResponse) XXX_DiscardUnknown() {
xxx_messageInfo_DataResponse.DiscardUnknown(m)
}
var xxx_messageInfo_DataResponse proto.InternalMessageInfo
func (m *DataResponse) GetSuccess() bool {
if m != nil {
return m.Success
}
return false
}
func (m *DataResponse) GetError() string {
if m != nil {
return m.Error
}
return ""
}
func (m *DataResponse) GetValue() string {
if m != nil {
return m.Value
}
return ""
}
func init() {
proto.RegisterType((*RegisterInfo)(nil), "accounts.RegisterInfo")
proto.RegisterType((*RegisterResponse)(nil), "accounts.RegisterResponse")
proto.RegisterType((*DataKeyValue)(nil), "accounts.DataKeyValue")
proto.RegisterType((*Response)(nil), "accounts.Response")
proto.RegisterType((*DataKey)(nil), "accounts.DataKey")
proto.RegisterType((*DataResponse)(nil), "accounts.DataResponse")
}
func init() {
proto.RegisterFile("accounts.proto", fileDescriptor_e1e7723af4c007b7)
}
var fileDescriptor_e1e7723af4c007b7 = []byte{
// 298 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x92, 0x4f, 0x4b, 0xc3, 0x40,
0x10, 0xc5, 0x8d, 0x55, 0x1b, 0xc7, 0x22, 0x75, 0x11, 0x09, 0x39, 0xc9, 0x8a, 0xe0, 0x29, 0x01,
0x45, 0x04, 0xbd, 0xd8, 0x22, 0x88, 0x78, 0x91, 0x20, 0x1e, 0xbc, 0x6d, 0xe3, 0x18, 0x43, 0x9b,
0xdd, 0xb0, 0x7f, 0x0a, 0xf5, 0xf3, 0xf9, 0xc1, 0x24, 0xbb, 0xd9, 0x1a, 0xac, 0x17, 0x7b, 0xdb,
0x17, 0xe6, 0xf7, 0xe6, 0xcd, 0x4c, 0x60, 0x9f, 0xe5, 0xb9, 0x30, 0x5c, 0xab, 0xa4, 0x96, 0x42,
0x0b, 0x12, 0x7a, 0x4d, 0x29, 0x0c, 0x32, 0x2c, 0x4a, 0xa5, 0x51, 0x3e, 0xf0, 0x77, 0x41, 0x08,
0x6c, 0x71, 0x56, 0x61, 0x14, 0x1c, 0x07, 0x67, 0xbb, 0x99, 0x7d, 0xd3, 0x31, 0x0c, 0x7d, 0x4d,
0x86, 0xaa, 0x16, 0x5c, 0x21, 0x89, 0xa0, 0xaf, 0x4c, 0x9e, 0xa3, 0x52, 0xb6, 0x34, 0xcc, 0xbc,
0x24, 0x87, 0xb0, 0x8d, 0x52, 0x0a, 0x19, 0x6d, 0x5a, 0x0b, 0x27, 0xe8, 0x13, 0x0c, 0xee, 0x98,
0x66, 0x8f, 0xb8, 0x78, 0x61, 0x33, 0x63, 0xf9, 0x36, 0x43, 0xdb, 0xca, 0x4b, 0x32, 0x84, 0xde,
0x14, 0x17, 0x2d, 0xdd, 0x3c, 0x1b, 0xc7, 0x79, 0x03, 0x45, 0x3d, 0xe7, 0x68, 0x05, 0xbd, 0x86,
0x70, 0xed, 0x34, 0x97, 0xd0, 0x6f, 0xd3, 0xfc, 0x27, 0x08, 0x7d, 0x76, 0x43, 0xac, 0xdb, 0xf6,
0xef, 0x41, 0xce, 0xbf, 0x02, 0x80, 0x91, 0xeb, 0xc9, 0xb8, 0x26, 0xb7, 0xcd, 0x5c, 0x6e, 0xdb,
0xe4, 0x28, 0x59, 0x1e, 0xae, 0x7b, 0xa5, 0x38, 0x5e, 0xfd, 0xee, 0x43, 0xd1, 0x0d, 0x72, 0x03,
0x7b, 0x23, 0xa5, 0xca, 0x82, 0xbb, 0x55, 0x77, 0x4c, 0xba, 0x27, 0x88, 0x49, 0xd7, 0x64, 0x09,
0x5f, 0x41, 0x78, 0x8f, 0xda, 0x91, 0x07, 0x2b, 0x64, 0xfc, 0xcb, 0xec, 0x07, 0x1c, 0x9f, 0xbe,
0x9e, 0x14, 0xa5, 0xfe, 0x30, 0x93, 0x24, 0x17, 0x55, 0x5a, 0xbd, 0x95, 0x33, 0xf3, 0x99, 0x4a,
0x31, 0xc7, 0xb4, 0x9e, 0x16, 0xa9, 0xa7, 0x26, 0x3b, 0xf6, 0x0f, 0xbc, 0xf8, 0x0e, 0x00, 0x00,
0xff, 0xff, 0xef, 0x53, 0xc6, 0xba, 0x93, 0x02, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConnInterface
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6
// AccountantClient is the client API for Accountant service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type AccountantClient interface {
Register(ctx context.Context, in *RegisterInfo, opts ...grpc.CallOption) (*RegisterResponse, error)
AssignValue(ctx context.Context, in *DataKeyValue, opts ...grpc.CallOption) (*Response, error)
GetValue(ctx context.Context, in *DataKey, opts ...grpc.CallOption) (*DataResponse, error)
}
type accountantClient struct {
cc grpc.ClientConnInterface
}
func NewAccountantClient(cc grpc.ClientConnInterface) AccountantClient {
return &accountantClient{cc}
}
func (c *accountantClient) Register(ctx context.Context, in *RegisterInfo, opts ...grpc.CallOption) (*RegisterResponse, error) {
out := new(RegisterResponse)
err := c.cc.Invoke(ctx, "/accounts.Accountant/Register", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *accountantClient) AssignValue(ctx context.Context, in *DataKeyValue, opts ...grpc.CallOption) (*Response, error) {
out := new(Response)
err := c.cc.Invoke(ctx, "/accounts.Accountant/AssignValue", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *accountantClient) GetValue(ctx context.Context, in *DataKey, opts ...grpc.CallOption) (*DataResponse, error) {
out := new(DataResponse)
err := c.cc.Invoke(ctx, "/accounts.Accountant/GetValue", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// AccountantServer is the server API for Accountant service.
type AccountantServer interface {
Register(context.Context, *RegisterInfo) (*RegisterResponse, error)
AssignValue(context.Context, *DataKeyValue) (*Response, error)
GetValue(context.Context, *DataKey) (*DataResponse, error)
}
// UnimplementedAccountantServer can be embedded to have forward compatible implementations.
type UnimplementedAccountantServer struct {
}
func (*UnimplementedAccountantServer) Register(ctx context.Context, req *RegisterInfo) (*RegisterResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Register not implemented")
}
func (*UnimplementedAccountantServer) AssignValue(ctx context.Context, req *DataKeyValue) (*Response, error) {
return nil, status.Errorf(codes.Unimplemented, "method AssignValue not implemented")
}
func (*UnimplementedAccountantServer) GetValue(ctx context.Context, req *DataKey) (*DataResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetValue not implemented")
}
func RegisterAccountantServer(s *grpc.Server, srv AccountantServer) {
s.RegisterService(&_Accountant_serviceDesc, srv)
}
func _Accountant_Register_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RegisterInfo)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AccountantServer).Register(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/accounts.Accountant/Register",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AccountantServer).Register(ctx, req.(*RegisterInfo))
}
return interceptor(ctx, in, info, handler)
}
func _Accountant_AssignValue_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DataKeyValue)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AccountantServer).AssignValue(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/accounts.Accountant/AssignValue",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AccountantServer).AssignValue(ctx, req.(*DataKeyValue))
}
return interceptor(ctx, in, info, handler)
}
func _Accountant_GetValue_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DataKey)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AccountantServer).GetValue(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/accounts.Accountant/GetValue",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AccountantServer).GetValue(ctx, req.(*DataKey))
}
return interceptor(ctx, in, info, handler)
}
var _Accountant_serviceDesc = grpc.ServiceDesc{
ServiceName: "accounts.Accountant",
HandlerType: (*AccountantServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Register",
Handler: _Accountant_Register_Handler,
},
{
MethodName: "AssignValue",
Handler: _Accountant_AssignValue_Handler,
},
{
MethodName: "GetValue",
Handler: _Accountant_GetValue_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "accounts.proto",
}

View file

@ -0,0 +1,43 @@
syntax = "proto3";
option go_package = "github.com/mdiluz/rove/pkg/accounts";
package accounts;
service Accountant {
rpc Register(RegisterInfo) returns (RegisterResponse) {}
rpc AssignValue(DataKeyValue) returns (Response) {}
rpc GetValue(DataKey) returns (DataResponse) {}
}
message RegisterInfo {
string name = 1;
}
message RegisterResponse {
bool success = 1;
string error = 2;
}
message DataKeyValue {
string account = 1;
string key = 2;
string value = 3;
}
message Response {
bool success = 1;
string error = 2;
}
message DataKey {
string account = 1;
string key = 2;
}
message DataResponse {
bool success = 1;
string error = 2;
string value = 3;
}

View file

@ -1,66 +0,0 @@
package accounts
import (
"testing"
"github.com/google/uuid"
)
func TestNewAccountant(t *testing.T) {
// Very basic verify here for now
accountant := NewAccountant()
if accountant == nil {
t.Error("Failed to create accountant")
}
}
func TestAccountant_RegisterAccount(t *testing.T) {
accountant := NewAccountant()
// Start by making two accounts
namea := uuid.New().String()
acca, err := accountant.RegisterAccount(namea)
if err != nil {
t.Error(err)
} else if acca.Name != namea {
t.Errorf("Missmatched account name after register, expected: %s, actual: %s", namea, acca.Name)
}
nameb := uuid.New().String()
accb, err := accountant.RegisterAccount(nameb)
if err != nil {
t.Error(err)
} else if accb.Name != nameb {
t.Errorf("Missmatched account name after register, expected: %s, actual: %s", nameb, acca.Name)
}
// Verify another request gets rejected
_, err = accountant.RegisterAccount(namea)
if err == nil {
t.Error("Duplicate account name did not produce error")
}
}
func TestAccountant_AssignGetData(t *testing.T) {
accountant := NewAccountant()
if len(accountant.Accounts) != 0 {
t.Error("New accountant created with non-zero account number")
}
name := uuid.New().String()
a, err := accountant.RegisterAccount(name)
if err != nil {
t.Error(err)
}
err = accountant.AssignData(a.Name, "key", "value")
if err != nil {
t.Error("Failed to set data for created account")
} else if id, err := accountant.GetData(a.Name, "key"); err != nil {
t.Error("Failed to get data for account")
} else if id != "value" {
t.Error("Fetched data is incorrect for account")
}
}