Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,6 @@ it.prop(
labelOf(admissionOf(subject, new AdmitEntryWrite({ mode: 'read-write', entry }))) === `admitted ${wireOf(entry)}`,
)

it.prop(
'∀e_AdmitEntryWrite_→OversizedPastCap',
{ of: [TraceEntry], subject: admitEntryWrite, arbitrary: { seed: 500_012 } },
(subject, [entry]) => {
const exact = paddedTo(entry, WIRE_BYTES_CAP)
const over = paddedTo(entry, WIRE_BYTES_CAP + 1)
return labelOf(admissionOf(subject, new AdmitEntryWrite({ mode: 'read-write', entry: exact }))) ===
`admitted ${wireOf(exact)}` &&
labelOf(admissionOf(subject, new AdmitEntryWrite({ mode: 'read-write', entry: over }))) === 'refused Oversized'
},
)

it.prop(
'∀e_AdmitEntryWrite_→ReadOnlyRefusedBeforeSize',
{ of: [TraceEntry, Schema.Boolean], subject: admitEntryWrite, arbitrary: { seed: 500_013 } },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { it } from '@systemfsoftware/vitest'
import * as Arr from 'effect/Array'
import * as Effect from 'effect/Effect'
import * as Match from 'effect/Match'
import * as Option from 'effect/Option'
import * as Result from 'effect/Result'
Expand All @@ -11,8 +11,6 @@ import { entryWireBytesOf, entryWireTextOf, TraceEntry } from '../entry.schema.j

type Classify = typeof classifyStoredEntry

const WIRE_BYTES_CAP = 1_048_576

const utf8 = new TextEncoder()

const readOf = (classify: Classify, command: ClassifyStoredEntry): CacheReadResult =>
Expand All @@ -27,45 +25,81 @@ const labelOf = (read: CacheReadResult): string =>
Invalid: ({ reason }) => `invalid ${reason}`,
})

const isHit = (read: CacheReadResult): boolean =>
Match.valueTags(read, { Hit: () => true, Miss: () => false, Invalid: () => false })

const wireOf = (entry: TraceEntry): string => Option.getOrElse(entryWireTextOf(entry), () => '')

const withAlerts = (entry: TraceEntry, alerts: ReadonlyArray<string>): TraceEntry => ({ ...entry, alerts })
const WIRE_BYTES_CAP = 1_048_576

type AlertSlot = readonly [head: string, tail: string]
const withAlerts = (entry: TraceEntry, alerts: ReadonlyArray<string>): TraceEntry => ({ ...entry, alerts })

const alertSlotOf = (entry: TraceEntry): AlertSlot => {
const empty = wireOf(withAlerts(entry, ['']))
const filled = wireOf(withAlerts(entry, ['a']))
const at = Option.getOrElse(
Arr.findFirstIndex(empty.split(''), (char, index) => char !== filled[index]),
() => empty.length,
)
return [empty.slice(0, at), empty.slice(at)]
const paddedTo = (entry: TraceEntry, bytes: number): TraceEntry => {
const slim = withAlerts(entry, [])
return withAlerts(slim, ['a'.repeat(bytes - entryWireBytesOf(slim) - 2)])
}

const paddedWireOf = ([head, tail]: AlertSlot, count: number): string => `${head}${'a'.repeat(count)}${tail}`

it.prop(
'∀e_ClassifyStoredEntry_≡HitRoundTripsWireText',
{ of: [TraceEntry], subject: classifyStoredEntry, arbitrary: { seed: 500_001 } },
(subject, [entry]) => labelOf(readOf(subject, foundOf(utf8.encode(wireOf(entry))))) === `hit ${wireOf(entry)}`,
)

const SWEEP_BOUND = 16

/** Folds a drawn integer onto a size offset in -SWEEP_BOUND..SWEEP_BOUND, so every draw lands near the cap. */
const offsetOf = (n: number): number => {
const span = 2 * SWEEP_BOUND + 1
return (((n % span) + span) % span) - SWEEP_BOUND
}

const templateEntry = Effect.runSync(
Schema.decodeEffect(TraceEntry)({
schema: 'trace-1',
keyedBy: {
step: 'act',
project: 'shop',
test: 'checkout pays',
target: 'staging',
engine: { adapter: '@systemfsoftware/effect-e2e-web', kind: 'web' },
app: 'shop',
instruction: 'open /cart',
params: {},
slots: [],
agent: { name: 'default', contextDigest: '0'.repeat(64) },
},
start: { origin: 'https://shop.example', path: '/', query: [] },
actions: [],
end: { origin: 'https://shop.example', path: '/cart', query: [] },
anchors: { appeared: [], gone: [] },
checks: [],
alerts: [],
provenance: {
engine: { adapter: '@systemfsoftware/effect-e2e-web', kind: 'web' },
engineVersion: '1.0.0',
model: { provider: 'openrouter', model: 'deepseek/deepseek-flash-latest' },
agent: 'default',
version: '1.0.0',
},
}),
)

it.prop(
'∀e_ClassifyStoredEntry_→OversizedPastCap',
{ of: [TraceEntry], subject: classifyStoredEntry, arbitrary: { seed: 500_002 } },
(subject, [entry]) => {
const slot = alertSlotOf(entry)
const base = entryWireBytesOf(withAlerts(entry, ['']))
const exact = utf8.encode(paddedWireOf(slot, WIRE_BYTES_CAP - base))
const over = utf8.encode(paddedWireOf(slot, WIRE_BYTES_CAP + 1 - base))
return exact.length === WIRE_BYTES_CAP &&
over.length === WIRE_BYTES_CAP + 1 &&
isHit(readOf(subject, foundOf(exact))) &&
labelOf(readOf(subject, foundOf(over))) === 'invalid oversized'
'∀n_ClassifyStoredEntry_≤WireCap',
{
of: [Schema.Int],
subject: classifyStoredEntry,
cover: {
BelowCap: [(n: number) => offsetOf(n) < 0, 0.3],
AtCap: [(n: number) => offsetOf(n) === 0, 0.02],
AboveCap: [(n: number) => offsetOf(n) > 0, 0.3],
},
arbitrary: { seed: 500_002 },
},
(subject, [n]) => {
const bytes = utf8.encode(wireOf(paddedTo(templateEntry, WIRE_BYTES_CAP + offsetOf(Number(n)))))
return Match.valueTags(readOf(subject, foundOf(bytes)), {
Hit: () => bytes.length <= WIRE_BYTES_CAP,
Invalid: () => bytes.length > WIRE_BYTES_CAP,
Miss: () => false,
})
},
)

Expand Down
174 changes: 174 additions & 0 deletions packages/effect-e2e/tests/cache-store.cap.integration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import {
CacheReadResult,
CacheStorageFailed,
CacheWriteResult,
KeyDigest,
MemoryCacheStore,
TraceEntry,
} from '@systemfsoftware/effect-e2e/cache'
import { Gherkin, Given, it, makeFeature, Then, When } from '@systemfsoftware/effect-gherkin-spec'
import * as Effect from 'effect/Effect'
import * as Layer from 'effect/Layer'
import * as Match from 'effect/Match'
import * as Schema from 'effect/Schema'

const Feature = makeFeature({ it })

/** The spec constant the store's own cap must agree with, kept here so the tests never import it. */
const WIRE_BYTES_CAP = 1_048_576

const utf8 = new TextEncoder()

const D1 = KeyDigest.make('1'.repeat(64))

const route = (path: string): Schema.JsonObject => ({ origin: 'https://shop.example', path, query: [] })

const entryJson = (path: string, alerts: ReadonlyArray<string>): Schema.JsonObject => ({
schema: 'trace-1',
keyedBy: {
step: 'act',
project: 'shop',
test: 'checkout pays',
target: 'staging',
engine: { adapter: '@systemfsoftware/effect-e2e-web', kind: 'web' },
app: 'shop',
instruction: `open ${path}`,
params: {},
slots: [],
agent: { name: 'default', contextDigest: '0'.repeat(64) },
},
start: route('/'),
actions: [{ action: { _tag: 'Navigate', url: `https://shop.example${path}` }, controls: [] }],
end: route(path),
anchors: { appeared: [], gone: [] },
checks: [],
alerts,
provenance: {
engine: { adapter: '@systemfsoftware/effect-e2e-web', kind: 'web' },
engineVersion: '1.0.0',
model: { provider: 'openrouter', model: 'deepseek/deepseek-flash-latest' },
agent: 'default',
version: '1.0.0',
},
})

const isJsonArray = (value: Schema.Json): value is Schema.JsonArray => Array.isArray(value)

const isJsonObject = (value: Schema.Json): value is Schema.JsonObject =>
typeof value === 'object' && value !== null && !isJsonArray(value)

/** Canonical wire text built here, never through the production encoder. */
const canonicalOf = (value: Schema.Json): string =>
isJsonArray(value)
? `[${value.map(canonicalOf).join(',')}]`
: isJsonObject(value)
? `{${
Object.entries(value)
.sort(([left], [right]) => (left < right ? -1 : 1))
.map(([key, field]) => `${JSON.stringify(key)}:${canonicalOf(field)}`)
.join(',')
}}`
: JSON.stringify(value)

const entryAtBytes = (bytes: number): Schema.JsonObject => {
const base = utf8.encode(canonicalOf(entryJson('/padded', ['']))).length
return entryJson('/padded', ['a'.repeat(bytes - base)])
}

const EXACT_CAP = entryAtBytes(WIRE_BYTES_CAP)
const OVER_CAP = entryAtBytes(WIRE_BYTES_CAP + 1)

const entryOf = (json: Schema.JsonObject): Effect.Effect<TraceEntry> =>
Effect.orDie(Schema.decodeUnknownEffect(TraceEntry)(json))

const readLabel = (read: CacheReadResult): string =>
Match.valueTags(read, {
Hit: () => 'Hit',
Miss: () => 'Miss',
Invalid: ({ reason }) => `Invalid(${reason})`,
})

const writeLabel = (write: Effect.Effect<CacheWriteResult, CacheStorageFailed>): Effect.Effect<string> =>
Effect.match(write, {
onFailure: (failure) => `CacheStorageFailed(${failure.message})`,
onSuccess: CacheWriteResult.match({
Written: () => 'Written',
ReadOnly: () => 'ReadOnly',
Oversized: () => 'Oversized',
}),
})

Feature('The wire byte cap at the cache store boundary')
.withLayer(Layer.empty)
.live('the scenarios run the real admit and classify workflows over an in-memory store')
.body(({ scenario }) => {
scenario(
'An entry of exactly the wire byte cap is admitted, and its bytes are exactly the cap',
Gherkin.Do.pipe(
Given('a read-write memory store')('store', () => MemoryCacheStore.make({ mode: 'read-write' })),
When('the exact-cap entry is written under a fresh digest')(
'write',
({ store }) => Effect.flatMap(entryOf(EXACT_CAP), (entry) => writeLabel(store.write(D1, entry))),
),
Then('the store admits it, and the entry is exactly 1048576 bytes')((state, expect) =>
expect([state.write, utf8.encode(canonicalOf(EXACT_CAP)).length]).toEqual(['Written', WIRE_BYTES_CAP])
),
),
)

scenario(
'An entry one byte past the wire byte cap is refused as oversized',
Gherkin.Do.pipe(
Given('a read-write memory store')('store', () => MemoryCacheStore.make({ mode: 'read-write' })),
When('the over-cap entry is written under a fresh digest')(
'write',
({ store }) => Effect.flatMap(entryOf(OVER_CAP), (entry) => writeLabel(store.write(D1, entry))),
),
Then('the store refuses it, and the entry is exactly 1048577 bytes')((state, expect) =>
expect([state.write, utf8.encode(canonicalOf(OVER_CAP)).length]).toEqual(['Oversized', WIRE_BYTES_CAP + 1])
),
),
)

scenario(
'A stored entry of exactly the wire byte cap is a hit',
Gherkin.Do.pipe(
Given('a read-write memory store seeded with the exact-cap bytes')(
'store',
() =>
MemoryCacheStore.make({
mode: 'read-write',
seed: new Map([[D1, utf8.encode(canonicalOf(EXACT_CAP))]]),
}),
),
When('the store reads that digest')('read', ({ store }) => Effect.map(store.read(D1), readLabel)),
Then('the entry replays as a hit, and the stored bytes are exactly the cap')((state, expect) =>
expect([state.read, utf8.encode(canonicalOf(EXACT_CAP)).length]).toEqual(['Hit', WIRE_BYTES_CAP])
),
),
)

scenario(
'A stored entry one byte past the wire byte cap is invalid oversized',
Gherkin.Do.pipe(
Given('a read-write memory store seeded with the over-cap bytes')(
'store',
() =>
MemoryCacheStore.make({
mode: 'read-write',
seed: new Map([[D1, utf8.encode(canonicalOf(OVER_CAP))]]),
}),
),
When('the store reads that digest')('read', ({ store }) => Effect.map(store.read(D1), readLabel)),
Then('the entry reads back as invalid oversized, and the stored bytes are exactly cap plus one')((
state,
expect,
) =>
expect([state.read, utf8.encode(canonicalOf(OVER_CAP)).length]).toEqual([
'Invalid(oversized)',
WIRE_BYTES_CAP + 1,
])
),
),
)
})
Loading