From 1794dbda4ff49a789f77c31ce30857858f0a505a Mon Sep 17 00:00:00 2001 From: pm-aadit-patil Date: Thu, 7 Jul 2022 19:54:59 +0530 Subject: [PATCH] UOE-7907:Added KeyStateDS with Operation Functions and Tests Cases --- async_cache.go | 103 ++++++++++++----- async_cache_test.go | 261 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 302 insertions(+), 62 deletions(-) diff --git a/async_cache.go b/async_cache.go index 31d9640..143e6bb 100644 --- a/async_cache.go +++ b/async_cache.go @@ -5,55 +5,98 @@ import ( "sync" ) -type KeyState map[string]state - -// type keyState struct { -// ks KeyState -// } - +//Error Codes for keystates var ( - m sync.RWMutex + ErrInvalidKey = fmt.Errorf("found invalid key") + ErrItemNotPresent = fmt.Errorf("item not present") + ErrKeyStateNotPresent = fmt.Errorf("keystate datastructure not initialized") ) +//keyState structure +type keyStates struct { + keyState map[string]state //states{INPROCESS,DONE,INVALID,NOPRESENT} + mu *sync.RWMutex //RWmutex +} + type state int +//states declared in constants const ( INPROCESS state = iota DONE INVALID + NOPRESENT ) -func getState(s state) { - fmt.Println("state", s) +var ks keyStates + +//initializing ks keyStates +func init() { + ks.keyState = make(map[string]state) + ks.mu = &sync.RWMutex{} } -// func NewAsyncCache() keyState { -// var ks keyState -// ks = keyState{ks: make(map[string]state) -// } -// return ks -// } - -func (ks KeyState) Set(key string, S state) bool { - getState(S) - if len(ks) == 0 { - ks = make(KeyState) - } - if len(key) > 0 { - m.Lock() - ks[key] = S - m.Unlock() +//Set status/state with respective key in keyState +func (ks *keyStates) Set(key string, status state) (bool, error) { + ok := false + if ks != nil && ks.keyState != nil { + ks.mu.Lock() + ok = ks.set(key, status) + ks.mu.Unlock() } else { + return false, ErrKeyStateNotPresent + } + if !ok { + return false, ErrInvalidKey + } + return true, nil +} + +//utility set used in Set +func (ks *keyStates) set(k string, s state) bool { + if len(k) <= 0 { return false } + ks.keyState[k] = s return true } -func (ks KeyState) Get(key string) state { - if len(key) > 0 { - currS := ks[key] - return currS +//Get status/state of respective key in keyState +func (ks *keyStates) Get(key string) (state, error) { + var ( + status state + ok bool + ) + if !isValid(key) { + return INVALID, ErrInvalidKey + } + if ks != nil && ks.keyState != nil { + status, ok = ks.get(key) } else { - return INVALID + return INVALID, ErrKeyStateNotPresent + } + + if !ok { + return NOPRESENT, ErrItemNotPresent + } + + return status, nil +} + +//utility get for Get +func (ks *keyStates) get(k string) (state, bool) { + item, found := ks.keyState[k] + if !found { + return NOPRESENT, false + } + return item, true +} + +//checkKeyvalidity +func isValid(key string) bool { + if len(key) > 0 { + return true + } else { + return false } } diff --git a/async_cache_test.go b/async_cache_test.go index 3c4cdae..a31a690 100644 --- a/async_cache_test.go +++ b/async_cache_test.go @@ -1,68 +1,265 @@ package cache import ( + "sync" "testing" ) -func TestSet(t *testing.T) { - +func Test_keyStates_Set(t *testing.T) { + type fields struct { + keyState map[string]state + mu *sync.RWMutex + } type args struct { - key string - S state + key string + status state } tests := []struct { - name string - args args - want bool + name string + fields fields + args args + want bool + wantStatus state + wantErr error }{ { - name: "Default", + name: "With Valid key and state", + fields: fields{ + keyState: map[string]state{}, + mu: &sync.RWMutex{}, + }, args: args{ - key: "prof_123", - S: INPROCESS, + key: "prof_123", + status: INPROCESS, + }, + want: true, + wantStatus: INPROCESS, + wantErr: nil, + }, + { + name: "With InValid key and state", + fields: fields{ + keyState: map[string]state{}, + mu: &sync.RWMutex{}, + }, + args: args{ + key: "", + status: INPROCESS, + }, + want: false, + wantErr: ErrInvalidKey, + }, + { + name: "nil check for keystateSet", + fields: fields{ + keyState: nil, + mu: &sync.RWMutex{}, + }, + args: args{ + key: "", + status: INPROCESS, + }, + want: false, + wantErr: ErrKeyStateNotPresent, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ks := &keyStates{ + keyState: tt.fields.keyState, + mu: tt.fields.mu, + } + got, err := ks.Set(tt.args.key, tt.args.status) + if got != tt.want { + t.Errorf("keyStates.Set() = %v, want %v", got, tt.want) + } + if err != tt.wantErr { + t.Errorf("keyStates.Set() Error = %v, want %v", err, tt.wantErr) + } + + }) + } +} + +func Test_keyStates_set(t *testing.T) { + type fields struct { + keyState map[string]state + mu *sync.RWMutex + } + type args struct { + k string + s state + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + { + name: "With Valid key and state", + fields: fields{ + keyState: map[string]state{}, + }, + args: args{ + k: "prof_123", + s: INPROCESS, }, want: true, }, + { + name: "With Invalid key and valid state", + fields: fields{ + keyState: map[string]state{}, + }, + args: args{ + k: "", + s: INPROCESS, + }, + want: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - var ks KeyState - if got := ks.Set(tt.args.key, tt.args.S); got != tt.want { - t.Errorf("Set() = %v, want %v", got, tt.want) + ks := &keyStates{ + keyState: tt.fields.keyState, + mu: tt.fields.mu, + } + if got := ks.set(tt.args.k, tt.args.s); got != tt.want { + t.Errorf("keyStates.set() = %v, want %v", got, tt.want) } }) } } -func TestKeyState_Get(t *testing.T) { +func Test_keyStates_get(t *testing.T) { + type fields struct { + keyState map[string]state + mu *sync.RWMutex + } type args struct { - key string + k string } tests := []struct { - name string - ks KeyState - args args - want state + name string + fields fields + args args + want state + want1 bool }{ { - name: "Default", - ks: func() KeyState { - var ks KeyState - ks.Set("prof_id_123", INPROCESS) - return ks - }(), - args: args{ - key: "prof_123", + name: "With Valid key and valid state", + fields: fields{ + keyState: map[string]state{"prof_123": DONE}, }, - want: 0, + args: args{ + k: "prof_123", + }, + want: DONE, + want1: true, + }, + { + name: "With InValid key and invalid state ", + fields: fields{ + keyState: map[string]state{}, + }, + args: args{ + k: "", + }, + want: NOPRESENT, + want1: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - var ks KeyState - ks.Set("prof_id_123", INPROCESS) - if got := tt.ks.Get(tt.args.key); got != tt.want { - t.Errorf("KeyState.Get() = %v, want %v", got, tt.want) + ks := &keyStates{ + keyState: tt.fields.keyState, + mu: tt.fields.mu, + } + got, got1 := ks.get(tt.args.k) + if got != tt.want { + t.Errorf("keyStates.get() got = %v, want %v", got, tt.want) + } + if got1 != tt.want1 { + t.Errorf("keyStates.get() got1 = %v, want %v", got1, tt.want1) + } + }) + } +} + +func Test_keyStates_Get(t *testing.T) { + type fields struct { + keyState map[string]state + mu *sync.RWMutex + } + type args struct { + key string + } + tests := []struct { + name string + fields fields + args args + want state + wantErr error + }{ + { + name: "With Valid key and state as DONE", + fields: fields{ + keyState: map[string]state{"prof_123": DONE}, + }, + args: args{ + key: "prof_123", + }, + want: DONE, + wantErr: nil, + }, + { + name: "With InValid key and state", + fields: fields{ + keyState: map[string]state{"prof_123": DONE}, + }, + args: args{ + key: "", + }, + want: INVALID, + wantErr: ErrInvalidKey, + }, + { + name: "With Valid key and state as INPROCESS", + fields: fields{ + keyState: map[string]state{"prof_123": INPROCESS}, + }, + args: args{ + key: "prof_123", + }, + want: INPROCESS, + wantErr: nil, + }, + { + name: "nil check", + fields: fields{ + keyState: nil, + }, + args: args{ + key: "prof_123", + }, + want: INVALID, + wantErr: ErrKeyStateNotPresent, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ks := &keyStates{ + keyState: tt.fields.keyState, + mu: tt.fields.mu, + } + got, err := ks.Get(tt.args.key) + if err != tt.wantErr { + t.Errorf("keyStates.Get() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("keyStates.Get() = %v, want %v", got, tt.want) } }) }