chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,265 @@
|
||||
package inventory
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// createTestInventory creates an inventory with the specified toolsets for testing.
|
||||
// All toolsets are enabled by default using WithToolsets([]string{"all"}).
|
||||
func createTestInventory(toolsets []ToolsetMetadata) *Inventory {
|
||||
// Create tools for each toolset so they show up in AvailableToolsets()
|
||||
var tools []ServerTool
|
||||
for _, ts := range toolsets {
|
||||
tools = append(tools, ServerTool{
|
||||
Toolset: ts,
|
||||
})
|
||||
}
|
||||
|
||||
inv, _ := NewBuilder().
|
||||
SetTools(tools).
|
||||
WithToolsets([]string{"all"}).
|
||||
Build()
|
||||
|
||||
return inv
|
||||
}
|
||||
|
||||
func TestGenerateInstructions(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
toolsets []ToolsetMetadata
|
||||
expectedEmpty bool
|
||||
}{
|
||||
{
|
||||
name: "empty toolsets",
|
||||
toolsets: []ToolsetMetadata{},
|
||||
expectedEmpty: false, // base instructions are always included
|
||||
},
|
||||
{
|
||||
name: "toolset with instructions",
|
||||
toolsets: []ToolsetMetadata{
|
||||
{
|
||||
ID: "test",
|
||||
Description: "Test toolset",
|
||||
InstructionsFunc: func(_ *Inventory) string {
|
||||
return "Test instructions"
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedEmpty: false,
|
||||
},
|
||||
{
|
||||
name: "toolset without instructions",
|
||||
toolsets: []ToolsetMetadata{
|
||||
{
|
||||
ID: "test",
|
||||
Description: "Test toolset",
|
||||
},
|
||||
},
|
||||
expectedEmpty: false, // base instructions still included
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
inv := createTestInventory(tt.toolsets)
|
||||
result := generateInstructions(inv)
|
||||
|
||||
if tt.expectedEmpty {
|
||||
if result != "" {
|
||||
t.Errorf("Expected empty instructions but got: %s", result)
|
||||
}
|
||||
} else {
|
||||
if result == "" {
|
||||
t.Errorf("Expected non-empty instructions but got empty result")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateInstructionsWithDisableFlag(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
disableEnvValue string
|
||||
expectedEmpty bool
|
||||
}{
|
||||
{
|
||||
name: "DISABLE_INSTRUCTIONS=true returns empty",
|
||||
disableEnvValue: "true",
|
||||
expectedEmpty: true,
|
||||
},
|
||||
{
|
||||
name: "DISABLE_INSTRUCTIONS=false returns normal instructions",
|
||||
disableEnvValue: "false",
|
||||
expectedEmpty: false,
|
||||
},
|
||||
{
|
||||
name: "DISABLE_INSTRUCTIONS unset returns normal instructions",
|
||||
disableEnvValue: "",
|
||||
expectedEmpty: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Save original env value
|
||||
originalValue := os.Getenv("DISABLE_INSTRUCTIONS")
|
||||
defer func() {
|
||||
if originalValue == "" {
|
||||
os.Unsetenv("DISABLE_INSTRUCTIONS")
|
||||
} else {
|
||||
os.Setenv("DISABLE_INSTRUCTIONS", originalValue)
|
||||
}
|
||||
}()
|
||||
|
||||
// Set test env value
|
||||
if tt.disableEnvValue == "" {
|
||||
os.Unsetenv("DISABLE_INSTRUCTIONS")
|
||||
} else {
|
||||
os.Setenv("DISABLE_INSTRUCTIONS", tt.disableEnvValue)
|
||||
}
|
||||
|
||||
inv := createTestInventory([]ToolsetMetadata{
|
||||
{ID: "test", Description: "Test"},
|
||||
})
|
||||
result := generateInstructions(inv)
|
||||
|
||||
if tt.expectedEmpty {
|
||||
if result != "" {
|
||||
t.Errorf("Expected empty instructions but got: %s", result)
|
||||
}
|
||||
} else {
|
||||
if result == "" {
|
||||
t.Errorf("Expected non-empty instructions but got empty result")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestToolsetInstructionsFunc(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
toolsets []ToolsetMetadata
|
||||
expectedToContain string
|
||||
notExpectedToContain string
|
||||
}{
|
||||
{
|
||||
name: "toolset with context-aware instructions includes extra text when dependency present",
|
||||
toolsets: []ToolsetMetadata{
|
||||
{ID: "repos", Description: "Repos"},
|
||||
{
|
||||
ID: "pull_requests",
|
||||
Description: "PRs",
|
||||
InstructionsFunc: func(inv *Inventory) string {
|
||||
instructions := "PR base instructions"
|
||||
if inv.HasToolset("repos") {
|
||||
instructions += " PR template instructions"
|
||||
}
|
||||
return instructions
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedToContain: "PR template instructions",
|
||||
},
|
||||
{
|
||||
name: "toolset with context-aware instructions excludes extra text when dependency missing",
|
||||
toolsets: []ToolsetMetadata{
|
||||
{
|
||||
ID: "pull_requests",
|
||||
Description: "PRs",
|
||||
InstructionsFunc: func(inv *Inventory) string {
|
||||
instructions := "PR base instructions"
|
||||
if inv.HasToolset("repos") {
|
||||
instructions += " PR template instructions"
|
||||
}
|
||||
return instructions
|
||||
},
|
||||
},
|
||||
},
|
||||
notExpectedToContain: "PR template instructions",
|
||||
},
|
||||
{
|
||||
name: "toolset without InstructionsFunc returns no toolset-specific instructions",
|
||||
toolsets: []ToolsetMetadata{
|
||||
{ID: "test", Description: "Test without instructions"},
|
||||
},
|
||||
notExpectedToContain: "## Test",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
inv := createTestInventory(tt.toolsets)
|
||||
result := generateInstructions(inv)
|
||||
|
||||
if tt.expectedToContain != "" && !strings.Contains(result, tt.expectedToContain) {
|
||||
t.Errorf("Expected result to contain '%s', but it did not. Result: %s", tt.expectedToContain, result)
|
||||
}
|
||||
|
||||
if tt.notExpectedToContain != "" && strings.Contains(result, tt.notExpectedToContain) {
|
||||
t.Errorf("Did not expect result to contain '%s', but it did. Result: %s", tt.notExpectedToContain, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestGenerateInstructionsOnlyEnabledToolsets verifies that generateInstructions
|
||||
// only includes instructions from enabled toolsets, not all available toolsets.
|
||||
// This is a regression test for https://github.com/github/github-mcp-server/issues/1897
|
||||
func TestGenerateInstructionsOnlyEnabledToolsets(t *testing.T) {
|
||||
// Create tools for multiple toolsets
|
||||
reposToolset := ToolsetMetadata{
|
||||
ID: "repos",
|
||||
Description: "Repository tools",
|
||||
InstructionsFunc: func(_ *Inventory) string {
|
||||
return "REPOS_INSTRUCTIONS"
|
||||
},
|
||||
}
|
||||
issuesToolset := ToolsetMetadata{
|
||||
ID: "issues",
|
||||
Description: "Issue tools",
|
||||
InstructionsFunc: func(_ *Inventory) string {
|
||||
return "ISSUES_INSTRUCTIONS"
|
||||
},
|
||||
}
|
||||
prsToolset := ToolsetMetadata{
|
||||
ID: "pull_requests",
|
||||
Description: "PR tools",
|
||||
InstructionsFunc: func(_ *Inventory) string {
|
||||
return "PRS_INSTRUCTIONS"
|
||||
},
|
||||
}
|
||||
|
||||
tools := []ServerTool{
|
||||
{Toolset: reposToolset},
|
||||
{Toolset: issuesToolset},
|
||||
{Toolset: prsToolset},
|
||||
}
|
||||
|
||||
// Build inventory with only "repos" toolset enabled
|
||||
inv, err := NewBuilder().
|
||||
SetTools(tools).
|
||||
WithToolsets([]string{"repos"}).
|
||||
Build()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to build inventory: %v", err)
|
||||
}
|
||||
|
||||
result := generateInstructions(inv)
|
||||
|
||||
// Should contain instructions from enabled toolset
|
||||
if !strings.Contains(result, "REPOS_INSTRUCTIONS") {
|
||||
t.Errorf("Expected instructions to contain 'REPOS_INSTRUCTIONS' for enabled toolset, but it did not. Result: %s", result)
|
||||
}
|
||||
|
||||
// Should NOT contain instructions from non-enabled toolsets
|
||||
if strings.Contains(result, "ISSUES_INSTRUCTIONS") {
|
||||
t.Errorf("Did not expect instructions to contain 'ISSUES_INSTRUCTIONS' for disabled toolset, but it did. Result: %s", result)
|
||||
}
|
||||
if strings.Contains(result, "PRS_INSTRUCTIONS") {
|
||||
t.Errorf("Did not expect instructions to contain 'PRS_INSTRUCTIONS' for disabled toolset, but it did. Result: %s", result)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user