/ go / test / suite_test.go
suite_test.go
  1  package test
  2  
  3  import (
  4  	"context"
  5  	"os"
  6  	"testing"
  7  	"time"
  8  
  9  	"github.com/TransformerOS/kamaji-go/internal/agents"
 10  	"github.com/TransformerOS/kamaji-go/internal/config"
 11  	"github.com/TransformerOS/kamaji-go/internal/providers"
 12  	"github.com/TransformerOS/kamaji-go/internal/tools"
 13  	"github.com/TransformerOS/kamaji-go/internal/types"
 14  )
 15  
 16  // TestSuite runs the complete Kamaji test suite
 17  func TestSuite(t *testing.T) {
 18  	t.Run("Config", testConfig)
 19  	t.Run("Tools", testTools)
 20  	t.Run("Providers", testProviders)
 21  	t.Run("Agents", testAgents)
 22  	t.Run("Integration", testIntegration)
 23  }
 24  
 25  func testConfig(t *testing.T) {
 26  	t.Run("LoadDefault", func(t *testing.T) {
 27  		cfg, err := config.Load()
 28  		if err != nil {
 29  			t.Fatalf("Failed to load config: %v", err)
 30  		}
 31  		
 32  		if cfg.Provider == "" {
 33  			t.Error("Provider should not be empty")
 34  		}
 35  		
 36  		if cfg.Model == "" {
 37  			t.Error("Model should not be empty")
 38  		}
 39  		
 40  		if cfg.Temperature < 0 || cfg.Temperature > 1 {
 41  			t.Errorf("Temperature should be 0-1, got %f", cfg.Temperature)
 42  		}
 43  	})
 44  	
 45  	t.Run("SaveLoad", func(t *testing.T) {
 46  		cfg := &config.Config{
 47  			Provider:    "test",
 48  			Model:       "test-model",
 49  			BaseURL:     "http://test",
 50  			Temperature: 0.5,
 51  			MaxTokens:   1000,
 52  		}
 53  		
 54  		if err := config.Save(cfg); err != nil {
 55  			t.Fatalf("Failed to save config: %v", err)
 56  		}
 57  		
 58  		loaded, err := config.Load()
 59  		if err != nil {
 60  			t.Fatalf("Failed to load saved config: %v", err)
 61  		}
 62  		
 63  		if loaded.Provider != cfg.Provider {
 64  			t.Errorf("Expected provider %s, got %s", cfg.Provider, loaded.Provider)
 65  		}
 66  	})
 67  }
 68  
 69  func testTools(t *testing.T) {
 70  	allTools := tools.GetAll()
 71  	
 72  	t.Run("ToolsAvailable", func(t *testing.T) {
 73  		if len(allTools) == 0 {
 74  			t.Fatal("No tools available")
 75  		}
 76  		
 77  		expectedTools := []string{
 78  			"file_read", "file_write", "list_directory", "file_append",
 79  			"shell_execute", "get_current_directory", "change_directory",
 80  			"git_status", "git_add", "git_commit", "git_diff", "git_log",
 81  		}
 82  		
 83  		toolMap := make(map[string]bool)
 84  		for _, tool := range allTools {
 85  			toolMap[tool.Name()] = true
 86  		}
 87  		
 88  		for _, expected := range expectedTools {
 89  			if !toolMap[expected] {
 90  				t.Errorf("Expected tool %s not found", expected)
 91  			}
 92  		}
 93  	})
 94  	
 95  	t.Run("ToolInterface", func(t *testing.T) {
 96  		for _, tool := range allTools {
 97  			if tool.Name() == "" {
 98  				t.Errorf("Tool %T has empty name", tool)
 99  			}
100  			
101  			if tool.Description() == "" {
102  				t.Errorf("Tool %s has empty description", tool.Name())
103  			}
104  		}
105  	})
106  	
107  	t.Run("FileReadTool", func(t *testing.T) {
108  		tmpFile := createTempFile(t, "test content")
109  		defer os.Remove(tmpFile)
110  		
111  		tool := tools.FileReadTool{}
112  		result, err := tool.Call(context.Background(), tmpFile)
113  		if err != nil {
114  			t.Fatalf("FileReadTool failed: %v", err)
115  		}
116  		
117  		if result != "test content" {
118  			t.Errorf("Expected 'test content', got '%s'", result)
119  		}
120  	})
121  	
122  	t.Run("ShellExecuteTool", func(t *testing.T) {
123  		tool := tools.ShellExecuteTool{}
124  		result, err := tool.Call(context.Background(), "echo hello")
125  		if err != nil {
126  			t.Fatalf("ShellExecuteTool failed: %v", err)
127  		}
128  		
129  		if !strings.Contains(result, "hello") {
130  			t.Errorf("Expected output to contain 'hello', got '%s'", result)
131  		}
132  	})
133  }
134  
135  func testProviders(t *testing.T) {
136  	t.Run("MockProvider", func(t *testing.T) {
137  		provider := providers.NewMockProvider("http://test", "test-model")
138  		
139  		result, err := provider.Call(context.Background(), "test prompt")
140  		if err != nil {
141  			t.Fatalf("Mock provider failed: %v", err)
142  		}
143  		
144  		if !strings.Contains(result, "test prompt") {
145  			t.Errorf("Expected response to contain prompt, got '%s'", result)
146  		}
147  	})
148  	
149  	t.Run("GetLLM", func(t *testing.T) {
150  		// This will use mock provider since no real providers are configured
151  		llm, err := providers.GetLLM(providers.LLMOptions{})
152  		if err != nil {
153  			t.Fatalf("Failed to get LLM: %v", err)
154  		}
155  		
156  		if llm == nil {
157  			t.Fatal("LLM is nil")
158  		}
159  	})
160  }
161  
162  func testAgents(t *testing.T) {
163  	t.Run("BasicAgentExecutor", func(t *testing.T) {
164  		llm := providers.NewMockProvider("http://test", "test-model")
165  		availableTools := []tools.Tool{tools.FileReadTool{}}
166  		
167  		agent := agents.NewBasicAgentExecutor(llm, availableTools, false)
168  		if agent == nil {
169  			t.Fatal("Agent is nil")
170  		}
171  		
172  		status := agent.GetStatus()
173  		if status.Status != "ready" {
174  			t.Errorf("Expected status 'ready', got '%s'", status.Status)
175  		}
176  		
177  		agentTools := agent.GetTools()
178  		if len(agentTools) != 1 {
179  			t.Errorf("Expected 1 tool, got %d", len(agentTools))
180  		}
181  	})
182  	
183  	t.Run("AgentExecution", func(t *testing.T) {
184  		llm := providers.NewMockProvider("http://test", "test-model")
185  		availableTools := []tools.Tool{}
186  		
187  		agent := agents.NewBasicAgentExecutor(llm, availableTools, false)
188  		
189  		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
190  		defer cancel()
191  		
192  		result, err := agent.Execute(ctx, "test task")
193  		if err != nil {
194  			t.Fatalf("Agent execution failed: %v", err)
195  		}
196  		
197  		if result == "" {
198  			t.Error("Agent returned empty result")
199  		}
200  		
201  		status := agent.GetStatus()
202  		if status.TasksRun != 1 {
203  			t.Errorf("Expected 1 task run, got %d", status.TasksRun)
204  		}
205  	})
206  }
207  
208  func testIntegration(t *testing.T) {
209  	t.Run("FullWorkflow", func(t *testing.T) {
210  		// Create temp file
211  		tmpFile := createTempFile(t, "integration test content")
212  		defer os.Remove(tmpFile)
213  		
214  		// Get LLM and tools
215  		llm, err := providers.GetLLM(providers.LLMOptions{})
216  		if err != nil {
217  			t.Fatalf("Failed to get LLM: %v", err)
218  		}
219  		
220  		allTools := tools.GetAll()
221  		if len(allTools) == 0 {
222  			t.Fatal("No tools available for integration test")
223  		}
224  		
225  		// Create agent
226  		agent := agents.NewBasicAgentExecutor(llm, allTools, false)
227  		
228  		// Execute task
229  		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
230  		defer cancel()
231  		
232  		task := "List the current directory"
233  		result, err := agent.Execute(ctx, task)
234  		if err != nil {
235  			t.Fatalf("Integration test failed: %v", err)
236  		}
237  		
238  		if result == "" {
239  			t.Error("Integration test returned empty result")
240  		}
241  		
242  		// Verify agent status
243  		status := agent.GetStatus()
244  		if status.TasksRun == 0 {
245  			t.Error("No tasks were executed")
246  		}
247  	})
248  }
249  
250  // Helper functions
251  func createTempFile(t *testing.T, content string) string {
252  	tmpFile, err := os.CreateTemp("", "kamaji_test_*.txt")
253  	if err != nil {
254  		t.Fatalf("Failed to create temp file: %v", err)
255  	}
256  	
257  	if _, err := tmpFile.WriteString(content); err != nil {
258  		t.Fatalf("Failed to write to temp file: %v", err)
259  	}
260  	
261  	tmpFile.Close()
262  	return tmpFile.Name()
263  }
264  
265  // Benchmark tests
266  func BenchmarkToolExecution(b *testing.B) {
267  	tool := tools.ShellExecuteTool{}
268  	ctx := context.Background()
269  	
270  	b.ResetTimer()
271  	for i := 0; i < b.N; i++ {
272  		_, err := tool.Call(ctx, "echo test")
273  		if err != nil {
274  			b.Fatalf("Tool execution failed: %v", err)
275  		}
276  	}
277  }
278  
279  func BenchmarkAgentExecution(b *testing.B) {
280  	llm := providers.NewMockProvider("http://test", "test-model")
281  	tools := []tools.Tool{tools.ShellExecuteTool{}}
282  	agent := agents.NewBasicAgentExecutor(llm, tools, false)
283  	
284  	b.ResetTimer()
285  	for i := 0; i < b.N; i++ {
286  		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
287  		_, err := agent.Execute(ctx, "test task")
288  		cancel()
289  		if err != nil {
290  			b.Fatalf("Agent execution failed: %v", err)
291  		}
292  	}
293  }