mirror of
https://github.com/turbot/steampipe.git
synced 2025-12-19 18:12:43 -05:00
195 lines
4.9 KiB
Go
195 lines
4.9 KiB
Go
package export
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/turbot/steampipe/v2/pkg/constants"
|
|
)
|
|
|
|
type testExporter struct {
|
|
alias string
|
|
extension string
|
|
name string
|
|
}
|
|
|
|
func (t *testExporter) Export(ctx context.Context, input ExportSourceData, destPath string) error {
|
|
return nil
|
|
}
|
|
func (t *testExporter) FileExtension() string { return t.extension }
|
|
func (t *testExporter) Name() string { return t.name }
|
|
func (t *testExporter) Alias() string { return t.alias }
|
|
|
|
var dummyCSVExporter = testExporter{alias: "", extension: ".csv", name: "csv"}
|
|
var dummyJSONExporter = testExporter{alias: "", extension: ".json", name: "json"}
|
|
var dummyASFFExporter = testExporter{alias: "asff.json", extension: ".json", name: "asff"}
|
|
var dummyNUNITExporter = testExporter{alias: "nunit3.xml", extension: ".xml", name: "nunit3"}
|
|
var dummySPSExporter = testExporter{alias: "sps", extension: constants.SnapshotExtension, name: constants.OutputFormatSnapshot}
|
|
|
|
type exporterTestCase struct {
|
|
name string
|
|
input string
|
|
expect interface{}
|
|
}
|
|
|
|
var exporterTestCases = []exporterTestCase{
|
|
{
|
|
name: "Bad Format",
|
|
input: "bad-format",
|
|
expect: "ERROR",
|
|
},
|
|
{
|
|
name: "csv file name",
|
|
input: "file.csv",
|
|
expect: &dummyCSVExporter,
|
|
},
|
|
{
|
|
name: "csv format name",
|
|
input: "csv",
|
|
expect: &dummyCSVExporter,
|
|
},
|
|
{
|
|
name: "Snapshot file name",
|
|
input: "file.sps",
|
|
expect: &dummySPSExporter,
|
|
},
|
|
{
|
|
name: "Snapshot format name",
|
|
input: "sps",
|
|
expect: &dummySPSExporter,
|
|
},
|
|
{
|
|
name: "json file name",
|
|
input: "file.json",
|
|
expect: &dummyJSONExporter,
|
|
},
|
|
{
|
|
name: "json format name",
|
|
input: "json",
|
|
expect: &dummyJSONExporter,
|
|
},
|
|
{
|
|
name: "asff json file name",
|
|
input: "file.asff.json",
|
|
expect: &dummyASFFExporter,
|
|
},
|
|
{
|
|
name: "asff json format name",
|
|
input: "asff.json",
|
|
expect: &dummyASFFExporter,
|
|
},
|
|
{
|
|
name: "nunit3 file name",
|
|
input: "file.nunit3.xml",
|
|
expect: &dummyNUNITExporter,
|
|
},
|
|
{
|
|
name: "nunit3 format name",
|
|
input: "nunit3.xml",
|
|
expect: &dummyNUNITExporter,
|
|
},
|
|
}
|
|
|
|
func TestDoExport(t *testing.T) {
|
|
exportersToRegister := []*testExporter{
|
|
&dummyJSONExporter,
|
|
&dummyCSVExporter,
|
|
&dummySPSExporter,
|
|
&dummyASFFExporter,
|
|
&dummyNUNITExporter,
|
|
}
|
|
|
|
m := NewManager()
|
|
for _, e := range exportersToRegister {
|
|
m.Register(e)
|
|
}
|
|
for _, testCase := range exporterTestCases {
|
|
targets, err := m.resolveTargetsFromArgs([]string{testCase.input}, "dummy_execution_name")
|
|
shouldError := testCase.expect == "ERROR"
|
|
if shouldError {
|
|
if err == nil {
|
|
t.Errorf("Request for '%s' should have errored - but did not", testCase.input)
|
|
}
|
|
continue
|
|
}
|
|
if !shouldError {
|
|
if err != nil {
|
|
t.Errorf("Request for '%s' should not have errored - but did: %v", testCase.input, err)
|
|
}
|
|
continue
|
|
}
|
|
|
|
if len(targets) != 1 {
|
|
t.Errorf("%v with %v input => expected one target - got %d", testCase.name, testCase.input, len(targets))
|
|
continue
|
|
}
|
|
actualTarget := targets[0]
|
|
expectedTargetExporter := testCase.expect.(*testExporter)
|
|
|
|
if actualTarget.exporter != expectedTargetExporter {
|
|
t.Errorf("%v with %v input => expected %s target - got %s", testCase.name, testCase.input, testCase.expect.(*testExporter).Name(), actualTarget.exporter.Name())
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestManager_ConcurrentRegistration tests that the Manager can handle concurrent
|
|
// exporter registration safely. This test is designed to expose race conditions
|
|
// when run with the -race flag.
|
|
//
|
|
// Related issue: #4715
|
|
func TestManager_ConcurrentRegistration(t *testing.T) {
|
|
// Create a manager instance
|
|
m := NewManager()
|
|
|
|
// Create multiple test exporters with unique names
|
|
exporters := []*testExporter{
|
|
{alias: "", extension: ".csv", name: "csv"},
|
|
{alias: "", extension: ".json", name: "json"},
|
|
{alias: "", extension: ".xml", name: "xml"},
|
|
{alias: "", extension: ".html", name: "html"},
|
|
{alias: "", extension: ".yaml", name: "yaml"},
|
|
{alias: "", extension: ".md", name: "markdown"},
|
|
{alias: "", extension: ".txt", name: "text"},
|
|
{alias: "", extension: ".log", name: "log"},
|
|
}
|
|
|
|
// Channel to collect errors from goroutines
|
|
errChan := make(chan error, len(exporters))
|
|
done := make(chan bool)
|
|
|
|
// Register all exporters concurrently
|
|
for _, exp := range exporters {
|
|
go func(e *testExporter) {
|
|
err := m.Register(e)
|
|
errChan <- err
|
|
}(exp)
|
|
}
|
|
|
|
// Collect results
|
|
go func() {
|
|
for i := 0; i < len(exporters); i++ {
|
|
err := <-errChan
|
|
if err != nil {
|
|
t.Errorf("Failed to register exporter: %v", err)
|
|
}
|
|
}
|
|
done <- true
|
|
}()
|
|
|
|
// Wait for completion
|
|
<-done
|
|
|
|
// Verify all exporters were registered successfully
|
|
// Each exporter should be accessible by its name
|
|
for _, exp := range exporters {
|
|
target, err := m.getExportTarget(exp.name, "test_exec")
|
|
if err != nil {
|
|
t.Errorf("Exporter '%s' was not registered properly: %v", exp.name, err)
|
|
}
|
|
if target == nil {
|
|
t.Errorf("Exporter '%s' returned nil target", exp.name)
|
|
}
|
|
}
|
|
}
|