Skip to content

Commit

Permalink
adding unit tests on goliac_server
Browse files Browse the repository at this point in the history
  • Loading branch information
nzin committed Aug 31, 2023
1 parent 8e4a366 commit 115b8d4
Show file tree
Hide file tree
Showing 6 changed files with 230 additions and 21 deletions.
1 change: 1 addition & 0 deletions browser/goliac-ui/src/components/DashboardApp.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template>
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">Goliac</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/' }">dashboard</el-breadcrumb-item>
</el-breadcrumb>
<el-divider />
Expand Down
7 changes: 7 additions & 0 deletions internal/engine/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ import (
* and mount it in memory
*/
type GoliacLocal interface {
GoliacLocalGit
GoliacLocalResources
}

type GoliacLocalGit interface {
Clone(accesstoken, repositoryUrl, branch string) error

// Return commits from tagname to HEAD
Expand All @@ -50,7 +55,9 @@ type GoliacLocal interface {

// Load and Validate from a local directory
LoadAndValidateLocal(fs afero.Fs, path string) ([]error, []entity.Warning)
}

type GoliacLocalResources interface {
Teams() map[string]*entity.Team // teamname, team definition
Repositories() map[string]*entity.Repository // reponame, repo definition
Users() map[string]*entity.User // github username, user definition
Expand Down
4 changes: 2 additions & 2 deletions internal/goliac.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type Goliac interface {
// flush remote cache
FlushCache()

GetLocal() engine.GoliacLocal
GetLocal() engine.GoliacLocalResources
}

type GoliacImpl struct {
Expand Down Expand Up @@ -72,7 +72,7 @@ func NewGoliacImpl() (Goliac, error) {
}, nil
}

func (g *GoliacImpl) GetLocal() engine.GoliacLocal {
func (g *GoliacImpl) GetLocal() engine.GoliacLocalResources {
return g.local
}

Expand Down
5 changes: 5 additions & 0 deletions internal/goliac_light.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import (
"github.com/spf13/afero"
)

/*
* This "version" of Goliac is here just to validate a local
* teams directory. It is mainly used for CI purpose when we need to validate
* a PR
*/
type GoliacLight interface {
// Validate a local teams directory
Validate(path string) error
Expand Down
63 changes: 44 additions & 19 deletions internal/goliac_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ import (
"github.com/sirupsen/logrus"
)

/*
* GoliacServer is here to run as a serve that
* - sync/reconciliate periodically
* - provide a REST API server
*/
type GoliacServer interface {
Serve()
GetLiveness(health.GetLivenessParams) middleware.Responder
Expand All @@ -37,10 +42,9 @@ type GoliacServer interface {
}

type GoliacServerImpl struct {
goliac Goliac
applyMutex gosync.Mutex
// when the server has finished to load the local configuration
ready bool
goliac Goliac
applyMutex gosync.Mutex
ready bool // when the server has finished to load the local configuration
lastSyncTime *time.Time
lastSyncError error
syncInterval int // in seconds time remaining between 2 sync
Expand Down Expand Up @@ -80,6 +84,9 @@ func (g *GoliacServerImpl) GetUser(params app.GetUserParams) middleware.Responde
Teams: make([]*models.Team, 0),
Repositories: make([]*models.Repository, 0),
}

// [teamname]team
userTeams := make(map[string]*models.Team)
local := g.goliac.GetLocal()
for teamname, team := range local.Teams() {
for _, owner := range team.Data.Owners {
Expand All @@ -89,7 +96,7 @@ func (g *GoliacServerImpl) GetUser(params app.GetUserParams) middleware.Responde
Members: team.Data.Members,
Owners: team.Data.Owners,
}
userdetails.Teams = append(userdetails.Teams, &team)
userTeams[teamname] = &team
break
}
}
Expand All @@ -100,40 +107,58 @@ func (g *GoliacServerImpl) GetUser(params app.GetUserParams) middleware.Responde
Members: team.Data.Members,
Owners: team.Data.Owners,
}
userdetails.Teams = append(userdetails.Teams, &team)
userTeams[teamname] = &team
break
}
}
}

teamRepo := make(map[string][]*entity.Repository)
for _, t := range userTeams {
userdetails.Teams = append(userdetails.Teams, t)
}

// let's sort repo per team
teamRepo := make(map[string]map[string]*entity.Repository)
for _, repo := range local.Repositories() {
if repo.Owner != nil {
teamRepo[*repo.Owner] = append(teamRepo[*repo.Owner], repo)
if _, ok := teamRepo[*repo.Owner]; !ok {
teamRepo[*repo.Owner] = make(map[string]*entity.Repository)
}
teamRepo[*repo.Owner][repo.Metadata.Name] = repo
}
for _, r := range repo.Data.Readers {
teamRepo[r] = append(teamRepo[*repo.Owner], repo)
if _, ok := teamRepo[r]; !ok {
teamRepo[r] = make(map[string]*entity.Repository)
}
teamRepo[r][repo.Metadata.Name] = repo
}
for _, w := range repo.Data.Writers {
teamRepo[w] = append(teamRepo[*repo.Owner], repo)
if _, ok := teamRepo[w]; !ok {
teamRepo[w] = make(map[string]*entity.Repository)
}
teamRepo[w][repo.Metadata.Name] = repo
}
}
fmt.Println(local.Repositories())
fmt.Println(teamRepo)

// [reponame]repo
userRepos := make(map[string]*entity.Repository)
for _, team := range userdetails.Teams {
if repositories, ok := teamRepo[team.Name]; ok {
for _, r := range repositories {
repo := models.Repository{
Name: r.Metadata.Name,
Public: r.Data.IsPublic,
Archived: r.Data.IsArchived,
}
userdetails.Repositories = append(userdetails.Repositories, &repo)
for n, r := range repositories {
userRepos[n] = r
}
}
}

for _, r := range userRepos {
repo := models.Repository{
Name: r.Metadata.Name,
Public: r.Data.IsPublic,
Archived: r.Data.IsArchived,
}
userdetails.Repositories = append(userdetails.Repositories, &repo)
}

return app.NewGetUserOK().WithPayload(&userdetails)
}

Expand Down
171 changes: 171 additions & 0 deletions internal/goliac_server_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package internal

import (
"fmt"
"testing"
"time"

"github.com/stretchr/testify/assert"

"github.com/Alayacare/goliac/internal/engine"
"github.com/Alayacare/goliac/internal/entity"
"github.com/Alayacare/goliac/swagger_gen/restapi/operations/app"
)

type GoliacLocalMock struct {
teams map[string]*entity.Team
repositories map[string]*entity.Repository
users map[string]*entity.User
externalUsers map[string]*entity.User
rulesets map[string]*entity.RuleSet
}

func (g *GoliacLocalMock) Teams() map[string]*entity.Team {
return g.teams
}
func (g *GoliacLocalMock) Repositories() map[string]*entity.Repository {
return g.repositories
}
func (g *GoliacLocalMock) Users() map[string]*entity.User {
return g.users
}
func (g *GoliacLocalMock) ExternalUsers() map[string]*entity.User {
return g.externalUsers
}
func (g *GoliacLocalMock) RuleSets() map[string]*entity.RuleSet {
return g.rulesets
}

func fixtureGoliacLocal() *GoliacLocalMock {
l := GoliacLocalMock{
teams: make(map[string]*entity.Team),
repositories: make(map[string]*entity.Repository),
users: make(map[string]*entity.User),
externalUsers: make(map[string]*entity.User),
rulesets: make(map[string]*entity.RuleSet),
}

// users
user1 := entity.User{}
user1.Metadata.Name = "user1"
user1.Data.GithubID = "github1"

user2 := entity.User{}
user2.Metadata.Name = "user2"
user2.Data.GithubID = "github2"

user3 := entity.User{}
user3.Metadata.Name = "user3"
user3.Data.GithubID = "github3"

l.users["user1"] = &user1
l.users["user2"] = &user2
l.users["user3"] = &user3

// external users
userE1 := entity.User{}
userE1.Metadata.Name = "userE1"
userE1.Data.GithubID = "githubE1"

l.externalUsers["userE1"] = &userE1

// teams
ateam := entity.Team{}
ateam.Metadata.Name = "ateam"
ateam.Data.Owners = []string{"user1"}
ateam.Data.Members = []string{"user3"}

mixteam := entity.Team{}
mixteam.Metadata.Name = "mixteam"
mixteam.Data.Owners = []string{"user1"}
mixteam.Data.Members = []string{"userE1"}

l.teams["ateam"] = &ateam
l.teams["mixteam"] = &mixteam

// repositories
repoA := entity.Repository{}
repoA.Metadata.Name = "repoA"
ownerA := "ateam"
repoA.Owner = &ownerA
repoA.Data.Readers = []string{}
repoA.Data.Writers = []string{}

repoB := entity.Repository{}
repoB.Metadata.Name = "repoB"
ownerB := "mixteam"
repoB.Owner = &ownerB
repoB.Data.Readers = []string{"ateam"}
repoB.Data.Writers = []string{}

l.repositories["repoA"] = &repoA
l.repositories["repoB"] = &repoB

return &l
}

type GoliacMock struct {
local engine.GoliacLocalResources
}

func (g *GoliacMock) LoadAndValidateGoliacOrganization(repositoryUrl, branch string) error {
return nil
}
func (g *GoliacMock) ApplyToGithub(dryrun bool, teamreponame string, branch string) error {
return nil
}
func (g *GoliacMock) UsersUpdate(repositoryUrl, branch string) error {
return nil
}
func (g *GoliacMock) Close() {
}
func (g *GoliacMock) FlushCache() {
}

func (g *GoliacMock) GetLocal() engine.GoliacLocalResources {
return g.local
}
func NewGoliacMock(local engine.GoliacLocalResources) Goliac {
mock := GoliacMock{
local: local,
}
return &mock
}

func TestAppGetUsers(t *testing.T) {
fixture := fixtureGoliacLocal()
goliac := NewGoliacMock(fixture)
now := time.Now()
server := GoliacServerImpl{
goliac: goliac,
ready: true,
lastSyncTime: &now,
lastSyncError: nil,
}

t.Run("happy path: get status", func(t *testing.T) {
res := server.GetStatus(app.GetStatusParams{})
payload := res.(*app.GetStatusOK)
assert.Equal(t, int64(2), payload.Payload.NbRepos)
assert.Equal(t, int64(2), payload.Payload.NbTeams)
assert.Equal(t, int64(3), payload.Payload.NbUsers)
assert.Equal(t, int64(1), payload.Payload.NbUsersExternal)
})

t.Run("happy path: list users", func(t *testing.T) {
res := server.GetUsers(app.GetUsersParams{})
payload := res.(*app.GetUsersOK)
assert.Equal(t, 4, len(payload.Payload.Users)) // 3 users + 1 external
})

t.Run("happy path: get user1", func(t *testing.T) {
res := server.GetUser(app.GetUserParams{UserID: "user1"})
payload := res.(*app.GetUserOK)
assert.Equal(t, 2, len(payload.Payload.Teams))
for _, r := range payload.Payload.Repositories {
fmt.Println(r.Name)
}
assert.Equal(t, 2, len(payload.Payload.Teams))
assert.Equal(t, 2, len(payload.Payload.Repositories))
})
}

0 comments on commit 115b8d4

Please sign in to comment.