Skip to main content
Glama
go_test.go14 kB
package parser_test import ( "testing" "github.com/st3v3nmw/sourcerer-mcp/internal/parser" "github.com/stretchr/testify/suite" ) type GoParserTestSuite struct { ParserBaseTestSuite } func (s *GoParserTestSuite) SetupSuite() { s.ParserBaseTestSuite.SetupSuite() var err error s.parser, err = parser.NewGoParser(s.workspaceRoot) s.Require().NoError(err) } func (s *GoParserTestSuite) TestFunctionParsing() { chunks := s.getChunks("go/functions.go") tests := []struct { name string path string summary string source string startLine int endLine int }{ { name: "Package Comments Hashing", path: "f2bcc925c6085e27", summary: "// Function tests", source: `// Function tests`, startLine: 1, endLine: 1, }, { name: "Simple Function", path: "SimpleFunction", summary: "func SimpleFunction(x int) string {", source: `// SimpleFunction demonstrates basic function parsing func SimpleFunction(x int) string { return fmt.Sprintf("%d", x) }`, startLine: 19, endLine: 22, }, { name: "Multiple Params Function", path: "MultipleParams", summary: "func MultipleParams(a string, b int, c bool) (string, error) {", source: `// MultipleParams shows function with multiple parameters and return values func MultipleParams(a string, b int, c bool) (string, error) { if c { return fmt.Sprintf("%s-%d", a, b), nil } return "", fmt.Errorf("invalid") }`, startLine: 24, endLine: 31, }, { name: "No Params Function", path: "NoParams", summary: "func NoParams() {", source: `// NoParams function with no parameters func NoParams() { fmt.Println("no params") }`, startLine: 33, endLine: 36, }, { name: "No Return Function", path: "NoReturn", summary: "func NoReturn(x int) {", source: `// NoReturn function with no return values func NoReturn(x int) { fmt.Printf("got %d\n", x) }`, startLine: 38, endLine: 41, }, { name: "Empty Function", path: "EmptyFunction", summary: "func EmptyFunction() {}", source: `// EmptyFunction with empty body func EmptyFunction() {}`, startLine: 43, endLine: 44, }, { name: "Complex Signature", path: "ComplexSignature", summary: "func ComplexSignature(ctx context.Context, data map[string]interface{}, opts ...func(*Config))...", source: `// ComplexSignature with various parameter types func ComplexSignature(ctx context.Context, data map[string]interface{}, opts ...func(*Config)) (*Result, error) { return &Result{Success: true}, nil }`, startLine: 46, endLine: 49, }, { name: "Variadic Function", path: "VariadicFunction", summary: "func VariadicFunction(first string, others ...int) int {", source: `// VariadicFunction with variadic parameters func VariadicFunction(first string, others ...int) int { return len(others) }`, startLine: 51, endLine: 54, }, { name: "Generic Function", path: "GenericFunction", summary: "func GenericFunction[T any](items []T) T {", source: `// GenericFunction with type parameters func GenericFunction[T any](items []T) T { var zero T if len(items) == 0 { return zero } return items[0] }`, startLine: 56, endLine: 64, }, { name: "Duplicate Name Function", path: "DuplicateNameFunction", summary: "func DuplicateNameFunction() string {", source: `// DuplicateNameFunction - testing duplicate function names func DuplicateNameFunction() string { return "duplicate name" }`, startLine: 66, endLine: 70, }, { name: "Duplicate Name Function - 2", path: "DuplicateNameFunction-2", summary: "func DuplicateNameFunction() string {", source: `// DuplicateNameFunction (2) // Testing duplicate function names func DuplicateNameFunction() string { return "duplicate name" }`, startLine: 72, endLine: 76, }, { name: "Duplicate Name Function - 3", path: "DuplicateNameFunction-3", summary: "func DuplicateNameFunction() string {", source: `// DuplicateNameFunction (3) // // Testing duplicate function names func DuplicateNameFunction() string { return "duplicate name" }`, startLine: 78, endLine: 83, }, { name: "Standalone Comment Hashing", path: "d5d69632b4d3fba5", summary: "// A standalone comment", source: `// A standalone comment`, startLine: 85, endLine: 85, }, } for _, test := range tests { s.Run(test.name, func() { chunk, exists := chunks[test.path] s.Require().True(exists, "chunk %s not found", test.path) s.Require().NotNil(chunk) s.Equal("src", chunk.Type) s.Equal(test.path, chunk.Path) s.Equal(test.summary, chunk.Summary) s.Equal(test.source, chunk.Source) s.Equal(test.startLine, int(chunk.StartLine)) s.Equal(test.endLine, int(chunk.EndLine)) s.Equal("go/functions.go::"+test.path, chunk.ID()) }) } } func (s *GoParserTestSuite) TestMethodParsing() { chunks := s.getChunks("go/methods.go") tests := []struct { name string path string summary string source string startLine int endLine int }{ { name: "Value Receiver Method", path: "User::GetName", summary: "func (u User) GetName() string {", source: `// GetName is a value receiver method func (u User) GetName() string { return u.Name }`, startLine: 9, endLine: 12, }, { name: "Pointer Receiver Method", path: "User::SetName", summary: "func (u *User) SetName(name string) {", source: `// SetName is a pointer receiver method func (u *User) SetName(name string) { u.Name = name }`, startLine: 14, endLine: 17, }, { name: "Service Add User Method", path: "Service::AddUser", summary: "func (s *Service) AddUser(user User) {", source: `// AddUser adds a user to the service func (s *Service) AddUser(user User) { s.users = append(s.users, user) }`, startLine: 24, endLine: 27, }, { name: "Service Find User Method", path: "Service::FindUser", summary: "func (s *Service) FindUser(id int) *User {", source: `// FindUser finds a user by ID func (s *Service) FindUser(id int) *User { for i := range s.users { if s.users[i].ID == id { return &s.users[i] } } return nil }`, startLine: 29, endLine: 38, }, { name: "Service Count Method", path: "Service::Count", summary: "func (s Service) Count() int {", source: `// Count returns the number of users func (s Service) Count() int { return len(s.users) }`, startLine: 40, endLine: 43, }, { name: "Generic Pointer Receiver Method", path: "Repository::Add", summary: "func (r *Repository[T]) Add(item T) {", source: `// Add adds an item to the repository func (r *Repository[T]) Add(item T) { r.items = append(r.items, item) }`, startLine: 50, endLine: 53, }, { name: "Generic Value Receiver Method", path: "Repository::Get", summary: "func (r Repository[T]) Get(index int) T {", source: `// Get retrieves an item by index func (r Repository[T]) Get(index int) T { return r.items[index] }`, startLine: 55, endLine: 58, }, { name: "Generic Size Method", path: "Repository::Size", summary: "func (r Repository[T]) Size() int {", source: `// Size returns the number of items func (r Repository[T]) Size() int { return len(r.items) }`, startLine: 60, endLine: 63, }, { name: "Service A Helper Method", path: "ServiceA::Helper", summary: "func (s ServiceA) Helper() string {", source: `func (s ServiceA) Helper() string { return "service A helper" }`, startLine: 69, endLine: 71, }, { name: "Service B Helper Method", path: "ServiceB::Helper", summary: "func (s ServiceB) Helper() string {", source: `func (s ServiceB) Helper() string { return "service B helper" }`, startLine: 73, endLine: 75, }, } for _, test := range tests { s.Run(test.name, func() { chunk, exists := chunks[test.path] s.Require().True(exists, "chunk %s not found", test.path) s.Require().NotNil(chunk) s.Equal("src", chunk.Type) s.Equal(test.path, chunk.Path) s.Equal(test.summary, chunk.Summary) s.Equal(test.source, chunk.Source) s.Equal(test.startLine, int(chunk.StartLine)) s.Equal(test.endLine, int(chunk.EndLine)) s.Equal("go/methods.go::"+test.path, chunk.ID()) }) } } func (s *GoParserTestSuite) TestTypeParsing() { chunks := s.getChunks("go/types.go") tests := []struct { name string path string summary string source string startLine int endLine int }{ { name: "Basic Struct", path: "BasicStruct", summary: "type BasicStruct struct {", source: `// BasicStruct demonstrates struct type parsing type BasicStruct struct { Field1 string Field2 int }`, startLine: 3, endLine: 7, }, { name: "Empty Struct", path: "EmptyStruct", summary: "type EmptyStruct struct{}", source: `// EmptyStruct demonstrates empty struct type EmptyStruct struct{}`, startLine: 9, endLine: 10, }, { name: "Embedded Struct", path: "EmbeddedStruct", summary: "type EmbeddedStruct struct {", source: `// EmbeddedStruct demonstrates struct with embedded fields type EmbeddedStruct struct { BasicStruct ExtraField bool }`, startLine: 12, endLine: 16, }, { name: "Simple Interface", path: "SimpleInterface", summary: "type SimpleInterface interface {", source: `// SimpleInterface demonstrates interface parsing type SimpleInterface interface { Method1() string Method2(int) error }`, startLine: 18, endLine: 22, }, { name: "Empty Interface", path: "EmptyInterface", summary: "type EmptyInterface interface{}", source: `// EmptyInterface demonstrates empty interface type EmptyInterface interface{}`, startLine: 24, endLine: 25, }, { name: "Embedded Interface", path: "EmbeddedInterface", summary: "type EmbeddedInterface interface {", source: `// EmbeddedInterface demonstrates interface composition type EmbeddedInterface interface { SimpleInterface Method3() bool }`, startLine: 27, endLine: 31, }, { name: "Generic Type", path: "GenericType", summary: "type GenericType[T any] struct {", source: `// GenericType demonstrates generic type declaration type GenericType[T any] struct { Value T }`, startLine: 33, endLine: 36, }, { name: "Constrained Generic", path: "ConstrainedGeneric", summary: "type ConstrainedGeneric[T comparable] struct {", source: `// ConstrainedGeneric demonstrates generic with constraints type ConstrainedGeneric[T comparable] struct { Key T Value string }`, startLine: 38, endLine: 42, }, { name: "Multiple Generics", path: "MultipleGenerics", summary: "type MultipleGenerics[K comparable, V any] map[K]V", source: `// MultipleGenerics demonstrates multiple type parameters type MultipleGenerics[K comparable, V any] map[K]V`, startLine: 44, endLine: 45, }, { name: "Type Alias", path: "TypeAlias", summary: "type TypeAlias = string", source: `// TypeAlias demonstrates type alias type TypeAlias = string`, startLine: 47, endLine: 48, }, { name: "Custom Type", path: "CustomType", summary: "type CustomType string", source: `// CustomType demonstrates custom type based on existing type type CustomType string`, startLine: 50, endLine: 51, }, { name: "Consts Block Hashing", path: "796012d7ee1311f0", summary: "const (", source: `// Constants for testing const parsing const ( StatusActive = "active" StatusInactive = "inactive" MaxRetries = 5 )`, startLine: 53, endLine: 58, }, { name: "Single Constant", path: "DefaultTimeout", summary: "const DefaultTimeout = 30", source: `// Single constant const DefaultTimeout = 30`, startLine: 60, endLine: 61, }, { name: "Vars Block Hashing", path: "3a12064c73be460c", summary: "var (", source: `// Variables for testing var parsing var ( GlobalCounter int SystemReady bool = true ConfigPath string )`, startLine: 63, endLine: 68, }, { name: "Another Multi Var Declaration", path: "b9303a3de4b66c8b", summary: "var x, y string", source: `// Another multi var declaration var x, y string`, startLine: 70, endLine: 71, }, { name: "Single Variable", path: "DefaultConfig", summary: "var DefaultConfig = BasicStruct{", source: `// Single variable var DefaultConfig = BasicStruct{ Field1: "default", Field2: 42, }`, startLine: 73, endLine: 77, }, } for _, test := range tests { s.Run(test.name, func() { chunk, exists := chunks[test.path] s.Require().True(exists, "chunk %s not found", test.path) s.Require().NotNil(chunk) s.Equal("src", chunk.Type) s.Equal(test.path, chunk.Path) s.Equal(test.summary, chunk.Summary) s.Equal(test.source, chunk.Source) s.Equal(test.startLine, int(chunk.StartLine)) s.Equal(test.endLine, int(chunk.EndLine)) s.Equal("go/types.go::"+test.path, chunk.ID()) }) } } func (s *GoParserTestSuite) TestTestFileParsing() { chunks := s.getChunks("go/tests_test.go") chunk, exists := chunks["TestSimple"] s.Require().True(exists, "chunk %s not found", "TestSimple") s.Require().NotNil(chunk) s.Equal("tests", chunk.Type) s.Equal("TestSimple", chunk.Path) s.Equal("func TestSimple(t *testing.T) {", chunk.Summary) s.Equal(`// TestSimple is a basic test function func TestSimple(t *testing.T) { if 1+1 != 2 { t.Error("math is broken") } }`, chunk.Source) s.Equal(5, int(chunk.StartLine)) s.Equal(10, int(chunk.EndLine)) s.Equal("go/tests_test.go::TestSimple", chunk.ID()) } func TestGoParserTestSuite(t *testing.T) { suite.Run(t, new(GoParserTestSuite)) }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/st3v3nmw/sourcerer-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server