diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-13 14:28:43 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-13 14:28:43 +0300 |
| commit | a73b7973531f2b8632269a8c8359acf69ee61f45 (patch) | |
| tree | 5f9e96b893fcf1a2ca774c76276a07ecfa565711 /internal | |
| parent | 27b94f917064948fa33141309a3f08deb40ffde2 (diff) | |
add compile-time interface assertions for public types (task c4)
Extend the var _ Interface = (*Concrete)(nil) coverage started in j3 to
cover the remaining public types not yet guarded:
- *file.FdFile → file.File (file/file.go)
- streamrow.Row → globalfilter.Candidate (streamrow/row.go; adds
globalfilter import — no cycle since globalfilter does not import streamrow)
- *streamrow.RingBuffer → eventstream.Source
(tui/eventstream/ringbuffer.go; already a type alias for streamrow.RingBuffer)
- *probemanager.Manager → tui/probes.Manager (tui/probes/model.go)
- All 9 generated *types.*Event types → event.Event in the new file
internal/event/interface_assertions.go (non-generated, lives in the event
package which already imports types, so no new import cycle)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/event/interface_assertions.go | 44 | ||||
| -rw-r--r-- | internal/file/file.go | 8 | ||||
| -rw-r--r-- | internal/streamrow/row.go | 10 | ||||
| -rw-r--r-- | internal/tui/eventstream/ringbuffer.go | 8 | ||||
| -rw-r--r-- | internal/tui/probes/model.go | 8 |
5 files changed, 78 insertions, 0 deletions
diff --git a/internal/event/interface_assertions.go b/internal/event/interface_assertions.go new file mode 100644 index 0000000..77a43ea --- /dev/null +++ b/internal/event/interface_assertions.go @@ -0,0 +1,44 @@ +package event + +import "ior/internal/types" + +// --- compile-time interface satisfaction assertions --- +// +// Every generated concrete event type in internal/types must satisfy the Event +// interface (which composes EventIdentity and EventLifecycle). These assertions +// live in the event package rather than in the generated file so they are not +// overwritten by mage generate. The event package already imports types, so no +// new import cycle is introduced. + +var ( + // *types.OpenEvent is the most common event type; it carries open-syscall + // enter-event data (fd, flags, pathname). + _ Event = (*types.OpenEvent)(nil) + + // *types.NullEvent is used for tracepoints that carry no extra payload + // beyond the base header fields. + _ Event = (*types.NullEvent)(nil) + + // *types.FdEvent carries a single file-descriptor field (close, dup, etc.). + _ Event = (*types.FdEvent)(nil) + + // *types.RetEvent is the exit-side event for all syscalls; it carries the + // kernel return value. + _ Event = (*types.RetEvent)(nil) + + // *types.NameEvent carries a single filename field (unlink, mkdir, etc.). + _ Event = (*types.NameEvent)(nil) + + // *types.PathEvent carries a pathname field for path-only syscalls. + _ Event = (*types.PathEvent)(nil) + + // *types.FcntlEvent carries the fcntl command and argument fields. + _ Event = (*types.FcntlEvent)(nil) + + // *types.Dup3Event carries the old and new file-descriptor fields for dup3. + _ Event = (*types.Dup3Event)(nil) + + // *types.OpenByHandleAtEvent carries the mount-fd and flags for + // open_by_handle_at syscalls. + _ Event = (*types.OpenByHandleAtEvent)(nil) +) diff --git a/internal/file/file.go b/internal/file/file.go index fc9c320..f933d69 100644 --- a/internal/file/file.go +++ b/internal/file/file.go @@ -217,3 +217,11 @@ func (f pathnameFile) String() string { return sb.String() } + +// --- compile-time interface satisfaction assertions --- +// +// *FdFile is the primary public implementation of File used throughout the +// codebase. The assertion causes a build error if FdFile drifts out of sync +// with the File interface contract. + +var _ File = (*FdFile)(nil) diff --git a/internal/streamrow/row.go b/internal/streamrow/row.go index 457fcc0..026aa93 100644 --- a/internal/streamrow/row.go +++ b/internal/streamrow/row.go @@ -5,6 +5,7 @@ import ( "time" "ior/internal/event" + "ior/internal/globalfilter" "ior/internal/types" ) @@ -121,6 +122,15 @@ func New(seq uint64, pair *event.Pair) Row { return row } +// --- compile-time interface satisfaction assertion --- +// +// Row must satisfy globalfilter.Candidate so the TUI eventstream model can +// pass stream rows directly into Filter.Matches for live filtering. All +// Candidate methods are defined on the value receiver so both Row and *Row +// satisfy the interface; we assert the value form as it is the common usage. + +var _ globalfilter.Candidate = Row{} + // NewWarning creates a synthetic row for non-fatal runtime warnings. func NewWarning(seq uint64, message string) Row { now := uint64(time.Now().UnixNano()) diff --git a/internal/tui/eventstream/ringbuffer.go b/internal/tui/eventstream/ringbuffer.go index 8644b42..8879114 100644 --- a/internal/tui/eventstream/ringbuffer.go +++ b/internal/tui/eventstream/ringbuffer.go @@ -15,3 +15,11 @@ const ringBufferCapacity = streamrow.RingBufferCapacity func NewRingBuffer() *RingBuffer { return streamrow.NewRingBuffer() } + +// --- compile-time interface satisfaction assertion --- +// +// *RingBuffer (= *streamrow.RingBuffer) must satisfy the Source contract so +// the TUI dashboard and stream views can receive live events without importing +// the lower-level streamrow package directly. + +var _ Source = (*RingBuffer)(nil) diff --git a/internal/tui/probes/model.go b/internal/tui/probes/model.go index baf22e8..b7e694f 100644 --- a/internal/tui/probes/model.go +++ b/internal/tui/probes/model.go @@ -346,3 +346,11 @@ func truncateText(s string, limit int) string { } return string(runes[:limit-3]) + "..." } + +// --- compile-time interface satisfaction assertion --- +// +// *probemanager.Manager must satisfy the Manager interface defined in this +// package. The tui/probes package already imports probemanager, so this +// assertion adds no new dependency. + +var _ Manager = (*probemanager.Manager)(nil) |
