diff --git a/lib/src/pty/pty_log.dart b/lib/src/pty/pty_log.dart index 2e50781c..7c61f9bc 100644 --- a/lib/src/pty/pty_log.dart +++ b/lib/src/pty/pty_log.dart @@ -65,7 +65,12 @@ class IsolateCrumbFile { IsolateCrumbFile(String? path, this.source, {int capBytes = 256 * 1024}) : _capBytes = capBytes { if (path == null) return; try { - final raf = File(path).openSync(mode: FileMode.append); + final f = File(path); + // Create the parent dir ourselves — a standalone caller (the soak probe) + // may point us at a dir nothing else has made yet. In the app the + // FileLogSink already created logDirectory(), so this is a no-op there. + f.parent.createSync(recursive: true); + final raf = f.openSync(mode: FileMode.append); _raf = raf; _size = raf.lengthSync(); } catch (_) { diff --git a/test/pty/pty_log_test.dart b/test/pty/pty_log_test.dart index 6673bee6..d0eaa94b 100644 --- a/test/pty/pty_log_test.dart +++ b/test/pty/pty_log_test.dart @@ -44,6 +44,14 @@ void main() { c.close(); }); + test('creates a missing parent directory (standalone soak probe case)', () { + final nested = '${dir.path}${Platform.pathSeparator}a${Platform.pathSeparator}b${Platform.pathSeparator}crumbs.log'; + final c = IsolateCrumbFile(nested, 'conpty.reader')..crumb('ReadFile enter'); + c.close(); + expect(File(nested).existsSync(), isTrue); + expect(File(nested).readAsStringSync(), contains('ReadFile enter')); + }); + test('writes one tagged, timestamped line per crumb', () { final c = IsolateCrumbFile(path(), 'pty.reader'); expect(c.enabled, isTrue);