diff --git a/backend/Makefile b/backend/Makefile index dcc3eab..1347ab4 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -36,7 +36,7 @@ fmt: ## Format code printf "${GREEN} Code formatted.\n\n"; \ .PHONY: test-ci -test: ## Run tests for CI +test-ci: ## Run tests for CI printf "${GREEN}Run all tests\n\n${WHITE}"; \ go clean -cache -testcache -i -r; \ go test -cover -race -json -v ./... ; \ diff --git a/backend/graph/schema.resolvers_test.go b/backend/graph/schema.resolvers_test.go index 32900a1..37c1490 100644 --- a/backend/graph/schema.resolvers_test.go +++ b/backend/graph/schema.resolvers_test.go @@ -37,7 +37,7 @@ import ( ) // NOTE : This test does not use testify.suite because -// Testify suite does not allow to run tests parallel, which is considered inevitable for resolver tests. +// Testify suite does not allow to run tests Parallel, which is considered inevitable for resolver tests. var e *echo.Echo var db *gorm.DB var migrationFilePath = "../db/migrations" diff --git a/backend/pkg/textdic/parser.go b/backend/pkg/textdic/parser.go index a8e4516..9c3494a 100644 --- a/backend/pkg/textdic/parser.go +++ b/backend/pkg/textdic/parser.go @@ -5,9 +5,11 @@ package textdic import __yyfmt__ "fmt" -// Define Node and Nodes types -// //line ./pkg/textdic/parser.y:2 + +import "sync" + +// Define Node and Nodes types type Node struct { Word string Definition string @@ -15,9 +17,10 @@ type Node struct { type Nodes []Node -//line ./pkg/textdic/parser.y:14 +//line ./pkg/textdic/parser.y:16 type yySymType struct { yys int + mutex sync.RWMutex str string node Node nodes Nodes @@ -42,7 +45,7 @@ const yyEofCode = 1 const yyErrCode = 2 const yyInitialStackSize = 16 -//line ./pkg/textdic/parser.y:43 +//line ./pkg/textdic/parser.y:46 type Parser interface { Parse(yyLexer) int @@ -51,15 +54,21 @@ type Parser interface { func NewParser(yylex yyLexer) Parser { yyparser := &yyParserImpl{} + yyparser.lval.mutex.RLock() + defer yyparser.lval.mutex.RUnlock() yyparser.Parse(yylex) return yyparser } func (yyrcvr *yyParserImpl) setNodes(nodes []Node) { + yyrcvr.lval.mutex.RLock() + defer yyrcvr.lval.mutex.RUnlock() yyrcvr.lval.nodes = nodes } func (yyrcvr *yyParserImpl) GetNodes() []Node { + yyrcvr.lval.mutex.RLock() + defer yyrcvr.lval.mutex.RUnlock() return yyrcvr.lval.nodes } @@ -453,14 +462,14 @@ yydefault: case 1: yyDollar = yyS[yypt-1 : yypt+1] -//line ./pkg/textdic/parser.y:30 +//line ./pkg/textdic/parser.y:33 { yyVAL.nodes = yyDollar[1].nodes yyrcvr.setNodes(yyDollar[1].nodes) } case 2: yyDollar = yyS[yypt-2 : yypt+1] -//line ./pkg/textdic/parser.y:34 +//line ./pkg/textdic/parser.y:37 { if yyDollar[2].node.Word != "" { yyVAL.nodes = append(yyDollar[1].nodes, yyDollar[2].node) @@ -470,7 +479,7 @@ yydefault: } case 3: yyDollar = yyS[yypt-1 : yypt+1] -//line ./pkg/textdic/parser.y:35 +//line ./pkg/textdic/parser.y:38 { if yyDollar[1].node.Word != "" { yyVAL.nodes = []Node{yyDollar[1].node} @@ -480,13 +489,13 @@ yydefault: } case 4: yyDollar = yyS[yypt-2 : yypt+1] -//line ./pkg/textdic/parser.y:39 +//line ./pkg/textdic/parser.y:42 { yyVAL.node = Node{Word: yyDollar[1].str, Definition: yyDollar[2].str} } case 5: yyDollar = yyS[yypt-1 : yypt+1] -//line ./pkg/textdic/parser.y:40 +//line ./pkg/textdic/parser.y:43 { yyVAL.node = Node{} } diff --git a/backend/pkg/textdic/parser.y b/backend/pkg/textdic/parser.y index 60162b3..a01534b 100644 --- a/backend/pkg/textdic/parser.y +++ b/backend/pkg/textdic/parser.y @@ -1,6 +1,8 @@ %{ package textdic +import "sync" + // Define Node and Nodes types type Node struct { Word string @@ -12,6 +14,7 @@ type Nodes []Node %} %union { + mutex sync.RWMutex str string node Node nodes Nodes @@ -49,14 +52,20 @@ type Parser interface { func NewParser(yylex yyLexer) Parser { yyparser := &yyParserImpl{} + yyparser.lval.mutex.RLock() + defer yyparser.lval.mutex.RUnlock() yyparser.Parse(yylex) return yyparser } func (yyrcvr *yyParserImpl) setNodes(nodes []Node) { + yyrcvr.lval.mutex.RLock() + defer yyrcvr.lval.mutex.RUnlock() yyrcvr.lval.nodes = nodes } func (yyrcvr *yyParserImpl) GetNodes() []Node { + yyrcvr.lval.mutex.RLock() + defer yyrcvr.lval.mutex.RUnlock() return yyrcvr.lval.nodes } diff --git a/backend/pkg/textdic/parser_test.go b/backend/pkg/textdic/parser_test.go index d0daeea..6aead0b 100644 --- a/backend/pkg/textdic/parser_test.go +++ b/backend/pkg/textdic/parser_test.go @@ -2,13 +2,17 @@ package textdic import ( "github.com/stretchr/testify/assert" + "sync" "testing" ) +var mutext sync.RWMutex + func TestParser(t *testing.T) { + t.Parallel() + // Run TestParserService t.Run("TestSmoke", func(t *testing.T) { - t.Parallel() // Test input var input = ` @@ -58,7 +62,8 @@ There is no leeway to provide services free of charge for the sake of others. } for _, tc := range testCases { - + mutext.RLock() + defer mutext.RUnlock() // Create a new lexer with the input l := newLexer(tc.input) @@ -81,7 +86,8 @@ There is no leeway to provide services free of charge for the sake of others. // New test case to check for errors t.Run("TestErrors", func(t *testing.T) { t.Parallel() - + mutext.RLock() + defer mutext.RUnlock() // Test input that will cause a parsing error var input = ` trot out 自慢げに話題に持ち出す @@ -90,8 +96,10 @@ trot out 自慢げに話題に持ち出す ` // Create a new lexer with the input l := newLexer(input) - yyDebug = 5 - yyErrorVerbose = true + + // For Debug + //yyDebug = 5 + //yyErrorVerbose = true // Parse the input using the parser instance parser := NewParser(l) diff --git a/backend/pkg/textdic/text_dictionary_service.go b/backend/pkg/textdic/text_dictionary_service.go index 9da3143..843cec6 100644 --- a/backend/pkg/textdic/text_dictionary_service.go +++ b/backend/pkg/textdic/text_dictionary_service.go @@ -3,10 +3,13 @@ package textdic import ( "encoding/base64" "fmt" + "sync" ) // textDictionaryService struct definition -type textDictionaryService struct{} +type textDictionaryService struct { + mu sync.RWMutex +} // TextDictionaryService defines the methods for processing text dictionaries. type TextDictionaryService interface { @@ -21,11 +24,15 @@ func NewTextDictionaryService() TextDictionaryService { // Process processes a given dictionary string and returns the parsed Nodes or an error func (tds *textDictionaryService) Process(dic string) ([]Node, []error) { + tds.mu.RLock() + defer tds.mu.RUnlock() + // Use the new parser to parse the input l := newLexer(dic) // Parse the input using the new parser - yyErrorVerbose = true + //yyErrorVerbose = true + parser := NewParser(l) parsedNodes := parser.GetNodes() diff --git a/backend/pkg/textdic/text_dictionary_service_test.go b/backend/pkg/textdic/text_dictionary_service_test.go index 7528878..7899625 100644 --- a/backend/pkg/textdic/text_dictionary_service_test.go +++ b/backend/pkg/textdic/text_dictionary_service_test.go @@ -5,7 +5,12 @@ import ( "testing" ) +var mu sync.RWMutex + func TestParserService(t *testing.T) { + t.Helper() + t.Parallel() + // Test input var input = ` trot out 自慢げに話題に持ち出す @@ -80,12 +85,16 @@ Hold me accountable for 自分の行動の結果を受け入れ、罰を受け tc := tc // capture range variable to avoid issues in parallel tests t.Run(tc.name, func(t *testing.T) { t.Parallel() // Mark the test to run in parallel + mu.RLock() + defer mu.RUnlock() // Create a new parser service service := NewTextDictionaryService() - yyDebug = 5 - yyErrorVerbose = true + // For Debug + //yyDebug = 5 + //yyErrorVerbose = true + // Process the dictionary input parsedNodes, err := service.Process(tc.input) if err != nil { @@ -108,6 +117,7 @@ Hold me accountable for 自分の行動の結果を受け入れ、罰を受け // Run TestParserService_ErrorCases t.Run("TestParserService_ErrorCases", func(t *testing.T) { + t.Parallel() // Mark the test to run in parallel // Define error test cases errorTestCases := []struct { name string @@ -133,6 +143,8 @@ Hold me accountable for 自分の行動の結果を受け入れ、罰を受け tc := tc // capture range variable to avoid issues in parallel tests t.Run(tc.name, func(t *testing.T) { t.Parallel() // Mark the test to run in parallel + mu.RLock() + defer mu.RUnlock() // Create a new parser service service := NewTextDictionaryService() diff --git a/backend/pkg/usecases/swipe_manager/swipe_manager_usecase_test.go b/backend/pkg/usecases/swipe_manager/swipe_manager_usecase_test.go index 08fcd66..f8bb692 100644 --- a/backend/pkg/usecases/swipe_manager/swipe_manager_usecase_test.go +++ b/backend/pkg/usecases/swipe_manager/swipe_manager_usecase_test.go @@ -9,7 +9,6 @@ import ( repo "backend/pkg/repository" "backend/testutils" "context" - "github.com/labstack/echo/v4" "log" "math/rand" "strconv" @@ -21,7 +20,6 @@ import ( ) var db *gorm.DB -var e *echo.Echo var sv services.Services var userService services.UserService var cardGroupService services.CardGroupService