From e60af5c1554e5c2703afb97cc432941e1b35c238 Mon Sep 17 00:00:00 2001 From: xylophonez Date: Thu, 14 May 2026 11:05:14 +0100 Subject: [PATCH 1/2] fix(manifest): preserve remote link scope --- src/dev_manifest.erl | 55 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/src/dev_manifest.erl b/src/dev_manifest.erl index bf0125148..f658ccd48 100644 --- a/src/dev_manifest.erl +++ b/src/dev_manifest.erl @@ -185,7 +185,7 @@ manifest(Base, _Req, Opts) -> %% @doc Generate a nested message of links to content from a parsed (and %% structured) manifest. linkify(#{ <<"id">> := ID }, Opts) when is_binary(ID) -> - LinkOptsBase = (maps:with([store], Opts))#{ scope => [local, remote]}, + LinkOptsBase = (maps:with([<<"store">>], Opts))#{ <<"scope">> => [local, remote]}, {link, ID, LinkOptsBase#{ <<"type">> => <<"link">>, <<"lazy">> => false }}; linkify(Manifest, Opts) when is_map(Manifest) -> hb_maps:map( @@ -203,6 +203,59 @@ linkify(Manifest, _Opts) -> %%% Tests +linkified_paths_keep_store_and_remote_scope_test() -> + Store = hb_test_utils:test_store(), + ID = hb_util:human_id(crypto:strong_rand_bytes(32)), + {link, ID, LinkOpts} = linkify(#{ <<"id">> => ID }, #{ <<"store">> => Store }), + ?assertEqual(Store, maps:get(<<"store">>, LinkOpts)), + ?assertEqual([local, remote], hb_opts:get(scope, undefined, LinkOpts)), + ?assertNot(maps:is_key(store, LinkOpts)), + ?assertNot(maps:is_key(scope, LinkOpts)). + +manifest_child_link_remote_fallback_test_parallel() -> + LocalStore = hb_test_utils:test_store(hb_store_fs, <<"manifest-local">>), + RemoteStore = + (hb_test_utils:test_store(hb_store_fs, <<"manifest-remote">>))#{ + <<"scope">> => remote + }, + Opts = #{ + <<"store">> => [LocalStore, RemoteStore], + <<"on">> => #{ + <<"request">> => #{ + <<"device">> => <<"manifest@1.0">> + } + } + }, + ok = hb_store:start([LocalStore, RemoteStore]), + Child = <<"Remote child">>, + {ok, ChildID} = hb_cache:write(Child, #{ <<"store">> => RemoteStore }), + Manifest = #{ + <<"paths">> => #{ + <<"page1">> => #{ <<"id">> => ChildID } + }, + <<"index">> => #{ <<"path">> => <<"page1">> } + }, + ManifestMsg = #{ + <<"device">> => <<"manifest@1.0">>, + <<"body">> => hb_json:encode(Manifest) + }, + {ok, ManifestID} = hb_cache:write(ManifestMsg, #{ <<"store">> => LocalStore }), + ?assertEqual({ok, Child}, hb_cache:read(ChildID, #{ <<"store">> => RemoteStore })), + ?assertEqual({ok, Child}, hb_cache:read(ChildID, Opts)), + ?assertMatch( + <<"Remote child">>, + hb_cache:ensure_loaded( + {link, ChildID, #{ + <<"scope">> => [local, remote], + <<"type">> => <<"link">>, + <<"lazy">> => false + }}, + Opts + ) + ), + Node = hb_http_server:start_node(Opts), + ?assertEqual({ok, <<"Remote child">>}, hb_http:get(Node, << ManifestID/binary, "/page1" >>, Opts)). + resolve_test_parallel() -> Opts = #{ <<"store">> => hb_opts:get(store, no_viable_store, #{}), From 6336f82a202c64e617c107b8956da389d0d0db45 Mon Sep 17 00:00:00 2001 From: xylophonez Date: Thu, 14 May 2026 21:23:05 +0100 Subject: [PATCH 2/2] test(manifest): remove broad link option assertions Keep the manifest regression test scoped to preserving the configured binary store and remote scope. Drop the atom-key absence assertions and redundant manifest fallback test called out in review. --- src/dev_manifest.erl | 48 +------------------------------------------- 1 file changed, 1 insertion(+), 47 deletions(-) diff --git a/src/dev_manifest.erl b/src/dev_manifest.erl index f658ccd48..c1743d16c 100644 --- a/src/dev_manifest.erl +++ b/src/dev_manifest.erl @@ -208,53 +208,7 @@ linkified_paths_keep_store_and_remote_scope_test() -> ID = hb_util:human_id(crypto:strong_rand_bytes(32)), {link, ID, LinkOpts} = linkify(#{ <<"id">> => ID }, #{ <<"store">> => Store }), ?assertEqual(Store, maps:get(<<"store">>, LinkOpts)), - ?assertEqual([local, remote], hb_opts:get(scope, undefined, LinkOpts)), - ?assertNot(maps:is_key(store, LinkOpts)), - ?assertNot(maps:is_key(scope, LinkOpts)). - -manifest_child_link_remote_fallback_test_parallel() -> - LocalStore = hb_test_utils:test_store(hb_store_fs, <<"manifest-local">>), - RemoteStore = - (hb_test_utils:test_store(hb_store_fs, <<"manifest-remote">>))#{ - <<"scope">> => remote - }, - Opts = #{ - <<"store">> => [LocalStore, RemoteStore], - <<"on">> => #{ - <<"request">> => #{ - <<"device">> => <<"manifest@1.0">> - } - } - }, - ok = hb_store:start([LocalStore, RemoteStore]), - Child = <<"Remote child">>, - {ok, ChildID} = hb_cache:write(Child, #{ <<"store">> => RemoteStore }), - Manifest = #{ - <<"paths">> => #{ - <<"page1">> => #{ <<"id">> => ChildID } - }, - <<"index">> => #{ <<"path">> => <<"page1">> } - }, - ManifestMsg = #{ - <<"device">> => <<"manifest@1.0">>, - <<"body">> => hb_json:encode(Manifest) - }, - {ok, ManifestID} = hb_cache:write(ManifestMsg, #{ <<"store">> => LocalStore }), - ?assertEqual({ok, Child}, hb_cache:read(ChildID, #{ <<"store">> => RemoteStore })), - ?assertEqual({ok, Child}, hb_cache:read(ChildID, Opts)), - ?assertMatch( - <<"Remote child">>, - hb_cache:ensure_loaded( - {link, ChildID, #{ - <<"scope">> => [local, remote], - <<"type">> => <<"link">>, - <<"lazy">> => false - }}, - Opts - ) - ), - Node = hb_http_server:start_node(Opts), - ?assertEqual({ok, <<"Remote child">>}, hb_http:get(Node, << ManifestID/binary, "/page1" >>, Opts)). + ?assertEqual([local, remote], hb_opts:get(scope, undefined, LinkOpts)). resolve_test_parallel() -> Opts = #{