Skip to content

Commit

Permalink
test: add more tests and refactor body of request to a function
Browse files Browse the repository at this point in the history
  • Loading branch information
teresalves committed Feb 28, 2025
1 parent 44f5025 commit ff830c5
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 48 deletions.
47 changes: 32 additions & 15 deletions src/workerd/api/kv-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default {
result = ""
} else if (pathname == "/get-json") {
result = JSON.stringify({ example: "values" });
} else if (pathname == "/get-bulk") {
} else if (pathname == "/bulk/get") {
var body = request.body;
const reader = body.getReader();
const decoder = new TextDecoder(); // UTF-8 by default
Expand All @@ -36,13 +36,17 @@ export default {
}
const parsedBody = JSON.parse(r);
const keys = parsedBody.keys;
console.log(keys);
if (keys.length < 1) {
return new Response("Array needs at least one key", {status: 400})
}
result = {}
if(parsedBody.type == "json") {
for(const key of keys) {
if(key == "key-not-json") {
return new Response(null, {status: 500})
}
const val = { example: "values"};
const val = { example: `values-${key}`};
if (parsedBody.withMetadata) {
result[key] = {value: val, metadata: "example-metadata"};
} else {
Expand All @@ -51,8 +55,10 @@ export default {
}
} else if (!parsedBody.type || parsedBody.type == "text") {
for(const key of keys) {
const val = JSON.stringify({ example: "values" });;
if (parsedBody.withMetadata) {
const val = JSON.stringify({ example: `values-${key}` });;
if(key == "not-found") {
result[key] = null;
} else if (parsedBody.withMetadata) {
result[key] = {value: val, metadata: "example-metadata"};
} else {
result[key] = val;
Expand All @@ -68,7 +74,6 @@ export default {
}
let response = new Response(result, {status: 200});
response.headers.set("CF-KV-Metadata", '{"someMetadataKey":"someMetadataValue","someUnicodeMeta":"🤓"}');

return response;
},

Expand Down Expand Up @@ -110,14 +115,29 @@ export default {


// Testing .get bulk
var response = await env.KV.get(["key1", "key2"]);
var expected = { key1: '{\"example\":\"values-key1\"}', key2: '{\"example\":\"values-key2\"}' };
assert.deepEqual(response, expected);

var response = await env.KV.get(["key1", "key2"],{});
var expected = { key1: '{\"example\":\"values\"}', key2: '{\"example\":\"values\"}' };
var expected = { key1: '{\"example\":\"values-key1\"}', key2: '{\"example\":\"values-key2\"}' };
assert.deepEqual(response, expected);

var response = await env.KV.get(["key1", "not-found"],{});
var expected = { key1: '{\"example\":\"values-key1\"}', "not-found": null };
assert.deepEqual(response, expected);

try {
var response = await env.KV.get([]);
assert.ok(false);
} catch ({ name, message }){
assert(message.includes("400"));
assert.ok(true);
}

// get bulk text but it is json format
var response = await env.KV.get(["key1", "key2"], "json");
var expected = { key1: { example: 'values' }, key2: { example: 'values' } };
var expected = { key1: { example: 'values-key1' }, key2: { example: 'values-key2' } };
assert.deepEqual(response, expected);

// get bulk json but it is not json - throws error
Expand All @@ -133,14 +153,14 @@ export default {
var response = await env.KV.get(["key-not-json", "key2"], "arrayBuffer");
assert.ok(false); // not reached
} catch ({ name, message }){
// assert(message.includes("invalid")) // this message is not processed, should it?
assert(message.includes("500"));
assert.ok(true);
}
try{
var response = await env.KV.get(["key-not-json", "key2"], {type: "banana"});
assert.ok(false); // not reached
} catch ({ name, message }){
// assert(message.includes("invalid")) // this message is not processed, should it?
assert(message.includes("500"));
assert.ok(true);
}

Expand All @@ -153,18 +173,15 @@ export default {
};
assert.deepEqual(response, expected);


var response = await env.KV.getWithMetadata(['key1'],{});
var expected = { key1: { metadata: 'example-metadata', value: '{"example":"values"}' } };
var expected = { key1: { metadata: 'example-metadata', value: '{"example":"values-key1"}' } };
assert.deepEqual(response, expected);


var response = await env.KV.getWithMetadata(['key1'], "json");
var expected = { key1: { metadata: 'example-metadata', value: { example: 'values' } } };
var expected = { key1: { metadata: 'example-metadata', value: { example: 'values-key1' } } };
assert.deepEqual(response, expected);

var response = await env.KV.getWithMetadata(['key1', 'key2'], "json");
var expected = { key1: { metadata: 'example-metadata', value: { example: 'values' } }, key2: { metadata: 'example-metadata', value: { example: 'values' } } };
var expected = { key1: { metadata: 'example-metadata', value: { example: 'values-key1' } }, key2: { metadata: 'example-metadata', value: { example: 'values-key2' } } };
assert.deepEqual(response, expected);
},
};
71 changes: 38 additions & 33 deletions src/workerd/api/kv.c++
Original file line number Diff line number Diff line change
Expand Up @@ -178,40 +178,10 @@ jsg::Promise<jsg::JsRef<jsg::JsValue>> KvNamespace::getBulk(jsg::Lock& js,
kj::Url url;
url.scheme = kj::str("https");
url.host = kj::str("fake-host");
url.path.add(kj::str("get-bulk"));
url.path.add(kj::str("bulk"));
url.path.add(kj::str("get"));

kj::String type = kj::str("");
KJ_IF_SOME(oneOfOptions, options) {
KJ_SWITCH_ONEOF(oneOfOptions) {
KJ_CASE_ONEOF(t, kj::String) {
type = kj::str(t);
}
KJ_CASE_ONEOF(options, GetOptions) {
KJ_IF_SOME(t, options.type) {
type = kj::str(t);
}
}
}
}

kj::Vector<kj::String> stringVector;
for (auto& str : name) {
stringVector.add(kj::str("\"", str, "\"")); // Wrap each string in quotes for JSON
}

// Join array elements into a JSON array format
kj::String jsonArray = kj::str("[", kj::strArray(stringVector, ", "), "]");
kj::String s = kj::str("{'key': 'value'}");
kj::String keys = kj::str("\"keys\": ", jsonArray);
kj::String typeStr = kj::str("");
kj::String metadataStr = kj::str("");
if(type != kj::str("")) {
typeStr = kj::str(",\"type\": \"", type, "\"");
}
if(withMetadata) {
metadataStr = kj::str(",\"withMetadata\": \"true\"");
}
kj::String body = kj::str("{", keys, typeStr, metadataStr, "}");
kj::String body = formBulkBodyString(name, withMetadata, options);

kj::Maybe<uint64_t> expectedBodySize = uint64_t(body.size());
auto headers = kj::HttpHeaders(context.getHeaderTable());
Expand Down Expand Up @@ -250,6 +220,41 @@ jsg::Promise<jsg::JsRef<jsg::JsValue>> KvNamespace::getBulk(jsg::Lock& js,
});
}

kj::String KvNamespace::formBulkBodyString(kj::Array<kj::String>& names, bool withMetadata, jsg::Optional<kj::OneOf<kj::String, GetOptions>>& options) {
kj::Vector<kj::String> stringVector;

kj::String type = kj::str("");
KJ_IF_SOME(oneOfOptions, options) {
KJ_SWITCH_ONEOF(oneOfOptions) {
KJ_CASE_ONEOF(t, kj::String) {
type = kj::str(t);
}
KJ_CASE_ONEOF(options, GetOptions) {
KJ_IF_SOME(t, options.type) {
type = kj::str(t);
}
}
}
}
for (auto& str : names) {
stringVector.add(kj::str("\"", str, "\"")); // Wrap each string in quotes for JSON
}

// Join array elements into a JSON array format
kj::String jsonArray = kj::str("[", kj::strArray(stringVector, ", "), "]");
kj::String s = kj::str("{'key': 'value'}");
kj::String keys = kj::str("\"keys\": ", jsonArray);
kj::String typeStr = kj::str("");
kj::String metadataStr = kj::str("");
if(type != kj::str("")) {
typeStr = kj::str(",\"type\": \"", type, "\"");
}
if(withMetadata) {
metadataStr = kj::str(",\"withMetadata\": \"true\"");
}
return kj::str("{", keys, typeStr, metadataStr, "}");
}

kj::OneOf<jsg::Promise<KvNamespace::GetResult>,jsg::Promise<jsg::JsRef<jsg::JsValue>> > KvNamespace::get(
jsg::Lock& js, kj::OneOf<kj::String, kj::Array<kj::String>> name, jsg::Optional<kj::OneOf<kj::String, GetOptions>> options) {

Expand Down
2 changes: 2 additions & 0 deletions src/workerd/api/kv.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class KvNamespace: public jsg::Object {
jsg::Optional<kj::OneOf<kj::String, GetOptions>> options,
bool withMetadata);

kj::String formBulkBodyString(kj::Array<kj::String>& names, bool withMetadata, jsg::Optional<kj::OneOf<kj::String, GetOptions>>& options);

kj::OneOf<jsg::Promise<KvNamespace::GetResult>,jsg::Promise<jsg::JsRef<jsg::JsValue>>> get(
jsg::Lock& js, kj::OneOf<kj::String, kj::Array<kj::String>> name, jsg::Optional<kj::OneOf<kj::String, GetOptions>> options);

Expand Down

0 comments on commit ff830c5

Please sign in to comment.