Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/workflows/dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Build and Test

on:
push:
branches:
- dev
pull_request:
branches:
- dev

jobs:
test:
name: Run Unit Tests
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'

- name: Run unit tests for thread-service
working-directory: code/services/thread-service
run: go test ./test/...

- name: Run unit tests for vote-service
working-directory: code/services/vote-service
run: go test ./test/...

- name: Run unit tests for search-service
working-directory: code/services/search-service
run: go test ./test/...

- name: Run unit tests for popular-service
working-directory: code/services/popular-service
run: go test ./test/...

- name: Run unit tests for community-service
working-directory: code/services/community-service
run: go test ./test/...

- name: Run unit tests for comment-service
working-directory: code/services/comment-service
run: go test ./test/...
File renamed without changes.
6 changes: 6 additions & 0 deletions code/services/comment-service/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,23 @@ toolchain go1.24.1

require (
gen v0.0.0-00010101000000-000000000000
github.com/stretchr/testify v1.10.0
google.golang.org/grpc v1.71.0
google.golang.org/protobuf v1.36.6
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

replace gen => ../../gen
18 changes: 18 additions & 0 deletions code/services/comment-service/go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
Expand All @@ -10,6 +13,16 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
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/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
Expand All @@ -36,3 +49,8 @@ google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
164 changes: 164 additions & 0 deletions code/services/comment-service/test/server_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package test

import (
"context"
"testing"

src "comment-service/src"
commentpb "gen/comment-service/pb"
dbpb "gen/db-service/pb"
models "gen/models/pb"
threadpb "gen/thread-service/pb"

"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
)

type MockDBClient struct {
dbpb.DBServiceClient
ListCommentsFunc func(ctx context.Context, req *dbpb.ListCommentsRequest, opts ...grpc.CallOption) (*dbpb.ListCommentsResponse, error)
CreateCommentFunc func(ctx context.Context, req *dbpb.CreateCommentRequest, opts ...grpc.CallOption) (*dbpb.CreateCommentResponse, error)
GetCommentFunc func(ctx context.Context, req *dbpb.GetCommentRequest, opts ...grpc.CallOption) (*models.Comment, error)
UpdateCommentFunc func(ctx context.Context, req *dbpb.UpdateCommentRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
DeleteCommentFunc func(ctx context.Context, req *dbpb.DeleteCommentRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
}

func (m *MockDBClient) ListComments(ctx context.Context, req *dbpb.ListCommentsRequest, opts ...grpc.CallOption) (*dbpb.ListCommentsResponse, error) {
return m.ListCommentsFunc(ctx, req, opts...)
}

func (m *MockDBClient) CreateComment(ctx context.Context, req *dbpb.CreateCommentRequest, opts ...grpc.CallOption) (*dbpb.CreateCommentResponse, error) {
return m.CreateCommentFunc(ctx, req, opts...)
}

func (m *MockDBClient) GetComment(ctx context.Context, req *dbpb.GetCommentRequest, opts ...grpc.CallOption) (*models.Comment, error) {
return m.GetCommentFunc(ctx, req, opts...)
}

func (m *MockDBClient) UpdateComment(ctx context.Context, req *dbpb.UpdateCommentRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
return m.UpdateCommentFunc(ctx, req, opts...)
}

func (m *MockDBClient) DeleteComment(ctx context.Context, req *dbpb.DeleteCommentRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
return m.DeleteCommentFunc(ctx, req, opts...)
}

type MockThreadClient struct {
threadpb.ThreadServiceClient
UpdateThreadFunc func(ctx context.Context, req *threadpb.UpdateThreadRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
}

func (m *MockThreadClient) UpdateThread(ctx context.Context, req *threadpb.UpdateThreadRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
return m.UpdateThreadFunc(ctx, req, opts...)
}

func TestCreateComment_Validation(t *testing.T) {
tests := []struct {
name string
req *commentpb.CreateCommentRequest
wantErr error
}{
{
name: "missing parent id",
req: &commentpb.CreateCommentRequest{},
wantErr: status.Error(codes.InvalidArgument, "Parent id is required"),
},
{
name: "missing content",
req: &commentpb.CreateCommentRequest{
ParentId: "123",
},
wantErr: status.Error(codes.InvalidArgument, "Content is required"),
},
{
name: "content too long",
req: &commentpb.CreateCommentRequest{
ParentId: "123",
Content: string(make([]byte, 501)),
},
wantErr: status.Error(codes.InvalidArgument, "Content exceeds maximum length of 500 characters"),
},
{
name: "valid request",
req: &commentpb.CreateCommentRequest{
ParentId: "123",
Content: "test comment",
ParentType: models.CommentParentType_THREAD,
},
wantErr: nil,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
server := &src.CommentServer{
DBClient: &MockDBClient{
CreateCommentFunc: func(ctx context.Context, req *dbpb.CreateCommentRequest, opts ...grpc.CallOption) (*dbpb.CreateCommentResponse, error) {
return &dbpb.CreateCommentResponse{
Id: "123",
}, nil
},
},
ThreadClient: &MockThreadClient{
UpdateThreadFunc: func(ctx context.Context, req *threadpb.UpdateThreadRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
return &emptypb.Empty{}, nil
},
},
}

_, err := server.CreateComment(context.Background(), tt.req)
if tt.wantErr != nil {
assert.Equal(t, tt.wantErr.Error(), err.Error())
} else {
assert.NoError(t, err)
}
})
}
}

func TestGetComment_Validation(t *testing.T) {
tests := []struct {
name string
req *commentpb.GetCommentRequest
wantErr error
}{
{
name: "missing id",
req: &commentpb.GetCommentRequest{},
wantErr: status.Error(codes.InvalidArgument, "Comment id is required"),
},
{
name: "valid request",
req: &commentpb.GetCommentRequest{
Id: "123",
},
wantErr: nil,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
server := &src.CommentServer{
DBClient: &MockDBClient{
GetCommentFunc: func(ctx context.Context, req *dbpb.GetCommentRequest, opts ...grpc.CallOption) (*models.Comment, error) {
return &models.Comment{
Id: "123",
Content: "test comment",
}, nil
},
},
ThreadClient: &MockThreadClient{},
}

_, err := server.GetComment(context.Background(), tt.req)
if tt.wantErr != nil {
assert.Equal(t, tt.wantErr.Error(), err.Error())
} else {
assert.NoError(t, err)
}
})
}
}
4 changes: 4 additions & 0 deletions code/services/community-service/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,21 @@ toolchain go1.24.1

require (
gen v0.0.0-00010101000000-000000000000
github.com/stretchr/testify v1.10.0
google.golang.org/grpc v1.71.0
google.golang.org/protobuf v1.36.6
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

replace gen => ../../gen
10 changes: 10 additions & 0 deletions code/services/community-service/go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
Expand All @@ -10,6 +12,11 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
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/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
Expand All @@ -36,3 +43,6 @@ google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Loading
Loading