diff --git a/internal/services/realtimeengine/iacrealtime/line_parser.go b/internal/services/realtimeengine/iacrealtime/line_parser.go index 0ba15bacf..330f8027b 100644 --- a/internal/services/realtimeengine/iacrealtime/line_parser.go +++ b/internal/services/realtimeengine/iacrealtime/line_parser.go @@ -1,8 +1,6 @@ package iacrealtime import ( - "os" - "path/filepath" "strings" ) @@ -12,17 +10,8 @@ func NewLineParser() *LineParser { return &LineParser{} } -func (lp *LineParser) GetLineIndices(filePath string, lineNumber int) (startIndex, endIndex int) { - if filePath == "" { - return 0, 0 - } - - data, err := os.ReadFile(filepath.Clean(filePath)) - if err != nil { - return 0, 0 - } - - lines := strings.Split(string(data), "\n") +func (lp *LineParser) GetLineIndices(content string, lineNumber int) (startIndex, endIndex int) { + lines := strings.Split(content, "\n") if lineNumber < 0 || lineNumber >= len(lines) { return 0, 0 @@ -48,7 +37,7 @@ func (lp *LineParser) findContentBounds(line string) (start, end int) { if start == -1 { start = i } - end = i + end = i + 1 } } diff --git a/internal/services/realtimeengine/iacrealtime/line_parser_test.go b/internal/services/realtimeengine/iacrealtime/line_parser_test.go index b83a6de7f..ca87eab99 100644 --- a/internal/services/realtimeengine/iacrealtime/line_parser_test.go +++ b/internal/services/realtimeengine/iacrealtime/line_parser_test.go @@ -1,7 +1,6 @@ package iacrealtime import ( - "os" "testing" ) @@ -17,7 +16,7 @@ func TestLineParser_GetLineIndices(t *testing.T) { parser := NewLineParser() // Create a test file with known content - testContent := `line 0 + fileContent := `line 0 line 1 line 2 with spaces line 3 with tab @@ -25,101 +24,79 @@ empty line below line 6` - tempFile, err := os.CreateTemp("", "test_line_parser_*.txt") - if err != nil { - t.Fatalf("Failed to create temp file: %v", err) - } - defer func() { - if err := os.Remove(tempFile.Name()); err != nil && !os.IsNotExist(err) { - t.Logf("Failed to remove temp file: %v", err) - } - }() - - if _, err := tempFile.WriteString(testContent); err != nil { - t.Fatalf("Failed to write to temp file: %v", err) - } - tempFile.Close() - tests := []struct { name string - filePath string + fileContent string lineNumber int expectedStart int expectedEnd int }{ { name: "First line with content", - filePath: tempFile.Name(), + fileContent: fileContent, lineNumber: 0, expectedStart: 0, - expectedEnd: 5, // "line 0" - ends at '0' + expectedEnd: 6, // "line 0" - ends at '0' }, { name: "Second line with content", - filePath: tempFile.Name(), + fileContent: fileContent, lineNumber: 1, expectedStart: 0, - expectedEnd: 5, // "line 1" - ends at '1' + expectedEnd: 6, // "line 1" - ends at '1' }, { name: "Line with leading spaces", - filePath: tempFile.Name(), + fileContent: fileContent, lineNumber: 2, expectedStart: 2, // starts after " " - expectedEnd: 19, // ends at last 's' in "spaces" + expectedEnd: 20, // ends at last 's' in "spaces" }, { name: "Line with tab", - filePath: tempFile.Name(), + fileContent: fileContent, lineNumber: 3, expectedStart: 1, // starts after tab - expectedEnd: 15, // ends at 'b' in "tab" + expectedEnd: 16, // ends at 'b' in "tab" }, { name: "Empty line", - filePath: tempFile.Name(), + fileContent: fileContent, lineNumber: 4, expectedStart: 0, - expectedEnd: 15, // "empty line below" + expectedEnd: 16, // "empty line below" }, { name: "Line with only whitespace", - filePath: tempFile.Name(), + fileContent: fileContent, lineNumber: 5, expectedStart: 0, expectedEnd: 0, }, { name: "Valid line number", - filePath: tempFile.Name(), + fileContent: fileContent, lineNumber: 6, expectedStart: 0, - expectedEnd: 5, // "line 6" + expectedEnd: 6, // "line 6" }, { name: "Invalid line number (negative)", - filePath: tempFile.Name(), + fileContent: fileContent, lineNumber: -1, expectedStart: 0, expectedEnd: 0, }, { name: "Invalid line number (too large)", - filePath: tempFile.Name(), + fileContent: fileContent, lineNumber: 100, expectedStart: 0, expectedEnd: 0, }, { name: "Empty file path", - filePath: "", - lineNumber: 0, - expectedStart: 0, - expectedEnd: 0, - }, - { - name: "Non-existent file", - filePath: "/nonexistent/file.txt", + fileContent: "", lineNumber: 0, expectedStart: 0, expectedEnd: 0, @@ -129,7 +106,7 @@ line 6` for _, tt := range tests { ttt := tt t.Run(tt.name, func(t *testing.T) { - start, end := parser.GetLineIndices(ttt.filePath, ttt.lineNumber) + start, end := parser.GetLineIndices(ttt.fileContent, ttt.lineNumber) if start != ttt.expectedStart || end != ttt.expectedEnd { t.Errorf("GetLineIndices() = (%d, %d), want (%d, %d)", start, end, ttt.expectedStart, ttt.expectedEnd) @@ -151,37 +128,37 @@ func TestLineParser_findContentBounds(t *testing.T) { name: "Normal line with content", line: "hello world", expectedStart: 0, - expectedEnd: 10, + expectedEnd: 11, }, { name: "Line with leading spaces", line: " hello world", expectedStart: 2, - expectedEnd: 12, + expectedEnd: 13, }, { name: "Line with trailing spaces", line: "hello world ", expectedStart: 0, - expectedEnd: 10, + expectedEnd: 11, }, { name: "Line with leading and trailing spaces", line: " hello world ", expectedStart: 2, - expectedEnd: 12, + expectedEnd: 13, }, { name: "Line with tabs", line: "\thello\tworld\t", expectedStart: 1, - expectedEnd: 11, + expectedEnd: 12, }, { name: "Line with mixed whitespace", line: " \t hello world \t ", expectedStart: 3, - expectedEnd: 13, + expectedEnd: 14, }, { name: "Empty line", @@ -211,19 +188,19 @@ func TestLineParser_findContentBounds(t *testing.T) { name: "Single character", line: "a", expectedStart: 0, - expectedEnd: 0, + expectedEnd: 1, }, { name: "Single character with spaces", line: " a ", expectedStart: 2, - expectedEnd: 2, + expectedEnd: 3, }, { name: "Line with carriage return", line: "hello\rworld", expectedStart: 0, - expectedEnd: 10, + expectedEnd: 11, }, } @@ -316,21 +293,6 @@ func TestLineParser_GetLineIndices_EdgeCases(t *testing.T) { // Test with a file that has different line endings testContent := "line1\nline2\r\nline3\rline4" - tempFile, err := os.CreateTemp("", "test_line_endings_*.txt") - if err != nil { - t.Fatalf("Failed to create temp file: %v", err) - } - defer func() { - if err := os.Remove(tempFile.Name()); err != nil && !os.IsNotExist(err) { - t.Logf("Failed to remove temp file: %v", err) - } - }() - - if _, err := tempFile.WriteString(testContent); err != nil { - t.Fatalf("Failed to write to temp file: %v", err) - } - tempFile.Close() - tests := []struct { name string lineNumber int @@ -341,26 +303,26 @@ func TestLineParser_GetLineIndices_EdgeCases(t *testing.T) { name: "First line", lineNumber: 0, expectedStart: 0, - expectedEnd: 4, // "line1" + expectedEnd: 5, // "line1" }, { name: "Second line with CRLF", lineNumber: 1, expectedStart: 0, - expectedEnd: 4, // "line2" + expectedEnd: 5, // "line2" }, { name: "Third line with CR", lineNumber: 2, expectedStart: 0, - expectedEnd: 10, // "line3\rline4" - ends at '4' + expectedEnd: 11, // "line3\rline4" - ends at '4' }, } for _, tt := range tests { ttt := tt t.Run(tt.name, func(t *testing.T) { - start, end := parser.GetLineIndices(tempFile.Name(), ttt.lineNumber) + start, end := parser.GetLineIndices(testContent, ttt.lineNumber) if start != ttt.expectedStart || end != ttt.expectedEnd { t.Errorf("GetLineIndices() = (%d, %d), want (%d, %d)", start, end, ttt.expectedStart, ttt.expectedEnd) diff --git a/internal/services/realtimeengine/iacrealtime/mapper.go b/internal/services/realtimeengine/iacrealtime/mapper.go index 34d35b539..5fe51483a 100644 --- a/internal/services/realtimeengine/iacrealtime/mapper.go +++ b/internal/services/realtimeengine/iacrealtime/mapper.go @@ -1,6 +1,8 @@ package iacrealtime import ( + "os" + "path/filepath" "strings" "github.com/checkmarx/ast-cli/internal/services/realtimeengine" @@ -24,12 +26,15 @@ func (m *Mapper) ConvertKicsToIacResults( iacResults := make([]IacRealtimeResult, 0) indexMap := make(map[int]LineIndex) + data, _ := os.ReadFile(filepath.Clean(filePath)) + fileContent := string(data) + for i := range results.Results { result := &results.Results[i] for j := range result.Locations { loc := &result.Locations[j] locLine := int(loc.Line) - 1 - lineIndex := m.getOrComputeLineIndex(filePath, locLine, indexMap) + lineIndex := m.getOrComputeLineIndex(fileContent, locLine, indexMap) iacResult := IacRealtimeResult{ Title: result.QueryName, @@ -51,12 +56,12 @@ func (m *Mapper) ConvertKicsToIacResults( return iacResults } -func (m *Mapper) getOrComputeLineIndex(filePath string, lineNum int, indexMap map[int]LineIndex) LineIndex { +func (m *Mapper) getOrComputeLineIndex(content string, lineNum int, indexMap map[int]LineIndex) LineIndex { if value, exists := indexMap[lineNum]; exists { return value } - startIndex, endIndex := m.lineParser.GetLineIndices(filePath, lineNum) + startIndex, endIndex := m.lineParser.GetLineIndices(content, lineNum) lineIndex := LineIndex{Start: startIndex, End: endIndex} indexMap[lineNum] = lineIndex return lineIndex diff --git a/internal/services/realtimeengine/iacrealtime/mapper_test.go b/internal/services/realtimeengine/iacrealtime/mapper_test.go index 0481b2101..c358f4798 100644 --- a/internal/services/realtimeengine/iacrealtime/mapper_test.go +++ b/internal/services/realtimeengine/iacrealtime/mapper_test.go @@ -277,59 +277,38 @@ func TestMapper_getOrComputeLineIndex(t *testing.T) { // Create a temporary file for testing content := "line 0\nline 1\n line 2 with spaces \nline 3\n" - tempFile, err := os.CreateTemp("", "test_file_*.txt") - if err != nil { - t.Fatalf("Failed to create temp file: %v", err) - } - defer func() { - if err := os.Remove(tempFile.Name()); err != nil && !os.IsNotExist(err) { - t.Logf("Failed to remove temp file: %v", err) - } - }() - - if _, err := tempFile.WriteString(content); err != nil { - t.Fatalf("Failed to write to temp file: %v", err) - } - tempFile.Close() tests := []struct { name string - filePath string + fileContent string lineNum int indexMap map[int]LineIndex expected LineIndex expectCached bool }{ { - name: "Compute line index for valid line", - filePath: tempFile.Name(), - lineNum: 2, - indexMap: make(map[int]LineIndex), - expected: LineIndex{Start: 2, End: 19}, // " line 2 with spaces " - starts at index 2, ends at index 19 (last 's') + name: "Compute line index for valid line", + fileContent: content, + lineNum: 2, + indexMap: make(map[int]LineIndex), + expected: LineIndex{Start: 2, End: 20}, }, { - name: "Return cached line index", - filePath: tempFile.Name(), - lineNum: 1, + name: "Return cached line index", + fileContent: content, + lineNum: 1, indexMap: map[int]LineIndex{ 1: {Start: 10, End: 20}, }, expected: LineIndex{Start: 10, End: 20}, expectCached: true, }, - { - name: "Handle invalid file path", - filePath: "/nonexistent/file.txt", - lineNum: 0, - indexMap: make(map[int]LineIndex), - expected: LineIndex{Start: 0, End: 0}, - }, } for _, tt := range tests { ttt := tt t.Run(tt.name, func(t *testing.T) { - got := mapper.getOrComputeLineIndex(ttt.filePath, ttt.lineNum, ttt.indexMap) + got := mapper.getOrComputeLineIndex(ttt.fileContent, ttt.lineNum, ttt.indexMap) if !reflect.DeepEqual(got, ttt.expected) { t.Errorf("getOrComputeLineIndex() = %v, want %v", got, ttt.expected) } @@ -356,29 +335,14 @@ spec: containers: - name: test` - tempFile, err := os.CreateTemp("", "test_integration_*.yaml") - if err != nil { - t.Fatalf("Failed to create temp file: %v", err) - } - defer func() { - if err := os.Remove(tempFile.Name()); err != nil && !os.IsNotExist(err) { - t.Logf("Failed to remove temp file: %v", err) - } - }() - - if _, err := tempFile.WriteString(testContent); err != nil { - t.Fatalf("Failed to write to temp file: %v", err) - } - tempFile.Close() - // Test that the same line number returns cached results on subsequent calls indexMap := make(map[int]LineIndex) // First call should compute - result1 := mapper.getOrComputeLineIndex(tempFile.Name(), 1, indexMap) + result1 := mapper.getOrComputeLineIndex(testContent, 1, indexMap) // Second call should use cache - result2 := mapper.getOrComputeLineIndex(tempFile.Name(), 1, indexMap) + result2 := mapper.getOrComputeLineIndex(testContent, 1, indexMap) if !reflect.DeepEqual(result1, result2) { t.Errorf("Cached result should be identical to computed result") @@ -458,7 +422,7 @@ metadata: } // The "kind: Pod" line should start at index 0 and end at index 8 (last 'd') - if location.StartIndex != 0 || location.EndIndex != 8 { + if location.StartIndex != 0 || location.EndIndex != 9 { t.Errorf("Expected StartIndex 0 and EndIndex 8, got StartIndex %d and EndIndex %d", location.StartIndex, location.EndIndex) }