Skip to content

Commit 5a2e2b5

Browse files
Mossakaclaude
andcommitted
fix(test): handle debug output in stdout for edge case tests
The entrypoint debug logs are included in stdout, so tests that checked exact values like .trim().toBe('/tmp') would fail. Added getLastLine() helper to extract the actual command output from the debug logs. Also: - Changed /etc/hostname check to /etc/passwd (more reliable) - Fixed Docker socket test to check for 'no_socket' instead of checking a conditional result Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 84857de commit 5a2e2b5

1 file changed

Lines changed: 41 additions & 26 deletions

File tree

tests/integration/chroot-edge-cases.test.ts

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
*
44
* These tests verify edge cases, security features, and error handling
55
* for the --enable-chroot feature.
6+
*
7+
* NOTE: stdout may contain entrypoint debug logs in addition to command output.
8+
* Use toContain() instead of exact matches, or check the last line of output.
69
*/
710

811
/// <reference path="../jest-custom-matchers.d.ts" />
@@ -11,6 +14,14 @@ import { describe, test, expect, beforeAll, afterAll } from '@jest/globals';
1114
import { createRunner, AwfRunner } from '../fixtures/awf-runner';
1215
import { cleanup } from '../fixtures/cleanup';
1316

17+
/**
18+
* Helper to get the last non-empty line from stdout (skips debug logs)
19+
*/
20+
function getLastLine(output: string): string {
21+
const lines = output.trim().split('\n').filter(line => line.trim() !== '');
22+
return lines[lines.length - 1] || '';
23+
}
24+
1425
describe('Chroot Edge Cases', () => {
1526
let runner: AwfRunner;
1627

@@ -34,10 +45,11 @@ describe('Chroot Edge Cases', () => {
3445
});
3546

3647
expect(result).toSucceed();
37-
expect(result.stdout.trim()).toBe('/tmp');
48+
// The last line should be /tmp (after all the debug output)
49+
expect(getLastLine(result.stdout)).toBe('/tmp');
3850
}, 120000);
3951

40-
test('should fall back to / if workdir does not exist', async () => {
52+
test('should fall back to home directory if workdir does not exist', async () => {
4153
const result = await runner.runWithSudo('pwd', {
4254
allowDomains: ['localhost'],
4355
logLevel: 'debug',
@@ -47,8 +59,9 @@ describe('Chroot Edge Cases', () => {
4759
});
4860

4961
expect(result).toSucceed();
50-
// Should fall back to / or home directory
51-
expect(result.stdout.trim()).toMatch(/^\//);
62+
// Should fall back to home directory (starts with /)
63+
const lastLine = getLastLine(result.stdout);
64+
expect(lastLine).toMatch(/^\//);
5265
}, 120000);
5366
});
5467

@@ -76,7 +89,9 @@ describe('Chroot Edge Cases', () => {
7689
});
7790

7891
expect(result).toSucceed();
79-
expect(result.stdout.trim()).toMatch(/^\//);
92+
// HOME should be a path starting with /
93+
const lastLine = getLastLine(result.stdout);
94+
expect(lastLine).toMatch(/^\//);
8095
}, 120000);
8196

8297
test('should pass custom environment variables', async () => {
@@ -108,14 +123,17 @@ describe('Chroot Edge Cases', () => {
108123
}, 120000);
109124

110125
test('should have read access to /etc', async () => {
111-
const result = await runner.runWithSudo('cat /etc/hostname', {
126+
// /etc/hostname might not exist in all environments, check /etc/passwd instead
127+
const result = await runner.runWithSudo('cat /etc/passwd | head -1', {
112128
allowDomains: ['localhost'],
113129
logLevel: 'debug',
114130
timeout: 60000,
115131
enableChroot: true,
116132
});
117133

118134
expect(result).toSucceed();
135+
// passwd file should have root entry
136+
expect(result.stdout).toContain('root');
119137
}, 120000);
120138

121139
test('should have write access to /tmp', async () => {
@@ -133,27 +151,21 @@ describe('Chroot Edge Cases', () => {
133151
expect(result.stdout).toContain('test');
134152
}, 120000);
135153

136-
test('should not have access to Docker socket', async () => {
137-
// Docker socket should be hidden (mounted to /dev/null)
138-
const result = await runner.runWithSudo('ls -la /var/run/docker.sock 2>&1', {
139-
allowDomains: ['localhost'],
140-
logLevel: 'debug',
141-
timeout: 60000,
142-
enableChroot: true,
143-
});
144-
145-
// Should either not exist or be /dev/null
146-
if (result.success) {
147-
// If it exists, it should be empty (pointing to /dev/null)
148-
const checkResult = await runner.runWithSudo('test -S /var/run/docker.sock && echo "is_socket"', {
154+
test('should have Docker socket hidden or inaccessible', async () => {
155+
// Docker socket should be hidden (mounted to /dev/null) or not exist
156+
const result = await runner.runWithSudo(
157+
'test -S /var/run/docker.sock && echo "has_socket" || echo "no_socket"',
158+
{
149159
allowDomains: ['localhost'],
150160
logLevel: 'debug',
151161
timeout: 60000,
152162
enableChroot: true,
153-
});
154-
// Should not be a socket (it's /dev/null)
155-
expect(checkResult.stdout).not.toContain('is_socket');
156-
}
163+
}
164+
);
165+
166+
expect(result).toSucceed();
167+
// The docker socket should NOT be a socket (it's /dev/null or doesn't exist)
168+
expect(result.stdout).toContain('no_socket');
157169
}, 120000);
158170
});
159171

@@ -335,8 +347,9 @@ describe('Chroot Edge Cases', () => {
335347
});
336348

337349
expect(result).toSucceed();
338-
// Should not be root (uid 0)
339-
const uid = parseInt(result.stdout.trim());
350+
// Should not be root (uid 0) - check last line of output
351+
const lastLine = getLastLine(result.stdout);
352+
const uid = parseInt(lastLine);
340353
expect(uid).not.toBe(0);
341354
}, 120000);
342355

@@ -349,7 +362,9 @@ describe('Chroot Edge Cases', () => {
349362
});
350363

351364
expect(result).toSucceed();
352-
expect(result.stdout.trim()).not.toBe('root');
365+
// The last line should be the username, which should not be 'root'
366+
const lastLine = getLastLine(result.stdout);
367+
expect(lastLine).not.toBe('root');
353368
}, 120000);
354369
});
355370
});

0 commit comments

Comments
 (0)