Skip to content
File

Blob: src/workerd/api/actor-state-iocontext-test.c++

3.0 KB
1// Copyright (c) 2017-2023 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4 
5#include <workerd/api/actor-state.h>
6#include <workerd/io/actor-id.h>
7#include <workerd/tests/test-fixture.h>
8 
9#include <kj/encoding.h>
10#include <kj/test.h>
11 
12#include <algorithm>
13 
14namespace workerd::api {
15namespace {
16 
17using workerd::TestFixture;
18 
19bool contains(kj::StringPtr haystack, kj::StringPtr needle) {
20 return std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end()) !=
21 haystack.end();
22}
23 
24class MockActorId: public ActorIdFactory::ActorId {
25 public:
26 MockActorId(kj::String id): id(kj::mv(id)) {}
27 kj::String toString() const override {
28 return kj::str("MockActorId<", id, ">");
29 }
30 
31 kj::Maybe<kj::StringPtr> getName() const override {
32 return kj::none;
33 }
34 
35 kj::Maybe<kj::StringPtr> getJurisdiction() const override {
36 return kj::none;
37 }
38 
39 bool equals(const ActorId& other) const override {
40 return false;
41 }
42 
43 kj::Own<ActorId> clone() const override {
44 return kj::heap<MockActorId>(kj::heapString(id));
45 }
46 
47 virtual ~MockActorId() {};
48 
49 private:
50 kj::String id;
51};
52 
53void runBadDeserialization(jsg::Lock& lock, kj::StringPtr expectedId) {
54 // FF = kVersion token, 0E = version 15, 06 = an unknown tag value
55 kj::StringPtr invalidV8Hex = "FF0E06"_kj;
56 auto invalidV8Value = kj::decodeHex(invalidV8Hex.asArray());
57 try {
58 deserializeV8Value(lock, "some-key"_kj, invalidV8Value);
59 KJ_FAIL_ASSERT("deserializeV8Value should have failed.");
60 } catch (kj::Exception& ex) {
61 if (ex.getDescription().startsWith("actor storage deserialization failed")) {
62 KJ_ASSERT(contains(ex.getDescription(), expectedId));
63 } else {
64 throw;
65 }
66 }
67}
68 
69void runBadDeserializationInIoContext(TestFixture& fixture, kj::StringPtr expectedId) {
70 fixture.runInIoContext(
71 [expectedId](const workerd::TestFixture::Environment& env) -> kj::Promise<void> {
72 runBadDeserialization(env.lock, expectedId);
73 return kj::READY_NOW;
74 });
75}
76 
77// TODO(maybe) It would be nice to have a test that tests the case when there's no IoContext,
78// but that's a royal pain to set up in this test file we'd basically only test that we don't
79// crash, which the actor-state-test.c++ does for us.
80 
81KJ_TEST("no actor specified") {
82 TestFixture fixture;
83 runBadDeserializationInIoContext(fixture, "actorId = ;"_kj);
84}
85 
86KJ_TEST("actor specified with string id") {
87 Worker::Actor::Id id = kj::str("testActorId");
88 TestFixture fixture(TestFixture::SetupParams{.actorId = kj::mv(id)});
89 runBadDeserializationInIoContext(fixture, "actorId = testActorId;"_kj);
90}
91 
92KJ_TEST("actor specified with ActorId object") {
93 kj::Own<ActorIdFactory::ActorId> mockActorId = kj::heap<MockActorId>(kj::str("testActorId"));
94 Worker::Actor::Id id = kj::mv(mockActorId);
95 TestFixture fixture(TestFixture::SetupParams{
96 .actorId = kj::mv(id),
97 });
98 runBadDeserializationInIoContext(fixture, "actorId = MockActorId<testActorId>;"_kj);
99}
100 
101} // namespace
102} // namespace workerd::api