From 7acf368bb29f4e7e75d3376716206c9198954948 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Wed, 8 Jul 2015 15:41:08 +0300 Subject: [PATCH] added index and tests --- users/users.go | 104 ++++++++++++++++++--- users/users_test.go | 215 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 285 insertions(+), 34 deletions(-) diff --git a/users/users.go b/users/users.go index ad4f5a473..e477418e4 100644 --- a/users/users.go +++ b/users/users.go @@ -32,39 +32,84 @@ type UserService interface { RemoveUser(UserProfile, *string) error UpdateUser(UserProfile, *string) error GetUsers(UserProfile, *[]*UserProfile) error + AddIndex([]string, *string) error } -type UserMap map[string]map[string]string +type UserMap struct { + Table map[string]map[string]string + Index map[string][]string +} -func (um UserMap) SetUser(up UserProfile, reply *string) error { - um[up.GetId()] = up.Profile +func NewUserMap() *UserMap { + return &UserMap{ + Table: make(map[string]map[string]string), + Index: make(map[string][]string), + } +} + +func (um *UserMap) SetUser(up UserProfile, reply *string) error { + um.Table[up.GetId()] = up.Profile *reply = utils.OK return nil } -func (um UserMap) RemoveUser(up UserProfile, reply *string) error { - delete(um, up.GetId()) + +func (um *UserMap) RemoveUser(up UserProfile, reply *string) error { + delete(um.Table, up.GetId()) *reply = utils.OK return nil } -func (um UserMap) UpdateUser(up UserProfile, reply *string) error { - m, found := um[up.GetId()] + +func (um *UserMap) UpdateUser(up UserProfile, reply *string) error { + m, found := um.Table[up.GetId()] if !found { *reply = utils.ErrNotFound.Error() return utils.ErrNotFound } if m == nil { - um[up.GetId()] = make(map[string]string, 0) + um.Table[up.GetId()] = make(map[string]string, 0) } for key, value := range up.Profile { - um[up.GetId()][key] = value + um.Table[up.GetId()][key] = value } *reply = utils.OK return nil } -func (um UserMap) GetUsers(up UserProfile, results *[]*UserProfile) error { - // no index + +func (um *UserMap) GetUsers(up UserProfile, results *[]*UserProfile) error { + table := um.Table // no index + + indexUnionKeys := make(map[string]bool) + // search index + if up.Tenant != "" { + if keys, found := um.Index[utils.ConcatenatedKey("Tenant", up.Tenant)]; found { + for _, key := range keys { + indexUnionKeys[key] = true + } + } + } + if up.UserName != "" { + if keys, found := um.Index[utils.ConcatenatedKey("UserName", up.UserName)]; found { + for _, key := range keys { + indexUnionKeys[key] = true + } + } + } + for k, v := range up.Profile { + if keys, found := um.Index[utils.ConcatenatedKey(k, v)]; found { + for _, key := range keys { + indexUnionKeys[key] = true + } + } + } + if len(indexUnionKeys) != 0 { + table = make(map[string]map[string]string) + for key := range indexUnionKeys { + table[key] = um.Table[key] + } + } + var candidates []*UserProfile - for key, values := range um { + for key, values := range table { if up.Tenant != "" && !strings.HasPrefix(key, up.Tenant+utils.CONCATENATED_KEY_SEP) { continue } @@ -88,8 +133,37 @@ func (um UserMap) GetUsers(up UserProfile, results *[]*UserProfile) error { nup.Profile[k] = v } candidates = append(candidates, nup) - *results = candidates } + *results = candidates + return nil +} + +func (um *UserMap) AddIndex(indexes []string, reply *string) error { + for key, values := range um.Table { + ud := &UserProfile{Profile: values} + ud.SetId(key) + for _, index := range indexes { + if index == "Tenant" { + if ud.Tenant != "" { + um.Index[utils.ConcatenatedKey(index, ud.Tenant)] = append(um.Index[utils.ConcatenatedKey(index, ud.Tenant)], key) + } + continue + } + if index == "UserName" { + if ud.UserName != "" { + um.Index[utils.ConcatenatedKey(index, ud.UserName)] = append(um.Index[utils.ConcatenatedKey(index, ud.UserName)], key) + } + continue + } + + for k, v := range ud.Profile { + if k == index && v != "" { + um.Index[utils.ConcatenatedKey(k, v)] = append(um.Index[utils.ConcatenatedKey(k, v)], key) + } + } + } + } + *reply = utils.OK return nil } @@ -118,3 +192,7 @@ func (ps *ProxyUserService) RemoveUser(ud UserProfile, reply *string) error { func (ps *ProxyUserService) GetUsers(ud UserProfile, users *[]*UserProfile) error { return ps.Client.Call("UserService.GetUsers", ud, users) } + +func (ps *ProxyUserService) AddIndex(indexes []string, reply *string) error { + return ps.Client.Call("UserService.AddIndex", indexes, reply) +} diff --git a/users/users_test.go b/users/users_test.go index 54c606a27..09bd6de81 100644 --- a/users/users_test.go +++ b/users/users_test.go @@ -7,14 +7,17 @@ import ( ) var testMap = UserMap{ - "test:user": map[string]string{"t": "v"}, - ":user": map[string]string{"t": "v"}, - "test:": map[string]string{"t": "v"}, - "test1:user1": map[string]string{"t": "v", "x": "y"}, + Table: map[string]map[string]string{ + "test:user": map[string]string{"t": "v"}, + ":user": map[string]string{"t": "v"}, + "test:": map[string]string{"t": "v"}, + "test1:user1": map[string]string{"t": "v", "x": "y"}, + }, + Index: make(map[string][]string), } func TestUsersAdd(t *testing.T) { - tm := UserMap{} + tm := NewUserMap() var r string up := UserProfile{ Tenant: "test", @@ -24,18 +27,18 @@ func TestUsersAdd(t *testing.T) { }, } tm.SetUser(up, &r) - p, found := tm[up.GetId()] + p, found := tm.Table[up.GetId()] if r != utils.OK || !found || p["t"] != "v" || - len(tm) != 1 || + len(tm.Table) != 1 || len(p) != 1 { t.Error("Error setting user: ", tm) } } func TestUsersUpdate(t *testing.T) { - tm := UserMap{} + tm := NewUserMap() var r string up := UserProfile{ Tenant: "test", @@ -45,28 +48,28 @@ func TestUsersUpdate(t *testing.T) { }, } tm.SetUser(up, &r) - p, found := tm[up.GetId()] + p, found := tm.Table[up.GetId()] if r != utils.OK || !found || p["t"] != "v" || - len(tm) != 1 || + len(tm.Table) != 1 || len(p) != 1 { t.Error("Error setting user: ", tm) } up.Profile["x"] = "y" tm.UpdateUser(up, &r) - p, found = tm[up.GetId()] + p, found = tm.Table[up.GetId()] if r != utils.OK || !found || p["x"] != "y" || - len(tm) != 1 || + len(tm.Table) != 1 || len(p) != 2 { t.Error("Error updating user: ", tm) } } func TestUsersUpdateNotFound(t *testing.T) { - tm := UserMap{} + tm := NewUserMap() var r string up := UserProfile{ Tenant: "test", @@ -84,7 +87,7 @@ func TestUsersUpdateNotFound(t *testing.T) { } func TestUsersUpdateInit(t *testing.T) { - tm := UserMap{} + tm := NewUserMap() var r string up := UserProfile{ Tenant: "test", @@ -99,18 +102,18 @@ func TestUsersUpdateInit(t *testing.T) { }, } tm.UpdateUser(up, &r) - p, found := tm[up.GetId()] + p, found := tm.Table[up.GetId()] if r != utils.OK || !found || p["t"] != "v" || - len(tm) != 1 || + len(tm.Table) != 1 || len(p) != 1 { t.Error("Error updating user: ", tm) } } func TestUsersRemove(t *testing.T) { - tm := UserMap{} + tm := NewUserMap() var r string up := UserProfile{ Tenant: "test", @@ -120,19 +123,19 @@ func TestUsersRemove(t *testing.T) { }, } tm.SetUser(up, &r) - p, found := tm[up.GetId()] + p, found := tm.Table[up.GetId()] if r != utils.OK || !found || p["t"] != "v" || - len(tm) != 1 || + len(tm.Table) != 1 || len(p) != 1 { t.Error("Error setting user: ", tm) } tm.RemoveUser(up, &r) - p, found = tm[up.GetId()] + p, found = tm.Table[up.GetId()] if r != utils.OK || found || - len(tm) != 0 { + len(tm.Table) != 0 { t.Error("Error removing user: ", tm) } } @@ -251,3 +254,173 @@ func TestUsersGetMissingIdTwo(t *testing.T) { t.Error("error getting users: ", results) } } + +func TestUsersAddIndex(t *testing.T) { + var r string + testMap.AddIndex([]string{"t"}, &r) + if r != utils.OK || + len(testMap.Index) != 1 || + len(testMap.Index[utils.ConcatenatedKey("t", "v")]) != 4 { + t.Error("error adding index: ", testMap.Index) + } +} + +func TestUsersAddIndexFull(t *testing.T) { + var r string + testMap.Index = make(map[string][]string) // reset index + testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r) + if r != utils.OK || + len(testMap.Index) != 6 || + len(testMap.Index[utils.ConcatenatedKey("t", "v")]) != 4 { + t.Error("error adding index: ", testMap.Index) + } +} + +func TestUsersAddIndexNone(t *testing.T) { + var r string + testMap.Index = make(map[string][]string) // reset index + testMap.AddIndex([]string{"test"}, &r) + if r != utils.OK || + len(testMap.Index) != 0 { + t.Error("error adding index: ", testMap.Index) + } +} + +func TestUsersGetFullIndex(t *testing.T) { + var r string + testMap.Index = make(map[string][]string) // reset index + testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r) + up := UserProfile{ + Tenant: "test", + UserName: "user", + Profile: map[string]string{ + "t": "v", + }, + } + results := make([]*UserProfile, 0) + testMap.GetUsers(up, &results) + if len(results) != 1 { + t.Error("error getting users: ", results) + } +} + +func TestUsersGetTenantIndex(t *testing.T) { + var r string + testMap.Index = make(map[string][]string) // reset index + testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r) + up := UserProfile{ + Tenant: "testX", + UserName: "user", + Profile: map[string]string{ + "t": "v", + }, + } + results := make([]*UserProfile, 0) + testMap.GetUsers(up, &results) + if len(results) != 0 { + t.Error("error getting users: ", results) + } +} + +func TestUsersGetUserNameIndex(t *testing.T) { + var r string + testMap.Index = make(map[string][]string) // reset index + testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r) + up := UserProfile{ + Tenant: "test", + UserName: "userX", + Profile: map[string]string{ + "t": "v", + }, + } + results := make([]*UserProfile, 0) + testMap.GetUsers(up, &results) + if len(results) != 0 { + t.Error("error getting users: ", results) + } +} + +func TestUsersGetNotFoundProfileIndex(t *testing.T) { + var r string + testMap.Index = make(map[string][]string) // reset index + testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r) + up := UserProfile{ + Tenant: "test", + UserName: "user", + Profile: map[string]string{ + "o": "p", + }, + } + results := make([]*UserProfile, 0) + testMap.GetUsers(up, &results) + if len(results) != 0 { + t.Error("error getting users: ", results) + } +} + +func TestUsersGetMissingTenantIndex(t *testing.T) { + var r string + testMap.Index = make(map[string][]string) // reset index + testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r) + up := UserProfile{ + UserName: "user", + Profile: map[string]string{ + "t": "v", + }, + } + results := make([]*UserProfile, 0) + testMap.GetUsers(up, &results) + if len(results) != 2 { + t.Error("error getting users: ", results) + } +} + +func TestUsersGetMissingUserNameIndex(t *testing.T) { + var r string + testMap.Index = make(map[string][]string) // reset index + testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r) + up := UserProfile{ + Tenant: "test", + Profile: map[string]string{ + "t": "v", + }, + } + results := make([]*UserProfile, 0) + testMap.GetUsers(up, &results) + if len(results) != 2 { + t.Error("error getting users: ", results) + } +} + +func TestUsersGetMissingIdIndex(t *testing.T) { + var r string + testMap.Index = make(map[string][]string) // reset index + testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r) + up := UserProfile{ + Profile: map[string]string{ + "t": "v", + }, + } + results := make([]*UserProfile, 0) + testMap.GetUsers(up, &results) + if len(results) != 4 { + t.Error("error getting users: ", results) + } +} + +func TestUsersGetMissingIdTwoINdex(t *testing.T) { + var r string + testMap.Index = make(map[string][]string) // reset index + testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r) + up := UserProfile{ + Profile: map[string]string{ + "t": "v", + "x": "y", + }, + } + results := make([]*UserProfile, 0) + testMap.GetUsers(up, &results) + if len(results) != 1 { + t.Error("error getting users: ", results) + } +}