5322d3cd8e
- Introduced benchmark tests for various XML parsing methods, including parsing from strings, bytes, and readers, to evaluate performance. - Added unit tests for the parser interface and validation mechanisms, ensuring robust error handling and validation logic. - Implemented tests for utility functions related to XML processing, enhancing overall test coverage and reliability. - Created a test suite for the TED domain, validating the structure and functionality of contract notices and related entities. - Developed a comprehensive test runner script to facilitate automated testing, coverage analysis, and performance benchmarking for the XML parser package.
815 lines
19 KiB
Go
815 lines
19 KiB
Go
package xmlparser
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
"sync"
|
|
"testing"
|
|
)
|
|
|
|
// Mock XML data for testing
|
|
const (
|
|
validMockXML = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<MockElement id="test-123">
|
|
<name>Test Mock Name</name>
|
|
<value>Test mock value</value>
|
|
</MockElement>`
|
|
|
|
validMockXMLWithNamespace = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<MockElement xmlns="http://test.example.com" id="test-456">
|
|
<name>Namespaced Mock</name>
|
|
<value>Namespaced value</value>
|
|
</MockElement>`
|
|
|
|
invalidMockXML = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<MockElement id="test-invalid">
|
|
<name></name>
|
|
<value>Missing name</value>
|
|
</MockElement>`
|
|
|
|
malformedXML = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<MockElement id="malformed">
|
|
<name>Unclosed tag</name>
|
|
<value>This will fail</value>
|
|
</MockElemen>`
|
|
|
|
emptyXML = ``
|
|
|
|
largeMockXML = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<MockElement id="large-test">
|
|
<name>Large Mock</name>
|
|
<value>This is a large XML document with nested elements</value>
|
|
<nested>
|
|
<level1>
|
|
<level2>
|
|
<level3>
|
|
<level4>
|
|
<level5>Deep nesting test</level5>
|
|
</level4>
|
|
</level3>
|
|
</level2>
|
|
</level1>
|
|
</nested>
|
|
</MockElement>`
|
|
|
|
deeplyNestedXML = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<MockElement id="deep-test">
|
|
<name>Deep Nesting Test</name>
|
|
<value>Testing depth limits</value>
|
|
<level1><level2><level3><level4><level5>
|
|
<level6><level7><level8><level9><level10>
|
|
<level11><level12><level13><level14><level15>
|
|
<level16><level17><level18><level19><level20>Deep</level20></level19></level18></level17></level16>
|
|
</level15></level14></level13></level12></level11>
|
|
</level10></level9></level8></level7></level6>
|
|
</level5></level4></level3></level2></level1>
|
|
</MockElement>`
|
|
)
|
|
|
|
// errorReader is a mock reader that always returns an error
|
|
type errorReader struct{}
|
|
|
|
func (er errorReader) Read(p []byte) (n int, err error) {
|
|
return 0, io.ErrUnexpectedEOF
|
|
}
|
|
|
|
func TestNewParser(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
options *ParserOptions
|
|
}{
|
|
{
|
|
name: "Default options",
|
|
options: nil,
|
|
},
|
|
{
|
|
name: "Custom options",
|
|
options: &ParserOptions{
|
|
StrictValidation: false,
|
|
AllowEmptyElements: false,
|
|
PreserveWhitespace: true,
|
|
IgnoreUnknownElements: true,
|
|
MaxDepth: 50,
|
|
MaxSize: 1024 * 1024,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
parser := NewParser[MockParsable](tt.options)
|
|
|
|
if parser == nil {
|
|
t.Error("Expected parser to not be nil")
|
|
return
|
|
}
|
|
|
|
// Verify parser type
|
|
if _, ok := parser.(*GenericParser[MockParsable]); !ok {
|
|
t.Error("Expected parser to be of type *GenericParser[MockParsable]")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseString(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
xmlData string
|
|
expectError bool
|
|
expectedID string
|
|
options *ParserOptions
|
|
}{
|
|
{
|
|
name: "Valid XML",
|
|
xmlData: validMockXML,
|
|
expectError: false,
|
|
expectedID: "test-123",
|
|
options: nil,
|
|
},
|
|
{
|
|
name: "Valid XML with namespace",
|
|
xmlData: validMockXMLWithNamespace,
|
|
expectError: false,
|
|
expectedID: "test-456",
|
|
options: nil,
|
|
},
|
|
{
|
|
name: "Invalid XML (validation failure)",
|
|
xmlData: invalidMockXML,
|
|
expectError: true,
|
|
expectedID: "",
|
|
options: nil,
|
|
},
|
|
{
|
|
name: "Malformed XML",
|
|
xmlData: malformedXML,
|
|
expectError: true,
|
|
expectedID: "",
|
|
options: nil,
|
|
},
|
|
{
|
|
name: "Empty XML",
|
|
xmlData: emptyXML,
|
|
expectError: true,
|
|
expectedID: "",
|
|
options: nil,
|
|
},
|
|
{
|
|
name: "Large XML",
|
|
xmlData: largeMockXML,
|
|
expectError: false,
|
|
expectedID: "large-test",
|
|
options: nil,
|
|
},
|
|
{
|
|
name: "XML exceeds size limit",
|
|
xmlData: largeMockXML,
|
|
expectError: true,
|
|
expectedID: "",
|
|
options: &ParserOptions{
|
|
MaxSize: 100, // Very small limit
|
|
},
|
|
},
|
|
{
|
|
name: "Deeply nested XML exceeds depth",
|
|
xmlData: deeplyNestedXML,
|
|
expectError: true,
|
|
expectedID: "",
|
|
options: &ParserOptions{
|
|
MaxDepth: 10, // Shallow depth limit
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
parser := NewParser[MockParsable](tt.options)
|
|
result, err := parser.ParseString(tt.xmlData)
|
|
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Error("Expected parsing error but got none")
|
|
}
|
|
if result != nil {
|
|
t.Error("Expected result to be nil when error occurs")
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("Unexpected parsing error: %v", err)
|
|
return
|
|
}
|
|
|
|
if result == nil {
|
|
t.Error("Expected result to not be nil")
|
|
return
|
|
}
|
|
|
|
if result.GetID() != tt.expectedID {
|
|
t.Errorf("Expected ID '%s', got '%s'", tt.expectedID, result.GetID())
|
|
}
|
|
|
|
// Verify the mock is valid (should pass validation)
|
|
if err := result.Validate(); err != nil {
|
|
t.Errorf("Parsed result failed validation: %v", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseBytes(t *testing.T) {
|
|
xmlData := []byte(validMockXML)
|
|
parser := NewParser[MockParsable](nil)
|
|
|
|
result, err := parser.ParseBytes(xmlData)
|
|
if err != nil {
|
|
t.Errorf("Unexpected parsing error: %v", err)
|
|
return
|
|
}
|
|
|
|
if result == nil {
|
|
t.Error("Expected result to not be nil")
|
|
return
|
|
}
|
|
|
|
if result.GetID() != "test-123" {
|
|
t.Errorf("Expected ID 'test-123', got '%s'", result.GetID())
|
|
}
|
|
}
|
|
|
|
func TestParse(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
reader io.Reader
|
|
expectError bool
|
|
expectedID string
|
|
}{
|
|
{
|
|
name: "Valid reader",
|
|
reader: strings.NewReader(validMockXML),
|
|
expectError: false,
|
|
expectedID: "test-123",
|
|
},
|
|
{
|
|
name: "Error reader",
|
|
reader: errorReader{},
|
|
expectError: true,
|
|
expectedID: "",
|
|
},
|
|
{
|
|
name: "Empty reader",
|
|
reader: strings.NewReader(""),
|
|
expectError: true,
|
|
expectedID: "",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
parser := NewParser[MockParsable](nil)
|
|
result, err := parser.Parse(tt.reader)
|
|
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Error("Expected parsing error but got none")
|
|
}
|
|
if result != nil {
|
|
t.Error("Expected result to be nil when error occurs")
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("Unexpected parsing error: %v", err)
|
|
return
|
|
}
|
|
|
|
if result == nil {
|
|
t.Error("Expected result to not be nil")
|
|
return
|
|
}
|
|
|
|
if result.GetID() != tt.expectedID {
|
|
t.Errorf("Expected ID '%s', got '%s'", tt.expectedID, result.GetID())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidate(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
reader io.Reader
|
|
expectError bool
|
|
options *ParserOptions
|
|
}{
|
|
{
|
|
name: "Valid XML",
|
|
reader: strings.NewReader(validMockXML),
|
|
expectError: false,
|
|
options: nil,
|
|
},
|
|
{
|
|
name: "Malformed XML",
|
|
reader: strings.NewReader(malformedXML),
|
|
expectError: true,
|
|
options: nil,
|
|
},
|
|
{
|
|
name: "Empty XML",
|
|
reader: strings.NewReader(""),
|
|
expectError: true,
|
|
options: nil,
|
|
},
|
|
{
|
|
name: "Error reader",
|
|
reader: errorReader{},
|
|
expectError: true,
|
|
options: nil,
|
|
},
|
|
{
|
|
name: "Deeply nested XML exceeds depth",
|
|
reader: strings.NewReader(deeplyNestedXML),
|
|
expectError: true,
|
|
options: &ParserOptions{
|
|
MaxDepth: 10,
|
|
},
|
|
},
|
|
{
|
|
name: "Valid deeply nested XML within limits",
|
|
reader: strings.NewReader(deeplyNestedXML),
|
|
expectError: false,
|
|
options: &ParserOptions{
|
|
MaxDepth: 100,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
parser := NewParser[MockParsable](tt.options)
|
|
err := parser.Validate(tt.reader)
|
|
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Error("Expected validation error but got none")
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Errorf("Unexpected validation error: %v", err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseWithResult(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
reader io.Reader
|
|
expectError bool
|
|
expectedID string
|
|
expectMetadata bool
|
|
expectedVersion string
|
|
expectedEncoding string
|
|
}{
|
|
{
|
|
name: "Valid XML with metadata",
|
|
reader: strings.NewReader(validMockXML),
|
|
expectError: false,
|
|
expectedID: "test-123",
|
|
expectMetadata: true,
|
|
expectedVersion: "1.0",
|
|
expectedEncoding: "UTF-8",
|
|
},
|
|
{
|
|
name: "Valid XML with namespace",
|
|
reader: strings.NewReader(validMockXMLWithNamespace),
|
|
expectError: false,
|
|
expectedID: "test-456",
|
|
expectMetadata: true,
|
|
expectedVersion: "1.0",
|
|
expectedEncoding: "UTF-8",
|
|
},
|
|
{
|
|
name: "Error reader",
|
|
reader: errorReader{},
|
|
expectError: true,
|
|
expectedID: "",
|
|
expectMetadata: false,
|
|
},
|
|
{
|
|
name: "Invalid XML (validation failure)",
|
|
reader: strings.NewReader(invalidMockXML),
|
|
expectError: true,
|
|
expectedID: "",
|
|
expectMetadata: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
parser := NewParser[MockParsable](nil)
|
|
|
|
// Cast to GenericParser to access ParseWithResult
|
|
genericParser, ok := parser.(*GenericParser[MockParsable])
|
|
if !ok {
|
|
t.Error("Expected parser to be of type *GenericParser[MockParsable]")
|
|
return
|
|
}
|
|
|
|
result, err := genericParser.ParseWithResult(tt.reader)
|
|
|
|
if result == nil {
|
|
t.Error("Expected result to not be nil")
|
|
return
|
|
}
|
|
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Error("Expected parsing error but got none")
|
|
}
|
|
if len(result.Errors) == 0 {
|
|
t.Error("Expected errors in result")
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Errorf("Unexpected parsing error: %v", err)
|
|
}
|
|
if len(result.Errors) > 0 {
|
|
t.Errorf("Unexpected errors in result: %v", result.Errors)
|
|
}
|
|
}
|
|
|
|
if tt.expectMetadata {
|
|
if result.Metadata == nil {
|
|
t.Error("Expected metadata to not be nil")
|
|
} else {
|
|
if tt.expectedVersion != "" && result.Metadata.Version != tt.expectedVersion {
|
|
t.Errorf("Expected version '%s', got '%s'", tt.expectedVersion, result.Metadata.Version)
|
|
}
|
|
if tt.expectedEncoding != "" && result.Metadata.Encoding != tt.expectedEncoding {
|
|
t.Errorf("Expected encoding '%s', got '%s'", tt.expectedEncoding, result.Metadata.Encoding)
|
|
}
|
|
}
|
|
}
|
|
|
|
if !tt.expectError && result.Data != nil {
|
|
if result.Data.GetID() != tt.expectedID {
|
|
t.Errorf("Expected ID '%s', got '%s'", tt.expectedID, result.Data.GetID())
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseWithInvalidMockData(t *testing.T) {
|
|
// Create invalid mock data that will pass XML parsing but fail validation
|
|
invalidMockData := MockParsable{
|
|
ID: "test-invalid",
|
|
Name: "Test Name",
|
|
Value: "test-validation-failure", // This will cause validation to fail
|
|
Valid: false, // This will cause validation to fail
|
|
}
|
|
|
|
// This test ensures that even if XML parsing succeeds, validation errors are caught
|
|
xmlData := `<?xml version="1.0" encoding="UTF-8"?>
|
|
<MockElement id="test-invalid">
|
|
<name>Test Name</name>
|
|
<value>test-validation-failure</value>
|
|
</MockElement>`
|
|
|
|
parser := NewParser[MockParsable](nil)
|
|
result, err := parser.ParseString(xmlData)
|
|
|
|
// This should fail during validation, not XML parsing
|
|
if err == nil {
|
|
t.Error("Expected validation error but got none")
|
|
}
|
|
|
|
if result != nil {
|
|
t.Error("Expected result to be nil when validation fails")
|
|
}
|
|
|
|
// Verify the error message contains validation information
|
|
if !strings.Contains(err.Error(), "validation failed") {
|
|
t.Errorf("Expected validation error message, got: %v", err)
|
|
}
|
|
|
|
// Test the mock data validation directly
|
|
validationErr := invalidMockData.Validate()
|
|
if validationErr == nil {
|
|
t.Error("Expected direct validation to fail")
|
|
}
|
|
}
|
|
|
|
func TestConcurrentParsing(t *testing.T) {
|
|
parser := NewParser[MockParsable](nil)
|
|
numGoroutines := 10
|
|
numOperations := 5
|
|
|
|
var wg sync.WaitGroup
|
|
errors := make(chan error, numGoroutines*numOperations)
|
|
results := make(chan *MockParsable, numGoroutines*numOperations)
|
|
|
|
for i := 0; i < numGoroutines; i++ {
|
|
wg.Add(1)
|
|
go func(goroutineID int) {
|
|
defer wg.Done()
|
|
|
|
for j := 0; j < numOperations; j++ {
|
|
// Use different XML data for each operation
|
|
xmlData := strings.Replace(validMockXML, "test-123",
|
|
fmt.Sprintf("test-%d-%d", goroutineID, j), 1)
|
|
|
|
result, err := parser.ParseString(xmlData)
|
|
|
|
if err != nil {
|
|
errors <- err
|
|
} else {
|
|
results <- result
|
|
}
|
|
}
|
|
}(i)
|
|
}
|
|
|
|
wg.Wait()
|
|
close(errors)
|
|
close(results)
|
|
|
|
// Check for errors
|
|
errorCount := 0
|
|
for err := range errors {
|
|
t.Errorf("Concurrent parsing error: %v", err)
|
|
errorCount++
|
|
}
|
|
|
|
// Check results
|
|
resultCount := 0
|
|
for range results {
|
|
resultCount++
|
|
}
|
|
|
|
expectedResults := numGoroutines * numOperations
|
|
if resultCount != expectedResults {
|
|
t.Errorf("Expected %d results, got %d (errors: %d)", expectedResults, resultCount, errorCount)
|
|
}
|
|
}
|
|
|
|
func TestParserOptionsEffects(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
options *ParserOptions
|
|
xmlData string
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "Strict validation enabled",
|
|
options: &ParserOptions{
|
|
StrictValidation: true,
|
|
},
|
|
xmlData: validMockXML,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Strict validation disabled",
|
|
options: &ParserOptions{
|
|
StrictValidation: false,
|
|
},
|
|
xmlData: validMockXML,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Very small size limit",
|
|
options: &ParserOptions{
|
|
MaxSize: 10, // Very small
|
|
},
|
|
xmlData: validMockXML,
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "Very small depth limit",
|
|
options: &ParserOptions{
|
|
MaxDepth: 1, // Very shallow
|
|
},
|
|
xmlData: largeMockXML, // Contains nested elements
|
|
expectError: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
parser := NewParser[MockParsable](tt.options)
|
|
_, err := parser.ParseString(tt.xmlData)
|
|
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Error("Expected parsing error but got none")
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Errorf("Unexpected parsing error: %v", err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExtractMetadata(t *testing.T) {
|
|
parser := NewParser[MockParsable](nil)
|
|
genericParser, ok := parser.(*GenericParser[MockParsable])
|
|
if !ok {
|
|
t.Error("Expected parser to be of type *GenericParser[MockParsable]")
|
|
return
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
xmlData string
|
|
expectedVersion string
|
|
expectedEncoding string
|
|
expectedNamespace string
|
|
}{
|
|
{
|
|
name: "Standard XML with version and encoding",
|
|
xmlData: validMockXML,
|
|
expectedVersion: "1.0",
|
|
expectedEncoding: "UTF-8",
|
|
expectedNamespace: "",
|
|
},
|
|
{
|
|
name: "XML with namespace",
|
|
xmlData: validMockXMLWithNamespace,
|
|
expectedVersion: "1.0",
|
|
expectedEncoding: "UTF-8",
|
|
expectedNamespace: "http://test.example.com",
|
|
},
|
|
{
|
|
name: "XML with single quotes",
|
|
xmlData: `<?xml version='1.1' encoding='ISO-8859-1'?>
|
|
<MockElement id="test">
|
|
<name>Test</name>
|
|
<value>Value</value>
|
|
</MockElement>`,
|
|
expectedVersion: "1.1",
|
|
expectedEncoding: "ISO-8859-1",
|
|
expectedNamespace: "",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
metadata := &XMLMetadata{}
|
|
err := genericParser.extractMetadata([]byte(tt.xmlData), metadata)
|
|
|
|
if err != nil {
|
|
t.Errorf("Unexpected metadata extraction error: %v", err)
|
|
return
|
|
}
|
|
|
|
if metadata.Version != tt.expectedVersion {
|
|
t.Errorf("Expected version '%s', got '%s'", tt.expectedVersion, metadata.Version)
|
|
}
|
|
|
|
if metadata.Encoding != tt.expectedEncoding {
|
|
t.Errorf("Expected encoding '%s', got '%s'", tt.expectedEncoding, metadata.Encoding)
|
|
}
|
|
|
|
if metadata.Namespace != tt.expectedNamespace {
|
|
t.Errorf("Expected namespace '%s', got '%s'", tt.expectedNamespace, metadata.Namespace)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseEdgeCases(t *testing.T) {
|
|
parser := NewParser[MockParsable](nil)
|
|
|
|
tests := []struct {
|
|
name string
|
|
xmlData string
|
|
expectError bool
|
|
description string
|
|
}{
|
|
{
|
|
name: "XML with comments",
|
|
xmlData: `<?xml version="1.0" encoding="UTF-8"?>
|
|
<!-- This is a comment -->
|
|
<MockElement id="test-comments">
|
|
<!-- Another comment -->
|
|
<name>Test with comments</name>
|
|
<value>Comments should be ignored</value>
|
|
</MockElement>`,
|
|
expectError: false,
|
|
description: "XML with comments should parse successfully",
|
|
},
|
|
{
|
|
name: "XML with CDATA",
|
|
xmlData: `<?xml version="1.0" encoding="UTF-8"?>
|
|
<MockElement id="test-cdata">
|
|
<name>CDATA Test</name>
|
|
<value><![CDATA[This is CDATA content with <special> characters]]></value>
|
|
</MockElement>`,
|
|
expectError: false,
|
|
description: "XML with CDATA should parse successfully",
|
|
},
|
|
{
|
|
name: "XML with special characters",
|
|
xmlData: `<?xml version="1.0" encoding="UTF-8"?>
|
|
<MockElement id="test-special">
|
|
<name>Special & Characters</name>
|
|
<value><tag> "quoted" 'text'</value>
|
|
</MockElement>`,
|
|
expectError: false,
|
|
description: "XML with escaped special characters should parse successfully",
|
|
},
|
|
{
|
|
name: "Minimal valid XML",
|
|
xmlData: `<MockElement id="minimal">
|
|
<name>Minimal</name>
|
|
<value>Test</value>
|
|
</MockElement>`,
|
|
expectError: false,
|
|
description: "Minimal XML without declaration should parse successfully",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result, err := parser.ParseString(tt.xmlData)
|
|
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Errorf("%s: Expected error but got none", tt.description)
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Errorf("%s: Unexpected error: %v", tt.description, err)
|
|
return
|
|
}
|
|
|
|
if result == nil {
|
|
t.Errorf("%s: Expected result to not be nil", tt.description)
|
|
return
|
|
}
|
|
|
|
// Verify the result is valid
|
|
if err := result.Validate(); err != nil {
|
|
t.Errorf("%s: Result validation failed: %v", tt.description, err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParserMemoryUsage(t *testing.T) {
|
|
// Test parsing multiple documents to ensure no memory leaks
|
|
parser := NewParser[MockParsable](nil)
|
|
|
|
for i := 0; i < 100; i++ {
|
|
xmlData := strings.Replace(validMockXML, "test-123", fmt.Sprintf("test-%d", i), 1)
|
|
result, err := parser.ParseString(xmlData)
|
|
|
|
if err != nil {
|
|
t.Errorf("Parse error on iteration %d: %v", i, err)
|
|
break
|
|
}
|
|
|
|
if result == nil {
|
|
t.Errorf("Nil result on iteration %d", i)
|
|
break
|
|
}
|
|
|
|
// Explicitly trigger validation to ensure full processing
|
|
if err := result.Validate(); err != nil {
|
|
t.Errorf("Validation error on iteration %d: %v", i, err)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseFromBuffer(t *testing.T) {
|
|
// Test parsing from a bytes.Buffer
|
|
buffer := bytes.NewBufferString(validMockXML)
|
|
parser := NewParser[MockParsable](nil)
|
|
|
|
result, err := parser.Parse(buffer)
|
|
if err != nil {
|
|
t.Errorf("Unexpected error parsing from buffer: %v", err)
|
|
return
|
|
}
|
|
|
|
if result == nil {
|
|
t.Error("Expected result to not be nil")
|
|
return
|
|
}
|
|
|
|
if result.GetID() != "test-123" {
|
|
t.Errorf("Expected ID 'test-123', got '%s'", result.GetID())
|
|
}
|
|
}
|