123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- package nginx_log
- import (
- "context"
- "testing"
- "time"
- )
- func TestAnalyticsService_ValidateLogPath(t *testing.T) {
- service := NewAnalyticsService()
- testCases := []struct {
- name string
- path string
- wantErr bool
- }{
- {
- name: "Empty path should be allowed",
- path: "",
- wantErr: false,
- },
- {
- name: "Invalid path should be rejected",
- path: "/var/log/nginx/access.log",
- wantErr: true, // This path is not in whitelist in test environment
- },
- }
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- err := service.ValidateLogPath(tc.path)
- if (err != nil) != tc.wantErr {
- t.Errorf("ValidateLogPath() error = %v, wantErr %v", err, tc.wantErr)
- }
- })
- }
- }
- func TestAnalyticsService_ValidateAndNormalizeSearchRequest(t *testing.T) {
- service := NewAnalyticsService()
- testCases := []struct {
- name string
- req *QueryRequest
- wantErr bool
- checkFn func(*QueryRequest) bool
- }{
- {
- name: "Default limit should be set",
- req: &QueryRequest{
- Limit: 0,
- },
- wantErr: false,
- checkFn: func(req *QueryRequest) bool {
- return req.Limit == 100
- },
- },
- {
- name: "Limit should be capped at 1000",
- req: &QueryRequest{
- Limit: 2000,
- },
- wantErr: false,
- checkFn: func(req *QueryRequest) bool {
- return req.Limit == 1000
- },
- },
- {
- name: "Negative offset should be normalized",
- req: &QueryRequest{
- Limit: 100,
- Offset: -10,
- },
- wantErr: false,
- checkFn: func(req *QueryRequest) bool {
- return req.Offset == 0
- },
- },
- {
- name: "Invalid time range should return error",
- req: &QueryRequest{
- StartTime: time.Now().Unix(),
- EndTime: time.Now().Add(-1 * time.Hour).Unix(),
- Limit: 100,
- },
- wantErr: true,
- checkFn: nil,
- },
- {
- name: "Invalid status code should return error",
- req: &QueryRequest{
- Status: []int{999},
- Limit: 100,
- },
- wantErr: true,
- checkFn: nil,
- },
- }
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- err := service.validateAndNormalizeSearchRequest(tc.req)
- if (err != nil) != tc.wantErr {
- t.Errorf("validateAndNormalizeSearchRequest() error = %v, wantErr %v", err, tc.wantErr)
- return
- }
- if !tc.wantErr && tc.checkFn != nil {
- if !tc.checkFn(tc.req) {
- t.Errorf("validateAndNormalizeSearchRequest() validation check failed")
- }
- }
- })
- }
- }
- func TestAnalyticsService_GetLogEntries(t *testing.T) {
- service := NewAnalyticsService()
- testCases := []struct {
- name string
- path string
- limit int
- tail bool
- wantErr bool
- }{
- {
- name: "Empty path should return error",
- path: "",
- limit: 100,
- tail: false,
- wantErr: true,
- },
- {
- name: "Invalid path should return error",
- path: "/var/log/nginx/access.log",
- limit: 100,
- tail: false,
- wantErr: true, // This path is not in whitelist in test environment
- },
- }
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- entries, err := service.GetLogEntries(tc.path, tc.limit, tc.tail)
- if (err != nil) != tc.wantErr {
- t.Errorf("GetLogEntries() error = %v, wantErr %v", err, tc.wantErr)
- return
- }
- if !tc.wantErr {
- // Should return a slice (even if empty)
- if entries == nil {
- t.Errorf("GetLogEntries() returned nil entries")
- }
- }
- })
- }
- }
- func BenchmarkAnalyticsService_ValidateAndNormalizeSearchRequest(b *testing.B) {
- service := NewAnalyticsService()
- req := &QueryRequest{
- StartTime: time.Now().Add(-1 * time.Hour).Unix(),
- EndTime: time.Now().Unix(),
- Query: "test query",
- IP: "192.168.1.1",
- Method: "GET",
- Status: []int{200, 404},
- Path: "/api/test",
- UserAgent: "Mozilla/5.0",
- Limit: 100,
- Offset: 0,
- }
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- // Create a copy for each iteration to avoid side effects
- reqCopy := *req
- _ = service.validateAndNormalizeSearchRequest(&reqCopy)
- }
- }
- func TestAnalyticsService_SearchLogs_WithoutIndexer(t *testing.T) {
- service := NewAnalyticsService()
- // Don't set indexer to test error handling
- ctx := context.Background()
- req := &QueryRequest{
- Limit: 100,
- }
- _, err := service.SearchLogs(ctx, req)
- if err == nil {
- t.Error("SearchLogs() should return error when indexer is not available")
- }
- if err != ErrIndexerNotAvailable {
- t.Errorf("SearchLogs() error = %v, want %v", err, ErrIndexerNotAvailable)
- }
- }
- func TestAnalyticsService_GetIndexStatus_WithoutIndexer(t *testing.T) {
- service := NewAnalyticsService()
- // Don't set indexer to test error handling
- _, err := service.GetIndexStatus()
- if err == nil {
- t.Error("GetIndexStatus() should return error when indexer is not available")
- }
- if err != ErrIndexerNotAvailable {
- t.Errorf("GetIndexStatus() error = %v, want %v", err, ErrIndexerNotAvailable)
- }
- }
|