Skip to content

Commit dd3d707

Browse files
committed
fix: pre-commit
Signed-off-by: Julio Jimenez <julio@clickhouse.com>
1 parent c036ec4 commit dd3d707

5 files changed

Lines changed: 482 additions & 1 deletion

File tree

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: 💣 ClickBOM Tests
2-
on: [push, pull_request]
2+
on: [push]
33

44
jobs:
55
# Unit tests
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//go:build integration
2+
// +build integration
3+
4+
package integration
5+
6+
import (
7+
"context"
8+
"os"
9+
"testing"
10+
11+
"github.com/ClickHouse/ClickBOM/internal/config"
12+
"github.com/ClickHouse/ClickBOM/internal/storage"
13+
)
14+
15+
func TestClickHouseIntegration(t *testing.T) {
16+
if os.Getenv("CLICKHOUSE_URL") == "" {
17+
t.Skip("Skipping integration test - CLICKHOUSE_URL not set")
18+
}
19+
20+
ctx := context.Background()
21+
22+
// Create ClickHouse client
23+
cfg := &config.Config{
24+
ClickHouseURL: os.Getenv("CLICKHOUSE_URL"),
25+
ClickHouseDatabase: "default",
26+
ClickHouseUsername: "default",
27+
ClickHousePassword: "",
28+
TruncateTable: true,
29+
}
30+
31+
chClient, err := storage.NewClickHouseClient(cfg)
32+
if err != nil {
33+
t.Fatalf("Failed to create ClickHouse client: %v", err)
34+
}
35+
36+
tableName := "test_sbom_components"
37+
38+
t.Run("Setup ClickHouse table", func(t *testing.T) {
39+
err := chClient.SetupTable(ctx, tableName)
40+
if err != nil {
41+
t.Fatalf("Failed to setup table: %v", err)
42+
}
43+
44+
t.Logf("✓ Successfully set up table: %s", tableName)
45+
})
46+
47+
t.Run("Insert SBOM data", func(t *testing.T) {
48+
// Create test SBOM file
49+
testSBOM := `/tmp/test-clickhouse-sbom.json`
50+
testContent := `{
51+
"bomFormat": "CycloneDX",
52+
"specVersion": "1.6",
53+
"components": [
54+
{
55+
"name": "lodash",
56+
"version": "4.17.21",
57+
"type": "library",
58+
"licenses": [
59+
{
60+
"license": {
61+
"id": "MIT"
62+
}
63+
}
64+
],
65+
"source": "github"
66+
},
67+
{
68+
"name": "react",
69+
"version": "18.2.0",
70+
"type": "library",
71+
"licenses": [
72+
{
73+
"license": {
74+
"id": "MIT"
75+
}
76+
}
77+
],
78+
"source": "github"
79+
}
80+
]
81+
}`
82+
83+
if err := os.WriteFile(testSBOM, []byte(testContent), 0644); err != nil {
84+
t.Fatalf("Failed to create test SBOM: %v", err)
85+
}
86+
defer os.Remove(testSBOM)
87+
88+
// Insert data
89+
err := chClient.InsertSBOMData(ctx, testSBOM, tableName, "cyclonedx")
90+
if err != nil {
91+
t.Fatalf("Failed to insert data: %v", err)
92+
}
93+
94+
t.Log("✓ Successfully inserted SBOM data into ClickHouse")
95+
})
96+
97+
t.Run("Verify table migration", func(t *testing.T) {
98+
// This tests the source column migration
99+
err := chClient.SetupTable(ctx, tableName)
100+
if err != nil {
101+
t.Fatalf("Failed during table setup/migration: %v", err)
102+
}
103+
104+
t.Log("✓ Table migration check passed")
105+
})
106+
}

test/integration/e2e_test.go

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
//go:build integration
2+
// +build integration
3+
4+
package integration
5+
6+
import (
7+
"context"
8+
"os"
9+
"path/filepath"
10+
"testing"
11+
12+
"github.com/ClickHouse/ClickBOM/internal/config"
13+
"github.com/ClickHouse/ClickBOM/internal/sbom"
14+
"github.com/ClickHouse/ClickBOM/internal/storage"
15+
)
16+
17+
func TestEndToEndWorkflow(t *testing.T) {
18+
if os.Getenv("AWS_ENDPOINT_URL") == "" || os.Getenv("CLICKHOUSE_URL") == "" {
19+
t.Skip("Skipping E2E test - AWS_ENDPOINT_URL or CLICKHOUSE_URL not set")
20+
}
21+
22+
ctx := context.Background()
23+
24+
// Create temp directory for test files
25+
tempDir := t.TempDir()
26+
27+
t.Run("Complete SBOM workflow", func(t *testing.T) {
28+
// Step 1: Create a mock SBOM
29+
originalSBOM := filepath.Join(tempDir, "original.json")
30+
sbomContent := `{
31+
"sbom": {
32+
"spdxVersion": "SPDX-2.3",
33+
"SPDXID": "SPDXRef-DOCUMENT",
34+
"name": "test-document",
35+
"packages": [
36+
{
37+
"name": "test-package",
38+
"versionInfo": "1.0.0",
39+
"licenseConcluded": "MIT"
40+
}
41+
]
42+
}
43+
}`
44+
45+
if err := os.WriteFile(originalSBOM, []byte(sbomContent), 0644); err != nil {
46+
t.Fatalf("Failed to create test SBOM: %v", err)
47+
}
48+
49+
t.Log("✓ Created test SBOM file")
50+
51+
// Step 2: Extract from wrapper
52+
extractedSBOM := filepath.Join(tempDir, "extracted.json")
53+
if err := sbom.ExtractSBOMFromWrapper(originalSBOM, extractedSBOM); err != nil {
54+
t.Fatalf("Failed to extract SBOM: %v", err)
55+
}
56+
57+
t.Log("✓ Extracted SBOM from wrapper")
58+
59+
// Step 3: Detect format
60+
format, err := sbom.DetectSBOMFormat(extractedSBOM)
61+
if err != nil {
62+
t.Fatalf("Failed to detect format: %v", err)
63+
}
64+
65+
if format != sbom.FormatSPDXJSON {
66+
t.Errorf("Expected SPDX format, got %s", format)
67+
}
68+
69+
t.Logf("✓ Detected format: %s", format)
70+
71+
// Step 4: Convert to CycloneDX
72+
convertedSBOM := filepath.Join(tempDir, "converted.json")
73+
if err := sbom.ConvertSBOM(extractedSBOM, convertedSBOM, format, sbom.FormatCycloneDX); err != nil {
74+
t.Fatalf("Failed to convert SBOM: %v", err)
75+
}
76+
77+
t.Log("✓ Converted SBOM to CycloneDX")
78+
79+
// Step 5: Upload to S3
80+
s3Client, err := storage.NewS3Client(
81+
ctx,
82+
os.Getenv("AWS_ACCESS_KEY_ID"),
83+
os.Getenv("AWS_SECRET_ACCESS_KEY"),
84+
os.Getenv("AWS_DEFAULT_REGION"),
85+
)
86+
if err != nil {
87+
t.Fatalf("Failed to create S3 client: %v", err)
88+
}
89+
90+
testBucket := "test-bucket"
91+
testKey := "e2e-test.json"
92+
93+
if err := s3Client.Upload(ctx, convertedSBOM, testBucket, testKey, "cyclonedx"); err != nil {
94+
t.Fatalf("Failed to upload to S3: %v", err)
95+
}
96+
97+
t.Log("✓ Uploaded SBOM to S3")
98+
99+
// Step 6: Insert into ClickHouse
100+
cfg := &config.Config{
101+
ClickHouseURL: os.Getenv("CLICKHOUSE_URL"),
102+
ClickHouseDatabase: "default",
103+
ClickHouseUsername: "default",
104+
ClickHousePassword: "",
105+
TruncateTable: true,
106+
}
107+
108+
chClient, err := storage.NewClickHouseClient(cfg)
109+
if err != nil {
110+
t.Fatalf("Failed to create ClickHouse client: %v", err)
111+
}
112+
113+
tableName := "e2e_test_sbom"
114+
115+
if err := chClient.SetupTable(ctx, tableName); err != nil {
116+
t.Fatalf("Failed to setup ClickHouse table: %v", err)
117+
}
118+
119+
if err := chClient.InsertSBOMData(ctx, convertedSBOM, tableName, "cyclonedx"); err != nil {
120+
t.Fatalf("Failed to insert into ClickHouse: %v", err)
121+
}
122+
123+
t.Log("✓ Inserted data into ClickHouse")
124+
125+
// Step 7: Download from S3 and verify
126+
downloadedSBOM := filepath.Join(tempDir, "downloaded.json")
127+
if err := s3Client.Download(ctx, testBucket, testKey, downloadedSBOM); err != nil {
128+
t.Fatalf("Failed to download from S3: %v", err)
129+
}
130+
131+
// Verify downloaded file exists and has content
132+
downloadedData, err := os.ReadFile(downloadedSBOM)
133+
if err != nil {
134+
t.Fatalf("Failed to read downloaded file: %v", err)
135+
}
136+
137+
if len(downloadedData) == 0 {
138+
t.Error("Downloaded file is empty")
139+
}
140+
141+
t.Log("✓ Downloaded and verified SBOM from S3")
142+
})
143+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
//go:build integration
2+
// +build integration
3+
4+
package integration
5+
6+
import (
7+
"os"
8+
"path/filepath"
9+
"testing"
10+
11+
"github.com/ClickHouse/ClickBOM/internal/sbom"
12+
)
13+
14+
func TestSBOMProcessing(t *testing.T) {
15+
tempDir := t.TempDir()
16+
17+
t.Run("Extract SBOM from GitHub wrapper", func(t *testing.T) {
18+
wrappedSBOM := filepath.Join(tempDir, "wrapped.json")
19+
wrappedContent := `{
20+
"sbom": {
21+
"bomFormat": "CycloneDX",
22+
"specVersion": "1.6",
23+
"components": []
24+
}
25+
}`
26+
27+
if err := os.WriteFile(wrappedSBOM, []byte(wrappedContent), 0644); err != nil {
28+
t.Fatalf("Failed to create wrapped SBOM: %v", err)
29+
}
30+
31+
extractedSBOM := filepath.Join(tempDir, "extracted.json")
32+
if err := sbom.ExtractSBOMFromWrapper(wrappedSBOM, extractedSBOM); err != nil {
33+
t.Fatalf("Failed to extract: %v", err)
34+
}
35+
36+
// Verify extracted file
37+
data, err := os.ReadFile(extractedSBOM)
38+
if err != nil {
39+
t.Fatalf("Failed to read extracted file: %v", err)
40+
}
41+
42+
if len(data) == 0 {
43+
t.Error("Extracted file is empty")
44+
}
45+
46+
t.Log("✓ Successfully extracted SBOM from wrapper")
47+
})
48+
49+
t.Run("Detect CycloneDX format", func(t *testing.T) {
50+
cdxSBOM := filepath.Join(tempDir, "cyclonedx.json")
51+
cdxContent := `{
52+
"bomFormat": "CycloneDX",
53+
"specVersion": "1.6",
54+
"components": []
55+
}`
56+
57+
if err := os.WriteFile(cdxSBOM, []byte(cdxContent), 0644); err != nil {
58+
t.Fatalf("Failed to create CycloneDX SBOM: %v", err)
59+
}
60+
61+
format, err := sbom.DetectSBOMFormat(cdxSBOM)
62+
if err != nil {
63+
t.Fatalf("Failed to detect format: %v", err)
64+
}
65+
66+
if format != sbom.FormatCycloneDX {
67+
t.Errorf("Expected CycloneDX, got %s", format)
68+
}
69+
70+
t.Log("✓ Correctly detected CycloneDX format")
71+
})
72+
73+
t.Run("Detect SPDX format", func(t *testing.T) {
74+
spdxSBOM := filepath.Join(tempDir, "spdx.json")
75+
spdxContent := `{
76+
"spdxVersion": "SPDX-2.3",
77+
"SPDXID": "SPDXRef-DOCUMENT",
78+
"name": "test"
79+
}`
80+
81+
if err := os.WriteFile(spdxSBOM, []byte(spdxContent), 0644); err != nil {
82+
t.Fatalf("Failed to create SPDX SBOM: %v", err)
83+
}
84+
85+
format, err := sbom.DetectSBOMFormat(spdxSBOM)
86+
if err != nil {
87+
t.Fatalf("Failed to detect format: %v", err)
88+
}
89+
90+
if format != sbom.FormatSPDXJSON {
91+
t.Errorf("Expected SPDX, got %s", format)
92+
}
93+
94+
t.Log("✓ Correctly detected SPDX format")
95+
})
96+
97+
t.Run("Convert same format (copy)", func(t *testing.T) {
98+
inputSBOM := filepath.Join(tempDir, "input.json")
99+
outputSBOM := filepath.Join(tempDir, "output.json")
100+
101+
content := `{"bomFormat":"CycloneDX","specVersion":"1.6"}`
102+
if err := os.WriteFile(inputSBOM, []byte(content), 0644); err != nil {
103+
t.Fatalf("Failed to create input SBOM: %v", err)
104+
}
105+
106+
err := sbom.ConvertSBOM(inputSBOM, outputSBOM, sbom.FormatCycloneDX, sbom.FormatCycloneDX)
107+
if err != nil {
108+
t.Fatalf("Failed to convert: %v", err)
109+
}
110+
111+
// Verify output exists
112+
if _, err := os.Stat(outputSBOM); os.IsNotExist(err) {
113+
t.Error("Output file was not created")
114+
}
115+
116+
t.Log("✓ Same format conversion (copy) successful")
117+
})
118+
}

0 commit comments

Comments
 (0)