feat: add host particle field submission contract
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled

This commit is contained in:
OpenAI Codex
2026-09-04 18:35:49 +08:00
parent 285d23a58f
commit 1e8eca7912
16 changed files with 756 additions and 8 deletions

View File

@@ -346,6 +346,160 @@ TEST(Source, LocalProductionFeedRejectsMissingGeneration) {
EXPECT_EQ(result.error, particle::ParticleFieldAdapterError::InvalidTimestampOrIdentity);
}
TEST(Source, CanonicalFieldUsesEastwardUAndNorthwardV) {
const auto east = fixtureBytes("uniform-east", "field.f32");
const auto north = fixtureBytes("uniform-north", "field.f32");
const auto vortex = fixtureBytes("vortex", "field.f32");
const auto eastResult = particle::LocalParticleFieldFeed::load(localMetadata(0),
std::vector<char>(east.begin(), east.end()));
const auto northResult = particle::LocalParticleFieldFeed::load(localMetadata(1),
std::vector<char>(north.begin(), north.end()));
const auto vortexResult = particle::LocalParticleFieldFeed::load(localMetadata(2),
std::vector<char>(vortex.begin(), vortex.end()));
ASSERT_TRUE(eastResult);
ASSERT_TRUE(northResult);
ASSERT_TRUE(vortexResult);
ASSERT_TRUE(eastResult.snapshot);
ASSERT_TRUE(northResult.snapshot);
ASSERT_GE(eastResult.snapshot->velocity.size(), 2u);
ASSERT_GE(northResult.snapshot->velocity.size(), 2u);
EXPECT_FLOAT_EQ(eastResult.snapshot->velocity[0], 1.0f);
EXPECT_FLOAT_EQ(eastResult.snapshot->velocity[1], 0.0f);
EXPECT_FLOAT_EQ(northResult.snapshot->velocity[0], 0.0f);
EXPECT_FLOAT_EQ(northResult.snapshot->velocity[1], 1.0f);
ASSERT_TRUE(vortexResult.snapshot);
EXPECT_FLOAT_EQ(vortexResult.snapshot->velocity[0], 0.9375f);
EXPECT_FLOAT_EQ(vortexResult.snapshot->velocity[1], -0.9375f);
EXPECT_FLOAT_EQ(vortexResult.snapshot->velocity[vortexResult.snapshot->velocity.size() - 2], -0.9375f);
EXPECT_FLOAT_EQ(vortexResult.snapshot->velocity.back(), 0.9375f);
}
TEST(Source, HostFieldSubmissionBuildsOneCoreOwnedTimeline) {
SourceTest test;
style::RasterArraySource source{"host-submission"};
source.setObserver(&test.styleObserver);
source.loadDescription(*test.fileSource);
EXPECT_TRUE(source.loaded);
EXPECT_TRUE(source.impl().hostFieldSubmission);
EXPECT_FALSE(source.impl().field);
const auto east = fixtureBytes("uniform-east", "field.f32");
const auto north = fixtureBytes("uniform-north", "field.f32");
const auto vortex = fixtureBytes("vortex", "field.f32");
const std::vector<char> eastPayload(east.begin(), east.end());
const std::vector<char> northPayload(north.begin(), north.end());
const std::vector<char> vortexPayload(vortex.begin(), vortex.end());
EXPECT_EQ(source.submitHostField(localMetadata(0), eastPayload),
style::RasterArrayHostFieldSubmitResult::AcceptedPendingInitialWindow);
EXPECT_FALSE(source.impl().field);
EXPECT_EQ(source.submitHostField(localMetadata(1), northPayload),
style::RasterArrayHostFieldSubmitResult::InitialWindowReady);
ASSERT_TRUE(source.impl().field);
ASSERT_TRUE(source.impl().nextField);
ASSERT_TRUE(source.impl().timeline);
EXPECT_EQ(source.impl().field->fieldID, "production-t0");
EXPECT_EQ(source.impl().nextField->fieldID, "production-t1");
EXPECT_EQ(source.impl().timeline->frame().state, style::RasterArrayPlaybackState::Ready);
EXPECT_EQ(source.submitHostField(localMetadata(2), vortexPayload),
style::RasterArrayHostFieldSubmitResult::AcceptedNextSnapshot);
EXPECT_EQ(source.submitHostField(localMetadata(3), eastPayload),
style::RasterArrayHostFieldSubmitResult::AcceptedNextSnapshot);
EXPECT_EQ(source.impl().timeline->size(), 4u);
EXPECT_EQ(source.impl().timeline->lastEntry().field->fieldID, "production-t3");
EXPECT_EQ(source.submitHostField(localMetadata(3), eastPayload),
style::RasterArrayHostFieldSubmitResult::Duplicate);
EXPECT_EQ(source.impl().timeline->size(), 4u);
EXPECT_TRUE(source.controlRuntimeTimeline(4));
EXPECT_EQ(source.impl().timeline->frame().t0Index, 1u);
EXPECT_TRUE(source.controlRuntimeTimeline(4));
EXPECT_EQ(source.impl().timeline->frame().t0Index, 2u);
}
TEST(Source, HostFieldSubmissionStyleContractCreatesEmptyIngress) {
SourceTest test;
test.style.loadJSON(R"STYLE({
"version": 8,
"sources": {
"host-submission": {"type": "raster-array", "host-field-submission": true}
},
"layers": []
})STYLE");
auto* baseSource = test.style.getSource("host-submission");
ASSERT_NE(baseSource, nullptr);
auto* source = baseSource->as<style::RasterArraySource>();
ASSERT_NE(source, nullptr);
EXPECT_TRUE(source->impl().hostFieldSubmission);
EXPECT_FALSE(source->impl().field);
EXPECT_FALSE(source->impl().timeline);
}
TEST(Source, HostFieldSubmissionRejectsInvalidWithoutChangingLastValidField) {
SourceTest test;
style::RasterArraySource source{"host-submission"};
source.setObserver(&test.styleObserver);
source.loadDescription(*test.fileSource);
const auto field = fixtureBytes("uniform-east", "field.f32");
const std::vector<char> payload(field.begin(), field.end());
EXPECT_EQ(source.submitHostField(localMetadata(0), payload),
style::RasterArrayHostFieldSubmitResult::AcceptedPendingInitialWindow);
EXPECT_EQ(source.submitHostField(localMetadata(1), payload),
style::RasterArrayHostFieldSubmitResult::InitialWindowReady);
ASSERT_TRUE(source.impl().timeline);
const auto lastValid = source.impl().timeline->lastEntry().field;
auto invalidIdentity = localMetadata(2);
const auto fieldID = invalidIdentity.find("production-t2");
ASSERT_NE(fieldID, std::string::npos);
invalidIdentity.replace(fieldID, std::string("production-t2").size(), "");
EXPECT_EQ(source.submitHostField(invalidIdentity, payload),
style::RasterArrayHostFieldSubmitResult::RejectedAdapter);
auto unsupportedLayout = localMetadata(2);
const auto layout = unsupportedLayout.find("interleaved-uv");
ASSERT_NE(layout, std::string::npos);
unsupportedLayout.replace(layout, std::string("interleaved-uv").size(), "planar-uv");
EXPECT_EQ(source.submitHostField(unsupportedLayout, payload),
style::RasterArrayHostFieldSubmitResult::RejectedAdapter);
auto unsupportedEncoding = localMetadata(2);
const auto encoding = unsupportedEncoding.find("float32-le");
ASSERT_NE(encoding, std::string::npos);
unsupportedEncoding.replace(encoding, std::string("float32-le").size(), "float64-le");
EXPECT_EQ(source.submitHostField(unsupportedEncoding, payload),
style::RasterArrayHostFieldSubmitResult::RejectedAdapter);
auto invalidDimensions = localMetadata(2);
const auto width = invalidDimensions.find("\"width\":16");
ASSERT_NE(width, std::string::npos);
invalidDimensions.replace(width, std::string("\"width\":16").size(), "\"width\":0");
EXPECT_EQ(source.submitHostField(invalidDimensions, payload),
style::RasterArrayHostFieldSubmitResult::RejectedAdapter);
auto shortPayload = payload;
shortPayload.pop_back();
EXPECT_EQ(source.submitHostField(localMetadata(2), shortPayload),
style::RasterArrayHostFieldSubmitResult::RejectedAdapter);
auto nonMonotonic = localMetadata(2);
const auto validTime = nonMonotonic.find("202609040200");
ASSERT_NE(validTime, std::string::npos);
nonMonotonic.replace(validTime, std::string("202609040200").size(), "202609040050");
EXPECT_EQ(source.submitHostField(nonMonotonic, payload),
style::RasterArrayHostFieldSubmitResult::RejectedNonMonotonicSnapshot);
EXPECT_EQ(source.impl().timeline->size(), 2u);
EXPECT_EQ(source.impl().timeline->lastEntry().field, lastValid);
EXPECT_EQ(source.impl().timeline->frame().state, style::RasterArrayPlaybackState::Ready);
style::RasterArraySource fixtureSource{"fixture", "uniform-east", "metadata", "field"};
EXPECT_EQ(fixtureSource.submitHostField(localMetadata(2), payload),
style::RasterArrayHostFieldSubmitResult::RejectedSourceMode);
}
TEST(Source, RasterArrayTimelineCandidatesReachReadyThroughFieldAdapter) {
SourceTest test;
const auto eastMetadata = fixtureBytes("uniform-east", "metadata.json");