Skip to content

Commit 31d36c9

Browse files
author
SWORDIntel
committed
feat: Directory cleanup and installer enhancements
- Organized build scripts into builders/ directory - Moved config files to config/ directory - Moved media files to assets/ directory - Moved logs to logs/ directory - Updated install.sh to reference builders/ paths - Added auto-bootstrap dependencies functionality - Added non-interactive mode support (--non-interactive, -y) - Added automatic sudo handling - Enhanced error handling for package installation
1 parent df5e4ca commit 31d36c9

30 files changed

+5897
-0
lines changed

assets/410.svg

Lines changed: 5 additions & 0 deletions
Loading

assets/Example.jpg

8.81 KB
Loading

assets/load-test.js

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
// K6 Load Testing Configuration for Media Hardening Service
2+
// Tests throughput, latency, and resource usage under load
3+
4+
import http from 'k6/http';
5+
import { check, sleep } from 'k6';
6+
import { Rate, Trend, Counter } from 'k6/metrics';
7+
8+
// Custom metrics
9+
const errorRate = new Rate('errors');
10+
const processingDuration = new Trend('processing_duration');
11+
const filesProcessed = new Counter('files_processed');
12+
const securityViolations = new Counter('security_violations');
13+
14+
// Load test configuration
15+
export const options = {
16+
// Scenario 1: Smoke test (quick validation)
17+
stages: [
18+
{ duration: '30s', target: 5 }, // Ramp up to 5 users
19+
{ duration: '1m', target: 5 }, // Stay at 5 users
20+
{ duration: '30s', target: 0 }, // Ramp down
21+
],
22+
23+
// Thresholds (SLOs)
24+
thresholds: {
25+
'http_req_duration': ['p(95)<5000'], // 95% of requests should complete within 5s
26+
'http_req_failed': ['rate<0.1'], // Error rate should be less than 10%
27+
'errors': ['rate<0.05'], // Custom error rate threshold
28+
'processing_duration': ['p(99)<10000'], // 99th percentile processing time
29+
},
30+
31+
// Alternative scenarios (comment/uncomment as needed)
32+
33+
// Scenario 2: Load test (sustained load)
34+
// stages: [
35+
// { duration: '2m', target: 50 }, // Ramp up to 50 users
36+
// { duration: '5m', target: 50 }, // Stay at 50 users
37+
// { duration: '2m', target: 0 }, // Ramp down
38+
// ],
39+
40+
// Scenario 3: Stress test (find breaking point)
41+
// stages: [
42+
// { duration: '2m', target: 100 }, // Ramp up to 100 users
43+
// { duration: '5m', target: 100 }, // Stay at 100
44+
// { duration: '2m', target: 200 }, // Ramp up to 200
45+
// { duration: '5m', target: 200 }, // Stay at 200
46+
// { duration: '2m', target: 0 }, // Ramp down
47+
// ],
48+
49+
// Scenario 4: Spike test (sudden traffic spike)
50+
// stages: [
51+
// { duration: '1m', target: 10 }, // Normal load
52+
// { duration: '30s', target: 200 }, // Sudden spike
53+
// { duration: '1m', target: 200 }, // Sustain spike
54+
// { duration: '30s', target: 10 }, // Return to normal
55+
// { duration: '1m', target: 0 }, // Ramp down
56+
// ],
57+
};
58+
59+
// Configuration
60+
const BASE_URL = __ENV.BASE_URL || 'http://localhost:8080';
61+
const MEDIA_PROCESSOR_URL = __ENV.MEDIA_PROCESSOR_URL || 'http://localhost:9000';
62+
63+
// Sample test files (base64 encoded for convenience)
64+
// In production, you'd load these from actual files
65+
const TEST_FILES = {
66+
// Minimal valid PNG (1x1 pixel, red)
67+
png: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==',
68+
69+
// Minimal JPEG header
70+
jpeg: '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/wAALCAABAAEBAREA/8QAFAABAAAAAAAAAAAAAAAAAAAACv/EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAD8AVp//2Q==',
71+
};
72+
73+
// Test data generator - creates various test scenarios
74+
function generateTestFile(fileType, scenario = 'valid') {
75+
const files = {
76+
valid_png: {
77+
name: 'test_valid.png',
78+
data: TEST_FILES.png,
79+
contentType: 'image/png',
80+
},
81+
valid_jpeg: {
82+
name: 'test_valid.jpg',
83+
data: TEST_FILES.jpeg,
84+
contentType: 'image/jpeg',
85+
},
86+
truncated: {
87+
name: 'test_truncated.png',
88+
data: TEST_FILES.png.substring(0, 20), // Truncated
89+
contentType: 'image/png',
90+
},
91+
malformed: {
92+
name: 'test_malformed.jpg',
93+
data: 'NOT_A_VALID_IMAGE_FILE',
94+
contentType: 'image/jpeg',
95+
},
96+
large: {
97+
name: 'test_large.bin',
98+
data: 'X'.repeat(10000), // Simulate large file
99+
contentType: 'application/octet-stream',
100+
},
101+
};
102+
103+
return files[scenario] || files.valid_png;
104+
}
105+
106+
// Main test function
107+
export default function () {
108+
// Select test scenario (90% valid, 10% malformed for realistic load)
109+
const scenarios = ['valid_png', 'valid_jpeg', 'malformed'];
110+
const weights = [0.45, 0.45, 0.10];
111+
const rand = Math.random();
112+
let scenario = scenarios[0];
113+
114+
let cumulative = 0;
115+
for (let i = 0; i < scenarios.length; i++) {
116+
cumulative += weights[i];
117+
if (rand < cumulative) {
118+
scenario = scenarios[i];
119+
break;
120+
}
121+
}
122+
123+
const testFile = generateTestFile(scenario);
124+
125+
// Test 1: Health check endpoint
126+
const healthRes = http.get(`${BASE_URL}/health`);
127+
check(healthRes, {
128+
'health check status 200': (r) => r.status === 200,
129+
});
130+
131+
// Test 2: Metrics endpoint (ensure monitoring is working)
132+
const metricsRes = http.get(`${BASE_URL}/metrics`);
133+
check(metricsRes, {
134+
'metrics endpoint accessible': (r) => r.status === 200,
135+
'metrics contain expected data': (r) => r.body.includes('media_processor'),
136+
});
137+
138+
// Test 3: Process media file (simulated via direct CLI invocation)
139+
// Note: In a real setup, you'd have an HTTP API wrapper around the CLI
140+
// For now, we test the monitoring endpoints
141+
142+
// Check for security violations in metrics
143+
if (metricsRes.body.includes('security_violations_total')) {
144+
const violationMatch = metricsRes.body.match(/security_violations_total{[^}]*} (\d+)/);
145+
if (violationMatch && parseInt(violationMatch[1]) > 0) {
146+
securityViolations.add(1);
147+
}
148+
}
149+
150+
// Track processing
151+
filesProcessed.add(1);
152+
153+
// Record errors
154+
const hasError = healthRes.status !== 200 || metricsRes.status !== 200;
155+
errorRate.add(hasError);
156+
157+
// Simulate processing time based on file type
158+
const processingTime = scenario.includes('large') ?
159+
Math.random() * 3000 + 2000 : // 2-5 seconds for large files
160+
Math.random() * 1000 + 500; // 0.5-1.5 seconds for normal files
161+
162+
processingDuration.add(processingTime);
163+
164+
// Small delay between requests (realistic user behavior)
165+
sleep(Math.random() * 2 + 1); // 1-3 seconds
166+
}
167+
168+
// Setup function (runs once at start)
169+
export function setup() {
170+
console.log('Starting load test...');
171+
console.log(`Target: ${BASE_URL}`);
172+
console.log('Scenario: Smoke test (5 concurrent users)');
173+
console.log('');
174+
175+
// Verify service is accessible
176+
const res = http.get(`${BASE_URL}/health`);
177+
if (res.status !== 200) {
178+
throw new Error(`Service not accessible at ${BASE_URL}`);
179+
}
180+
181+
return { startTime: Date.now() };
182+
}
183+
184+
// Teardown function (runs once at end)
185+
export function teardown(data) {
186+
const duration = (Date.now() - data.startTime) / 1000;
187+
console.log('');
188+
console.log('Load test completed!');
189+
console.log(`Total duration: ${duration.toFixed(2)} seconds`);
190+
console.log('');
191+
console.log('Check the full report above for detailed metrics.');
192+
console.log('');
193+
console.log('To view live metrics during the test:');
194+
console.log(` curl ${BASE_URL}/metrics`);
195+
console.log('');
196+
console.log('To view Grafana dashboards:');
197+
console.log(' http://localhost:3000 (if running via docker-compose)');
198+
}
199+
200+
// Handle HTTP errors
201+
export function handleSummary(data) {
202+
return {
203+
'stdout': textSummary(data, { indent: ' ', enableColors: true }),
204+
'load-test-results.json': JSON.stringify(data),
205+
};
206+
}
207+
208+
// Helper function for text summary
209+
function textSummary(data, options = {}) {
210+
const indent = options.indent || '';
211+
const enableColors = options.enableColors || false;
212+
213+
let output = '\n';
214+
output += `${indent}Load Test Summary\n`;
215+
output += `${indent}================\n\n`;
216+
217+
// Requests
218+
const requests = data.metrics.http_reqs?.values;
219+
if (requests) {
220+
output += `${indent}HTTP Requests:\n`;
221+
output += `${indent} Total: ${requests.count}\n`;
222+
output += `${indent} Rate: ${requests.rate.toFixed(2)}/s\n\n`;
223+
}
224+
225+
// Duration
226+
const duration = data.metrics.http_req_duration?.values;
227+
if (duration) {
228+
output += `${indent}Request Duration:\n`;
229+
output += `${indent} Min: ${duration.min.toFixed(2)}ms\n`;
230+
output += `${indent} Avg: ${duration.avg.toFixed(2)}ms\n`;
231+
output += `${indent} Max: ${duration.max.toFixed(2)}ms\n`;
232+
output += `${indent} p(95): ${duration['p(95)'].toFixed(2)}ms\n`;
233+
output += `${indent} p(99): ${duration['p(99)'].toFixed(2)}ms\n\n`;
234+
}
235+
236+
// Errors
237+
const failed = data.metrics.http_req_failed?.values;
238+
if (failed) {
239+
const rate = (failed.rate * 100).toFixed(2);
240+
output += `${indent}Errors:\n`;
241+
output += `${indent} Failed requests: ${failed.passes} (${rate}%)\n\n`;
242+
}
243+
244+
return output;
245+
}

assets/mov_bbb.mp4

770 KB
Binary file not shown.

assets/nurbcup2si.png

33.5 KB
Loading

builders/README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# IMAGEHARDER Build Scripts
2+
3+
This directory contains all build scripts for IMAGEHARDER components.
4+
5+
## Build Scripts
6+
7+
### Core Builds
8+
- **build.sh** - Core image libraries (GIF, PNG, JPEG)
9+
- **build_extended_formats.sh** - Extended formats (AVIF, JXL, TIFF, OpenEXR)
10+
- **build_audio.sh** - Audio codec libraries (MP3, Vorbis, Opus, FLAC)
11+
- **build_ffmpeg_wasm.sh** - FFmpeg WebAssembly sandbox
12+
- **build_all_hardened.sh** - All-in-one hardened media stack builder
13+
14+
### Driver Builds
15+
- **build_hardened_drivers.sh** - Hardened video driver configurations
16+
- **build_hardened_audio_drivers.sh** - Hardened audio driver configurations
17+
18+
### Setup Scripts
19+
- **setup_emsdk.sh** - Emscripten SDK setup for WebAssembly builds
20+
- **setup-cockpit.sh** - Cockpit setup (if applicable)
21+
22+
### Testing & Verification
23+
- **integration-tests.sh** - Integration test suite
24+
- **benchmark.sh** - Benchmark tools
25+
- **test_corpus_generator.sh** - Test corpus generation
26+
- **verify_meteor_lake.sh** - Meteor Lake hardware verification
27+
28+
### Utilities
29+
- **generate-sbom.sh** - Software Bill of Materials generation
30+
31+
## Usage
32+
33+
These scripts are called by the main orchestrator (`install.sh` in the root directory). They can also be run individually:
34+
35+
```bash
36+
# Build core libraries
37+
./builders/build.sh
38+
39+
# Build extended formats
40+
IMAGEHARDEN_CPU=host ./builders/build_extended_formats.sh
41+
42+
# Build audio codecs
43+
./builders/build_audio.sh
44+
```
45+
46+
## CPU Profiles
47+
48+
Set `IMAGEHARDEN_CPU` environment variable:
49+
- `generic` - Generic x86-64 (default)
50+
- `v3` - x86-64-v3 (AVX2 baseline)
51+
- `host` - Native CPU (Meteor Lake optimized)

0 commit comments

Comments
 (0)