diff --git a/README.md b/README.md index 06577b2..c0a9ae0 100644 --- a/README.md +++ b/README.md @@ -137,10 +137,10 @@ real Qt plugin to work with. All operations go through the public `logos_core` C API. Tests cover: -- **Process** — `logos_core_process_plugin` concurrently on disjoint and shared module sets -- **Query under writes** — `logos_core_get_known_plugins` / `logos_core_get_loaded_plugins` called by reader threads while writers are processing or loading -- **Load** — `logos_core_load_plugin` and `logos_core_load_plugin_with_dependencies` on disjoint and shared sets, including unknown-name fast-failure paths -- **Unload** — `logos_core_unload_plugin` interleaved with concurrent load threads on a shared small module set +- **Process** — `logos_core_process_module` concurrently on disjoint and shared module sets +- **Query under writes** — `logos_core_get_known_modules` / `logos_core_get_loaded_modules` called by reader threads while writers are processing or loading +- **Load** — `logos_core_load_module` and `logos_core_load_module_with_dependencies` on disjoint and shared sets, including unknown-name fast-failure paths +- **Unload** — `logos_core_unload_module` interleaved with concurrent load threads on a shared small module set ```bash # Standalone diff --git a/flake.lock b/flake.lock index 73cda61..a28adbc 100644 --- a/flake.lock +++ b/flake.lock @@ -175,11 +175,11 @@ ] }, "locked": { - "lastModified": 1774958555, - "narHash": "sha256-9FMXR+YesH0JnR3DBv3BG1jtdTDWkPwMx+kIhuBpxZ4=", + "lastModified": 1775745471, + "narHash": "sha256-Flz0Ipok57ivbqg7Fw4qRcfCL3ainrRTXMIlNDh3ajY=", "owner": "logos-co", "repo": "logos-cpp-sdk", - "rev": "38006e72400ee96a9d75e8feb102b474f80d3da5", + "rev": "8b1cfadf090f0df9d75e61ac7475d83f9c58b0a9", "type": "github" }, "original": { @@ -199,11 +199,11 @@ ] }, "locked": { - "lastModified": 1774958555, - "narHash": "sha256-9FMXR+YesH0JnR3DBv3BG1jtdTDWkPwMx+kIhuBpxZ4=", + "lastModified": 1776359718, + "narHash": "sha256-G2+MbYPictF9V9864KndteaEJzd8iUMktSzCphETabw=", "owner": "logos-co", "repo": "logos-cpp-sdk", - "rev": "38006e72400ee96a9d75e8feb102b474f80d3da5", + "rev": "04b75c84b821662c9ae8f69967d4dd508e6d9e17", "type": "github" }, "original": { @@ -275,11 +275,11 @@ ] }, "locked": { - "lastModified": 1774958555, - "narHash": "sha256-9FMXR+YesH0JnR3DBv3BG1jtdTDWkPwMx+kIhuBpxZ4=", + "lastModified": 1776359718, + "narHash": "sha256-G2+MbYPictF9V9864KndteaEJzd8iUMktSzCphETabw=", "owner": "logos-co", "repo": "logos-cpp-sdk", - "rev": "38006e72400ee96a9d75e8feb102b474f80d3da5", + "rev": "04b75c84b821662c9ae8f69967d4dd508e6d9e17", "type": "github" }, "original": { @@ -324,11 +324,11 @@ ] }, "locked": { - "lastModified": 1774988975, - "narHash": "sha256-wJ7Bv3TL754bZcTL2qilI0JahiVag7fLDzw8Y6Qz0pk=", + "lastModified": 1776778717, + "narHash": "sha256-HTtNO9I++CSwd64T0jpsPn+mixeZnebFxHKE4840mPY=", "owner": "logos-co", "repo": "logos-cpp-sdk", - "rev": "d633575677a3d19a8bf1d5ff687398dace532938", + "rev": "f7c855b110e493c293e81f473757cf17ee772514", "type": "github" }, "original": { @@ -349,11 +349,11 @@ ] }, "locked": { - "lastModified": 1774988975, - "narHash": "sha256-wJ7Bv3TL754bZcTL2qilI0JahiVag7fLDzw8Y6Qz0pk=", + "lastModified": 1776101366, + "narHash": "sha256-HxkzOs2xv0grkNAJMBLXKDjVl8Z+z3YFn+sC4eFKy/8=", "owner": "logos-co", "repo": "logos-cpp-sdk", - "rev": "d633575677a3d19a8bf1d5ff687398dace532938", + "rev": "1468180b2567f4c59346bb94f74951e76341f5c5", "type": "github" }, "original": { @@ -429,11 +429,11 @@ "process-stats": "process-stats" }, "locked": { - "lastModified": 1775476667, - "narHash": "sha256-/CxLQZF1NDplSRRH5+NKJ9n9hhVZBKNIqry2xrQqtEo=", + "lastModified": 1776950445, + "narHash": "sha256-UQBZehyqd4GcqBLp4Uiu8r6bl/SJbpfmO/S5Z9luBeQ=", "owner": "logos-co", "repo": "logos-liblogos", - "rev": "87fbb87c9cce62bc44115c8ba1c8b0ab8bf864d0", + "rev": "b82145ce9a8907624b8593ac85897d54f33b3bc4", "type": "github" }, "original": { @@ -458,11 +458,11 @@ "process-stats": "process-stats_2" }, "locked": { - "lastModified": 1774967221, - "narHash": "sha256-i/8S4ldt0ikyjWrwp428Y7a7MRCIsS4R7pED0MFM52o=", + "lastModified": 1776868521, + "narHash": "sha256-aJP2FUCegZSUrr3mWECCa6o+FwSN+A2IKuoJGOjgTsM=", "owner": "logos-co", "repo": "logos-liblogos", - "rev": "da6ba7210e5145bfa5cb40590a2ac7e5dbbfd30d", + "rev": "d2d6ec769501afbbd4708d8a3889c460e060684a", "type": "github" }, "original": { @@ -487,11 +487,11 @@ "process-stats": "process-stats_3" }, "locked": { - "lastModified": 1774967221, - "narHash": "sha256-i/8S4ldt0ikyjWrwp428Y7a7MRCIsS4R7pED0MFM52o=", + "lastModified": 1776084938, + "narHash": "sha256-0UL6tG6mK00HN99fm9CLJu3JA9ay2ry6dgeHfyApiWo=", "owner": "logos-co", "repo": "logos-liblogos", - "rev": "da6ba7210e5145bfa5cb40590a2ac7e5dbbfd30d", + "rev": "b293e9d70a04983778ef2ef3ef42596f76f41161", "type": "github" }, "original": { @@ -516,11 +516,11 @@ ] }, "locked": { - "lastModified": 1774990915, - "narHash": "sha256-g/N+XDuHMQ4uB6LLUKD7sVxhm3gd3aSUfnYPwEEE+E0=", + "lastModified": 1776884837, + "narHash": "sha256-w0u9875fBRSAYFXrUe2V/S8V3jE5URq4g/nSSL+kX8I=", "owner": "logos-co", "repo": "logos-logoscore-cli", - "rev": "ce3884cce83f0706916c1af2a44f0775386c0ec4", + "rev": "c24e58eb8ddf817f5998ca4ead7a994e2a732cc8", "type": "github" }, "original": { @@ -572,11 +572,11 @@ ] }, "locked": { - "lastModified": 1775222875, - "narHash": "sha256-YfzJ/+JEkMbxdSz34ZNryefDcxUo23EjTwfQFpWX698=", + "lastModified": 1777039050, + "narHash": "sha256-4AQeTUl+fO8F+F9aND3aS1Px4lommokii7DeA2X4T0w=", "owner": "logos-co", "repo": "logos-module-builder", - "rev": "b7b0664653a48a3a4e7af355bb7ed343b89038b8", + "rev": "29cecd23a2a6bd63d113340cc9773829681598a4", "type": "github" }, "original": { @@ -650,11 +650,11 @@ ] }, "locked": { - "lastModified": 1774633164, - "narHash": "sha256-TobXeKMS1RWYKo30ujYJNnrDVhu4U1JFdtL31yIOu8c=", + "lastModified": 1775763932, + "narHash": "sha256-PrVdkHNN2PPXoUEJoJUKv61t6IeQ3iQSRarIpFr9GHE=", "owner": "logos-co", "repo": "logos-module", - "rev": "8ed727449a4a6713a8c819c213b0d5d25f575580", + "rev": "73cd9c4b2646dedb1b624a3178b32a7af1670047", "type": "github" }, "original": { @@ -674,11 +674,11 @@ ] }, "locked": { - "lastModified": 1774633164, - "narHash": "sha256-TobXeKMS1RWYKo30ujYJNnrDVhu4U1JFdtL31yIOu8c=", + "lastModified": 1776369033, + "narHash": "sha256-ehePoUEd/u3Ng0TvCmjocXYJWWH6P61PA7tNpgV59lo=", "owner": "logos-co", "repo": "logos-module", - "rev": "8ed727449a4a6713a8c819c213b0d5d25f575580", + "rev": "194778491ef4dd36967ac40cc2fec6b8a8b1d660", "type": "github" }, "original": { @@ -750,11 +750,11 @@ ] }, "locked": { - "lastModified": 1774633164, - "narHash": "sha256-TobXeKMS1RWYKo30ujYJNnrDVhu4U1JFdtL31yIOu8c=", + "lastModified": 1776369033, + "narHash": "sha256-ehePoUEd/u3Ng0TvCmjocXYJWWH6P61PA7tNpgV59lo=", "owner": "logos-co", "repo": "logos-module", - "rev": "8ed727449a4a6713a8c819c213b0d5d25f575580", + "rev": "194778491ef4dd36967ac40cc2fec6b8a8b1d660", "type": "github" }, "original": { @@ -774,11 +774,11 @@ ] }, "locked": { - "lastModified": 1774988698, - "narHash": "sha256-Ugngv17u5CA3lOSNHN6nJ+/WpIyNn8yui0M2VDdkENk=", + "lastModified": 1775763932, + "narHash": "sha256-PrVdkHNN2PPXoUEJoJUKv61t6IeQ3iQSRarIpFr9GHE=", "owner": "logos-co", "repo": "logos-module", - "rev": "337223f2a72710d8052ca750510cd25d33e05047", + "rev": "73cd9c4b2646dedb1b624a3178b32a7af1670047", "type": "github" }, "original": { @@ -1120,11 +1120,11 @@ "nixpkgs": "nixpkgs_22" }, "locked": { - "lastModified": 1773955630, - "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", + "lastModified": 1774455309, + "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", "owner": "logos-co", "repo": "logos-nix", - "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", + "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", "type": "github" }, "original": { @@ -1300,11 +1300,11 @@ "nixpkgs": "nixpkgs_31" }, "locked": { - "lastModified": 1773955630, - "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", + "lastModified": 1774455309, + "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", "owner": "logos-co", "repo": "logos-nix", - "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", + "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", "type": "github" }, "original": { @@ -1372,11 +1372,11 @@ "nixpkgs": "nixpkgs_35" }, "locked": { - "lastModified": 1773955630, - "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", + "lastModified": 1774455309, + "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", "owner": "logos-co", "repo": "logos-nix", - "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", + "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", "type": "github" }, "original": { @@ -1480,11 +1480,11 @@ "nixpkgs": "nixpkgs_40" }, "locked": { - "lastModified": 1773955630, - "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", + "lastModified": 1774455309, + "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", "owner": "logos-co", "repo": "logos-nix", - "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", + "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", "type": "github" }, "original": { @@ -1876,11 +1876,11 @@ "nixpkgs": "nixpkgs_60" }, "locked": { - "lastModified": 1773955630, - "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", + "lastModified": 1774455309, + "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", "owner": "logos-co", "repo": "logos-nix", - "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", + "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", "type": "github" }, "original": { @@ -2020,11 +2020,11 @@ "nixpkgs": "nixpkgs_68" }, "locked": { - "lastModified": 1773955630, - "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", + "lastModified": 1774455309, + "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", "owner": "logos-co", "repo": "logos-nix", - "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", + "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", "type": "github" }, "original": { @@ -2038,11 +2038,11 @@ "nixpkgs": "nixpkgs_69" }, "locked": { - "lastModified": 1773955630, - "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", + "lastModified": 1774455309, + "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", "owner": "logos-co", "repo": "logos-nix", - "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", + "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", "type": "github" }, "original": { @@ -2056,11 +2056,11 @@ "nixpkgs": "nixpkgs_7" }, "locked": { - "lastModified": 1773955630, - "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", + "lastModified": 1774455309, + "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", "owner": "logos-co", "repo": "logos-nix", - "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", + "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", "type": "github" }, "original": { @@ -2074,11 +2074,11 @@ "nixpkgs": "nixpkgs_70" }, "locked": { - "lastModified": 1774455309, - "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", + "lastModified": 1773955630, + "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", "owner": "logos-co", "repo": "logos-nix", - "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", + "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", "type": "github" }, "original": { @@ -2110,11 +2110,11 @@ "nixpkgs": "nixpkgs_72" }, "locked": { - "lastModified": 1773955630, - "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", + "lastModified": 1774455309, + "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", "owner": "logos-co", "repo": "logos-nix", - "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", + "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", "type": "github" }, "original": { @@ -2128,11 +2128,11 @@ "nixpkgs": "nixpkgs_73" }, "locked": { - "lastModified": 1773955630, - "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", + "lastModified": 1774455309, + "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", "owner": "logos-co", "repo": "logos-nix", - "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", + "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", "type": "github" }, "original": { @@ -2146,11 +2146,11 @@ "nixpkgs": "nixpkgs_74" }, "locked": { - "lastModified": 1774455309, - "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", + "lastModified": 1773955630, + "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", "owner": "logos-co", "repo": "logos-nix", - "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", + "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", "type": "github" }, "original": { @@ -2182,11 +2182,11 @@ "nixpkgs": "nixpkgs_76" }, "locked": { - "lastModified": 1773955630, - "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", + "lastModified": 1774455309, + "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", "owner": "logos-co", "repo": "logos-nix", - "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", + "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", "type": "github" }, "original": { @@ -2200,11 +2200,11 @@ "nixpkgs": "nixpkgs_77" }, "locked": { - "lastModified": 1773955630, - "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", + "lastModified": 1774455309, + "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", "owner": "logos-co", "repo": "logos-nix", - "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", + "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", "type": "github" }, "original": { @@ -2307,6 +2307,24 @@ "inputs": { "nixpkgs": "nixpkgs_82" }, + "locked": { + "lastModified": 1774455309, + "narHash": "sha256-3AN7aFnArdysrbQQ2UskWzjNSFADb4hDCsnx69Fa0ng=", + "owner": "logos-co", + "repo": "logos-nix", + "rev": "e637a1f5e871244d1c2df1e3c52a067f2eb406f2", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-nix", + "type": "github" + } + }, + "logos-nix_83": { + "inputs": { + "nixpkgs": "nixpkgs_83" + }, "locked": { "lastModified": 1773955630, "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", @@ -2321,9 +2339,27 @@ "type": "github" } }, - "logos-nix_83": { + "logos-nix_84": { "inputs": { - "nixpkgs": "nixpkgs_83" + "nixpkgs": "nixpkgs_84" + }, + "locked": { + "lastModified": 1773955630, + "narHash": "sha256-KqzMoWYIVp2xMgphs7v02T/BE54RKMFxpdC2duhJKG0=", + "owner": "logos-co", + "repo": "logos-nix", + "rev": "0e9e6d66ab8eb34f59e45ed448f7dc29130feb88", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-nix", + "type": "github" + } + }, + "logos-nix_85": { + "inputs": { + "nixpkgs": "nixpkgs_85" }, "locked": { "lastModified": 1774455309, @@ -2369,11 +2405,11 @@ ] }, "locked": { - "lastModified": 1773965173, - "narHash": "sha256-toDnGXUthRcQm7vcEYzb2bLI7FE1tbfzH8Ie2Cnb9mk=", + "lastModified": 1775835037, + "narHash": "sha256-Cti0DhkzyLQs98BSzcHWMLtGXpa3n+R+5upfSw6vKdQ=", "owner": "logos-co", "repo": "logos-package", - "rev": "9e3730d5c0e3ec955761c05b50e3a6047ee4030b", + "rev": "ff93a0df15ceab255f27687d22d962ea2737efbe", "type": "github" }, "original": { @@ -2396,11 +2432,11 @@ ] }, "locked": { - "lastModified": 1774635434, - "narHash": "sha256-9LRXf/Wy500rNO9IhDSH+PSuadS3TguNFCbcbI4YYZU=", + "lastModified": 1776374462, + "narHash": "sha256-HMkuqSLdScAWTwXEWjhqx9Yk82GiPzPIfRaHTvjG730=", "owner": "logos-co", "repo": "logos-package-manager", - "rev": "e5c25989861f4487c3dc8c7b3bc0062bcbc3221f", + "rev": "9101875bc103214855bc6217834e22e66802ed86", "type": "github" }, "original": { @@ -2424,11 +2460,11 @@ ] }, "locked": { - "lastModified": 1774635434, - "narHash": "sha256-9LRXf/Wy500rNO9IhDSH+PSuadS3TguNFCbcbI4YYZU=", + "lastModified": 1776374462, + "narHash": "sha256-HMkuqSLdScAWTwXEWjhqx9Yk82GiPzPIfRaHTvjG730=", "owner": "logos-co", "repo": "logos-package-manager", - "rev": "e5c25989861f4487c3dc8c7b3bc0062bcbc3221f", + "rev": "9101875bc103214855bc6217834e22e66802ed86", "type": "github" }, "original": { @@ -2452,11 +2488,11 @@ ] }, "locked": { - "lastModified": 1774635434, - "narHash": "sha256-9LRXf/Wy500rNO9IhDSH+PSuadS3TguNFCbcbI4YYZU=", + "lastModified": 1775836847, + "narHash": "sha256-pU7GShEizE8HkDGvR9NWZPqksiGyvfcWodtFyc318TM=", "owner": "logos-co", "repo": "logos-package-manager", - "rev": "e5c25989861f4487c3dc8c7b3bc0062bcbc3221f", + "rev": "39118d6c52226e88a77c6ff7d1196229f56b757e", "type": "github" }, "original": { @@ -2481,11 +2517,11 @@ ] }, "locked": { - "lastModified": 1774635434, - "narHash": "sha256-9LRXf/Wy500rNO9IhDSH+PSuadS3TguNFCbcbI4YYZU=", + "lastModified": 1775680583, + "narHash": "sha256-0Bh48zTfi4lPL78ZLgmiX+QMW+nvjWKXHp5iJPEhvLg=", "owner": "logos-co", "repo": "logos-package-manager", - "rev": "e5c25989861f4487c3dc8c7b3bc0062bcbc3221f", + "rev": "8110734252edf9ca4266f475ace1c7c9bee68018", "type": "github" }, "original": { @@ -2496,7 +2532,7 @@ }, "logos-package-manager_5": { "inputs": { - "logos-nix": "logos-nix_75", + "logos-nix": "logos-nix_77", "logos-package": "logos-package_8", "nix-bundle-appimage": "nix-bundle-appimage_6", "nix-bundle-dir": "nix-bundle-dir_15", @@ -2509,11 +2545,11 @@ ] }, "locked": { - "lastModified": 1774635434, - "narHash": "sha256-9LRXf/Wy500rNO9IhDSH+PSuadS3TguNFCbcbI4YYZU=", + "lastModified": 1775836847, + "narHash": "sha256-pU7GShEizE8HkDGvR9NWZPqksiGyvfcWodtFyc318TM=", "owner": "logos-co", "repo": "logos-package-manager", - "rev": "e5c25989861f4487c3dc8c7b3bc0062bcbc3221f", + "rev": "39118d6c52226e88a77c6ff7d1196229f56b757e", "type": "github" }, "original": { @@ -2535,11 +2571,11 @@ ] }, "locked": { - "lastModified": 1773965173, - "narHash": "sha256-toDnGXUthRcQm7vcEYzb2bLI7FE1tbfzH8Ie2Cnb9mk=", + "lastModified": 1775835037, + "narHash": "sha256-Cti0DhkzyLQs98BSzcHWMLtGXpa3n+R+5upfSw6vKdQ=", "owner": "logos-co", "repo": "logos-package", - "rev": "9e3730d5c0e3ec955761c05b50e3a6047ee4030b", + "rev": "ff93a0df15ceab255f27687d22d962ea2737efbe", "type": "github" }, "original": { @@ -2561,11 +2597,11 @@ ] }, "locked": { - "lastModified": 1773965173, - "narHash": "sha256-toDnGXUthRcQm7vcEYzb2bLI7FE1tbfzH8Ie2Cnb9mk=", + "lastModified": 1775835037, + "narHash": "sha256-Cti0DhkzyLQs98BSzcHWMLtGXpa3n+R+5upfSw6vKdQ=", "owner": "logos-co", "repo": "logos-package", - "rev": "9e3730d5c0e3ec955761c05b50e3a6047ee4030b", + "rev": "ff93a0df15ceab255f27687d22d962ea2737efbe", "type": "github" }, "original": { @@ -2587,11 +2623,11 @@ ] }, "locked": { - "lastModified": 1773965173, - "narHash": "sha256-toDnGXUthRcQm7vcEYzb2bLI7FE1tbfzH8Ie2Cnb9mk=", + "lastModified": 1775835037, + "narHash": "sha256-Cti0DhkzyLQs98BSzcHWMLtGXpa3n+R+5upfSw6vKdQ=", "owner": "logos-co", "repo": "logos-package", - "rev": "9e3730d5c0e3ec955761c05b50e3a6047ee4030b", + "rev": "ff93a0df15ceab255f27687d22d962ea2737efbe", "type": "github" }, "original": { @@ -2614,11 +2650,11 @@ ] }, "locked": { - "lastModified": 1773965173, - "narHash": "sha256-toDnGXUthRcQm7vcEYzb2bLI7FE1tbfzH8Ie2Cnb9mk=", + "lastModified": 1775677349, + "narHash": "sha256-G+0E1mkmG3QDeTR4Pgy+xkiole/TDq+FYrvHwNp9Yrc=", "owner": "logos-co", "repo": "logos-package", - "rev": "9e3730d5c0e3ec955761c05b50e3a6047ee4030b", + "rev": "64edea0e64309e1c9f91259d16f8f81e5e39e40e", "type": "github" }, "original": { @@ -2629,7 +2665,7 @@ }, "logos-package_6": { "inputs": { - "logos-nix": "logos-nix_68", + "logos-nix": "logos-nix_70", "nixpkgs": [ "logos-module-builder", "logos-standalone-app", @@ -2640,11 +2676,11 @@ ] }, "locked": { - "lastModified": 1773965173, - "narHash": "sha256-toDnGXUthRcQm7vcEYzb2bLI7FE1tbfzH8Ie2Cnb9mk=", + "lastModified": 1775835037, + "narHash": "sha256-Cti0DhkzyLQs98BSzcHWMLtGXpa3n+R+5upfSw6vKdQ=", "owner": "logos-co", "repo": "logos-package", - "rev": "9e3730d5c0e3ec955761c05b50e3a6047ee4030b", + "rev": "ff93a0df15ceab255f27687d22d962ea2737efbe", "type": "github" }, "original": { @@ -2655,7 +2691,7 @@ }, "logos-package_7": { "inputs": { - "logos-nix": "logos-nix_72", + "logos-nix": "logos-nix_74", "nixpkgs": [ "logos-module-builder", "nix-bundle-lgx", @@ -2665,11 +2701,11 @@ ] }, "locked": { - "lastModified": 1773965173, - "narHash": "sha256-toDnGXUthRcQm7vcEYzb2bLI7FE1tbfzH8Ie2Cnb9mk=", + "lastModified": 1775835037, + "narHash": "sha256-Cti0DhkzyLQs98BSzcHWMLtGXpa3n+R+5upfSw6vKdQ=", "owner": "logos-co", "repo": "logos-package", - "rev": "9e3730d5c0e3ec955761c05b50e3a6047ee4030b", + "rev": "ff93a0df15ceab255f27687d22d962ea2737efbe", "type": "github" }, "original": { @@ -2680,7 +2716,7 @@ }, "logos-package_8": { "inputs": { - "logos-nix": "logos-nix_76", + "logos-nix": "logos-nix_78", "nixpkgs": [ "logos-module-builder", "nix-bundle-logos-module-install", @@ -2691,11 +2727,11 @@ ] }, "locked": { - "lastModified": 1773965173, - "narHash": "sha256-toDnGXUthRcQm7vcEYzb2bLI7FE1tbfzH8Ie2Cnb9mk=", + "lastModified": 1775835037, + "narHash": "sha256-Cti0DhkzyLQs98BSzcHWMLtGXpa3n+R+5upfSw6vKdQ=", "owner": "logos-co", "repo": "logos-package", - "rev": "9e3730d5c0e3ec955761c05b50e3a6047ee4030b", + "rev": "ff93a0df15ceab255f27687d22d962ea2737efbe", "type": "github" }, "original": { @@ -2706,7 +2742,7 @@ }, "logos-package_9": { "inputs": { - "logos-nix": "logos-nix_81", + "logos-nix": "logos-nix_83", "nixpkgs": [ "logos-module-builder", "nix-bundle-logos-module-install", @@ -2717,11 +2753,11 @@ ] }, "locked": { - "lastModified": 1773965173, - "narHash": "sha256-toDnGXUthRcQm7vcEYzb2bLI7FE1tbfzH8Ie2Cnb9mk=", + "lastModified": 1775835037, + "narHash": "sha256-Cti0DhkzyLQs98BSzcHWMLtGXpa3n+R+5upfSw6vKdQ=", "owner": "logos-co", "repo": "logos-package", - "rev": "9e3730d5c0e3ec955761c05b50e3a6047ee4030b", + "rev": "ff93a0df15ceab255f27687d22d962ea2737efbe", "type": "github" }, "original": { @@ -2742,11 +2778,11 @@ ] }, "locked": { - "lastModified": 1775140086, - "narHash": "sha256-evfXNeRTneUl86IUMsIQfGrazoQlaJHElL7zfuesC/Y=", + "lastModified": 1775835070, + "narHash": "sha256-RaJzt4sx6WrLtwhRhkGki/I+Bvt8fuC+p+oCcuLTm3g=", "owner": "logos-co", "repo": "logos-plugin-qt", - "rev": "b30f00cbbcce8a979ddffb9ad18356d37a30d259", + "rev": "78a04d603d910d864a26b158eca0882321258d44", "type": "github" }, "original": { @@ -2767,11 +2803,11 @@ ] }, "locked": { - "lastModified": 1775140086, - "narHash": "sha256-evfXNeRTneUl86IUMsIQfGrazoQlaJHElL7zfuesC/Y=", + "lastModified": 1775835070, + "narHash": "sha256-RaJzt4sx6WrLtwhRhkGki/I+Bvt8fuC+p+oCcuLTm3g=", "owner": "logos-co", "repo": "logos-plugin-qt", - "rev": "b30f00cbbcce8a979ddffb9ad18356d37a30d259", + "rev": "78a04d603d910d864a26b158eca0882321258d44", "type": "github" }, "original": { @@ -2780,6 +2816,30 @@ "type": "github" } }, + "logos-qt-mcp": { + "inputs": { + "logos-nix": "logos-nix_67", + "nixpkgs": [ + "logos-module-builder", + "logos-standalone-app", + "logos-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1774455349, + "narHash": "sha256-rebrtH1UxC1hDuwQBwyYbGzNCrnuuqiVL7OvzUhk65k=", + "owner": "logos-co", + "repo": "logos-qt-mcp", + "rev": "c5223b4b640add09e461983b8fddbd12c8b31f4f", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-qt-mcp", + "type": "github" + } + }, "logos-standalone-app": { "inputs": { "logos-capability-module": "logos-capability-module_4", @@ -2787,6 +2847,8 @@ "logos-design-system": "logos-design-system", "logos-liblogos": "logos-liblogos_3", "logos-nix": "logos-nix_66", + "logos-qt-mcp": "logos-qt-mcp", + "logos-view-module-runtime": "logos-view-module-runtime", "nix-bundle-lgx": "nix-bundle-lgx_2", "nixpkgs": [ "logos-module-builder", @@ -2796,11 +2858,11 @@ ] }, "locked": { - "lastModified": 1775052093, - "narHash": "sha256-HJfrILACOcdkhT8nvK7LvzcGor6uZv5IYbACkfHGv+0=", + "lastModified": 1777037010, + "narHash": "sha256-CfXpdDD/3/SNNmbtiJUdrloc28xDstdB7DcEgfzhAPI=", "owner": "logos-co", "repo": "logos-standalone-app", - "rev": "f6e13eabd144b4cf87b533cce7318536cbd03123", + "rev": "c3a079c1e007deee592ce74196c258077bdf3692", "type": "github" }, "original": { @@ -2815,7 +2877,7 @@ "logos-module-builder", "logos-cpp-sdk" ], - "logos-nix": "logos-nix_70", + "logos-nix": "logos-nix_72", "nixpkgs": [ "logos-module-builder", "logos-test-framework", @@ -2824,11 +2886,11 @@ ] }, "locked": { - "lastModified": 1775163659, - "narHash": "sha256-6gk164iURa+emkY30WA9sIUCEA9ByavuBEveC5sfa08=", + "lastModified": 1775684803, + "narHash": "sha256-BnnrAjYJHW994WYAhd6e6/T7igLqJm4utjhqx1a6kLw=", "owner": "logos-co", "repo": "logos-test-framework", - "rev": "a1bcd3608847535975ba4a2da473c03257a82412", + "rev": "55b15075b5990b3c043030a3e404c7f11d57c32b", "type": "github" }, "original": { @@ -2837,6 +2899,35 @@ "type": "github" } }, + "logos-view-module-runtime": { + "inputs": { + "logos-cpp-sdk": [ + "logos-module-builder", + "logos-standalone-app", + "logos-cpp-sdk" + ], + "logos-nix": "logos-nix_68", + "nixpkgs": [ + "logos-module-builder", + "logos-standalone-app", + "logos-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1776431382, + "narHash": "sha256-21SqqdOuHBLUGcYxGvjtC4iKp+wLGEQOKn64qLVl/+0=", + "owner": "logos-co", + "repo": "logos-view-module-runtime", + "rev": "d611d697bf4ff48405d71f6ea29b8103d7969b22", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-view-module-runtime", + "type": "github" + } + }, "nix-bundle-appimage": { "inputs": { "logos-nix": "logos-nix_9", @@ -2850,11 +2941,11 @@ ] }, "locked": { - "lastModified": 1773961597, - "narHash": "sha256-UEUlp3VRXBcj2YlOMTQdeW3qjyGJl2V3+GMf8IXwSWA=", + "lastModified": 1774455478, + "narHash": "sha256-S8IMfdDc+2Wwri0krLDsIUwSqmwanmvHAJWHOFo8ykk=", "owner": "logos-co", "repo": "nix-bundle-appimage", - "rev": "7343f6df1ebab357f51f23dff0af9d7e468638cb", + "rev": "2428125a4a1b34ad9119efa97edb98676283e3da", "type": "github" }, "original": { @@ -2877,11 +2968,11 @@ ] }, "locked": { - "lastModified": 1773961597, - "narHash": "sha256-UEUlp3VRXBcj2YlOMTQdeW3qjyGJl2V3+GMf8IXwSWA=", + "lastModified": 1774455478, + "narHash": "sha256-S8IMfdDc+2Wwri0krLDsIUwSqmwanmvHAJWHOFo8ykk=", "owner": "logos-co", "repo": "nix-bundle-appimage", - "rev": "7343f6df1ebab357f51f23dff0af9d7e468638cb", + "rev": "2428125a4a1b34ad9119efa97edb98676283e3da", "type": "github" }, "original": { @@ -2902,11 +2993,11 @@ ] }, "locked": { - "lastModified": 1774455478, - "narHash": "sha256-S8IMfdDc+2Wwri0krLDsIUwSqmwanmvHAJWHOFo8ykk=", + "lastModified": 1776458016, + "narHash": "sha256-yIFmtVps0SfxusidPT5s5pAJxTODWhWv69UwzDwEDGM=", "owner": "logos-co", "repo": "nix-bundle-appimage", - "rev": "2428125a4a1b34ad9119efa97edb98676283e3da", + "rev": "14111ea314b9f40aff3e4c54816e6ee9680d962f", "type": "github" }, "original": { @@ -2929,11 +3020,11 @@ ] }, "locked": { - "lastModified": 1773961597, - "narHash": "sha256-UEUlp3VRXBcj2YlOMTQdeW3qjyGJl2V3+GMf8IXwSWA=", + "lastModified": 1774455478, + "narHash": "sha256-S8IMfdDc+2Wwri0krLDsIUwSqmwanmvHAJWHOFo8ykk=", "owner": "logos-co", "repo": "nix-bundle-appimage", - "rev": "7343f6df1ebab357f51f23dff0af9d7e468638cb", + "rev": "2428125a4a1b34ad9119efa97edb98676283e3da", "type": "github" }, "original": { @@ -2957,11 +3048,11 @@ ] }, "locked": { - "lastModified": 1773961597, - "narHash": "sha256-UEUlp3VRXBcj2YlOMTQdeW3qjyGJl2V3+GMf8IXwSWA=", + "lastModified": 1774455478, + "narHash": "sha256-S8IMfdDc+2Wwri0krLDsIUwSqmwanmvHAJWHOFo8ykk=", "owner": "logos-co", "repo": "nix-bundle-appimage", - "rev": "7343f6df1ebab357f51f23dff0af9d7e468638cb", + "rev": "2428125a4a1b34ad9119efa97edb98676283e3da", "type": "github" }, "original": { @@ -2972,7 +3063,7 @@ }, "nix-bundle-appimage_6": { "inputs": { - "logos-nix": "logos-nix_77", + "logos-nix": "logos-nix_79", "nix-bundle-dir": "nix-bundle-dir_14", "nixpkgs": [ "logos-module-builder", @@ -2984,11 +3075,11 @@ ] }, "locked": { - "lastModified": 1773961597, - "narHash": "sha256-UEUlp3VRXBcj2YlOMTQdeW3qjyGJl2V3+GMf8IXwSWA=", + "lastModified": 1774455478, + "narHash": "sha256-S8IMfdDc+2Wwri0krLDsIUwSqmwanmvHAJWHOFo8ykk=", "owner": "logos-co", "repo": "nix-bundle-appimage", - "rev": "7343f6df1ebab357f51f23dff0af9d7e468638cb", + "rev": "2428125a4a1b34ad9119efa97edb98676283e3da", "type": "github" }, "original": { @@ -3061,11 +3152,11 @@ ] }, "locked": { - "lastModified": 1773961179, - "narHash": "sha256-bpaTvz//R8WFP5xnnDLv3a9l7unDmBwJjCewx3wCjzM=", + "lastModified": 1774455641, + "narHash": "sha256-HrVJguPxhIoZMCH+x8Wooa0tE6slUhgNOU6P89t2uQc=", "owner": "logos-co", "repo": "nix-bundle-dir", - "rev": "cd214dbf15487d80967389847ae2210468be6ebf", + "rev": "3d155cab09051703a0b02ff2de166a53c30cbca8", "type": "github" }, "original": { @@ -3076,7 +3167,7 @@ }, "nix-bundle-dir_12": { "inputs": { - "logos-nix": "logos-nix_69", + "logos-nix": "logos-nix_71", "nixpkgs": [ "logos-module-builder", "logos-standalone-app", @@ -3087,11 +3178,11 @@ ] }, "locked": { - "lastModified": 1773961179, - "narHash": "sha256-bpaTvz//R8WFP5xnnDLv3a9l7unDmBwJjCewx3wCjzM=", + "lastModified": 1774455641, + "narHash": "sha256-HrVJguPxhIoZMCH+x8Wooa0tE6slUhgNOU6P89t2uQc=", "owner": "logos-co", "repo": "nix-bundle-dir", - "rev": "cd214dbf15487d80967389847ae2210468be6ebf", + "rev": "3d155cab09051703a0b02ff2de166a53c30cbca8", "type": "github" }, "original": { @@ -3102,7 +3193,7 @@ }, "nix-bundle-dir_13": { "inputs": { - "logos-nix": "logos-nix_73", + "logos-nix": "logos-nix_75", "nixpkgs": [ "logos-module-builder", "nix-bundle-lgx", @@ -3112,11 +3203,11 @@ ] }, "locked": { - "lastModified": 1773961179, - "narHash": "sha256-bpaTvz//R8WFP5xnnDLv3a9l7unDmBwJjCewx3wCjzM=", + "lastModified": 1774455641, + "narHash": "sha256-HrVJguPxhIoZMCH+x8Wooa0tE6slUhgNOU6P89t2uQc=", "owner": "logos-co", "repo": "nix-bundle-dir", - "rev": "cd214dbf15487d80967389847ae2210468be6ebf", + "rev": "3d155cab09051703a0b02ff2de166a53c30cbca8", "type": "github" }, "original": { @@ -3127,7 +3218,7 @@ }, "nix-bundle-dir_14": { "inputs": { - "logos-nix": "logos-nix_78", + "logos-nix": "logos-nix_80", "nixpkgs": [ "logos-module-builder", "nix-bundle-logos-module-install", @@ -3152,7 +3243,7 @@ }, "nix-bundle-dir_15": { "inputs": { - "logos-nix": "logos-nix_79", + "logos-nix": "logos-nix_81", "nixpkgs": [ "logos-module-builder", "nix-bundle-logos-module-install", @@ -3163,11 +3254,11 @@ ] }, "locked": { - "lastModified": 1773961179, - "narHash": "sha256-bpaTvz//R8WFP5xnnDLv3a9l7unDmBwJjCewx3wCjzM=", + "lastModified": 1774455641, + "narHash": "sha256-HrVJguPxhIoZMCH+x8Wooa0tE6slUhgNOU6P89t2uQc=", "owner": "logos-co", "repo": "nix-bundle-dir", - "rev": "cd214dbf15487d80967389847ae2210468be6ebf", + "rev": "3d155cab09051703a0b02ff2de166a53c30cbca8", "type": "github" }, "original": { @@ -3178,7 +3269,7 @@ }, "nix-bundle-dir_16": { "inputs": { - "logos-nix": "logos-nix_82", + "logos-nix": "logos-nix_84", "nixpkgs": [ "logos-module-builder", "nix-bundle-logos-module-install", @@ -3189,11 +3280,11 @@ ] }, "locked": { - "lastModified": 1773961179, - "narHash": "sha256-bpaTvz//R8WFP5xnnDLv3a9l7unDmBwJjCewx3wCjzM=", + "lastModified": 1774455641, + "narHash": "sha256-HrVJguPxhIoZMCH+x8Wooa0tE6slUhgNOU6P89t2uQc=", "owner": "logos-co", "repo": "nix-bundle-dir", - "rev": "cd214dbf15487d80967389847ae2210468be6ebf", + "rev": "3d155cab09051703a0b02ff2de166a53c30cbca8", "type": "github" }, "original": { @@ -3214,11 +3305,11 @@ ] }, "locked": { - "lastModified": 1773961179, - "narHash": "sha256-bpaTvz//R8WFP5xnnDLv3a9l7unDmBwJjCewx3wCjzM=", + "lastModified": 1774455641, + "narHash": "sha256-HrVJguPxhIoZMCH+x8Wooa0tE6slUhgNOU6P89t2uQc=", "owner": "logos-co", "repo": "nix-bundle-dir", - "rev": "cd214dbf15487d80967389847ae2210468be6ebf", + "rev": "3d155cab09051703a0b02ff2de166a53c30cbca8", "type": "github" }, "original": { @@ -3265,11 +3356,11 @@ ] }, "locked": { - "lastModified": 1773961179, - "narHash": "sha256-bpaTvz//R8WFP5xnnDLv3a9l7unDmBwJjCewx3wCjzM=", + "lastModified": 1774455641, + "narHash": "sha256-HrVJguPxhIoZMCH+x8Wooa0tE6slUhgNOU6P89t2uQc=", "owner": "logos-co", "repo": "nix-bundle-dir", - "rev": "cd214dbf15487d80967389847ae2210468be6ebf", + "rev": "3d155cab09051703a0b02ff2de166a53c30cbca8", "type": "github" }, "original": { @@ -3288,11 +3379,11 @@ ] }, "locked": { - "lastModified": 1773961179, - "narHash": "sha256-bpaTvz//R8WFP5xnnDLv3a9l7unDmBwJjCewx3wCjzM=", + "lastModified": 1776457964, + "narHash": "sha256-hSwyWA3ufUhrLy9cmuIbKl4s+mvZmcMqjD/pRx1d6sc=", "owner": "logos-co", "repo": "nix-bundle-dir", - "rev": "cd214dbf15487d80967389847ae2210468be6ebf", + "rev": "061a9a830afaf23bb85d13fac673a6bb97edb2e2", "type": "github" }, "original": { @@ -3312,11 +3403,11 @@ ] }, "locked": { - "lastModified": 1774455641, - "narHash": "sha256-HrVJguPxhIoZMCH+x8Wooa0tE6slUhgNOU6P89t2uQc=", + "lastModified": 1776457964, + "narHash": "sha256-hSwyWA3ufUhrLy9cmuIbKl4s+mvZmcMqjD/pRx1d6sc=", "owner": "logos-co", "repo": "nix-bundle-dir", - "rev": "3d155cab09051703a0b02ff2de166a53c30cbca8", + "rev": "061a9a830afaf23bb85d13fac673a6bb97edb2e2", "type": "github" }, "original": { @@ -3363,11 +3454,11 @@ ] }, "locked": { - "lastModified": 1773961179, - "narHash": "sha256-bpaTvz//R8WFP5xnnDLv3a9l7unDmBwJjCewx3wCjzM=", + "lastModified": 1774455641, + "narHash": "sha256-HrVJguPxhIoZMCH+x8Wooa0tE6slUhgNOU6P89t2uQc=", "owner": "logos-co", "repo": "nix-bundle-dir", - "rev": "cd214dbf15487d80967389847ae2210468be6ebf", + "rev": "3d155cab09051703a0b02ff2de166a53c30cbca8", "type": "github" }, "original": { @@ -3389,11 +3480,11 @@ ] }, "locked": { - "lastModified": 1773961179, - "narHash": "sha256-bpaTvz//R8WFP5xnnDLv3a9l7unDmBwJjCewx3wCjzM=", + "lastModified": 1774455641, + "narHash": "sha256-HrVJguPxhIoZMCH+x8Wooa0tE6slUhgNOU6P89t2uQc=", "owner": "logos-co", "repo": "nix-bundle-dir", - "rev": "cd214dbf15487d80967389847ae2210468be6ebf", + "rev": "3d155cab09051703a0b02ff2de166a53c30cbca8", "type": "github" }, "original": { @@ -3416,11 +3507,11 @@ ] }, "locked": { - "lastModified": 1774455541, - "narHash": "sha256-ku5gG6qKIZeWzJ/jNOxfsx1rwJ3kPrCw8/wnBKq1Uyw=", + "lastModified": 1775836380, + "narHash": "sha256-XbBPcMuDFA/SxYVw9TIRQbhie5Vj5MqwdU+Gh1iR1LA=", "owner": "logos-co", "repo": "nix-bundle-lgx", - "rev": "9d6f9016c865b9d2793672bc3c45a50b59753c78", + "rev": "9d8f8602b1574ec9ac4c9b31ae0c92570221c268", "type": "github" }, "original": { @@ -3431,7 +3522,7 @@ }, "nix-bundle-lgx_2": { "inputs": { - "logos-nix": "logos-nix_67", + "logos-nix": "logos-nix_69", "logos-package": "logos-package_6", "nix-bundle-dir": "nix-bundle-dir_12", "nixpkgs": [ @@ -3442,11 +3533,11 @@ ] }, "locked": { - "lastModified": 1774455541, - "narHash": "sha256-ku5gG6qKIZeWzJ/jNOxfsx1rwJ3kPrCw8/wnBKq1Uyw=", + "lastModified": 1775836380, + "narHash": "sha256-XbBPcMuDFA/SxYVw9TIRQbhie5Vj5MqwdU+Gh1iR1LA=", "owner": "logos-co", "repo": "nix-bundle-lgx", - "rev": "9d6f9016c865b9d2793672bc3c45a50b59753c78", + "rev": "9d8f8602b1574ec9ac4c9b31ae0c92570221c268", "type": "github" }, "original": { @@ -3457,7 +3548,7 @@ }, "nix-bundle-lgx_3": { "inputs": { - "logos-nix": "logos-nix_71", + "logos-nix": "logos-nix_73", "logos-package": "logos-package_7", "nix-bundle-dir": "nix-bundle-dir_13", "nixpkgs": [ @@ -3468,11 +3559,11 @@ ] }, "locked": { - "lastModified": 1774455541, - "narHash": "sha256-ku5gG6qKIZeWzJ/jNOxfsx1rwJ3kPrCw8/wnBKq1Uyw=", + "lastModified": 1775836380, + "narHash": "sha256-XbBPcMuDFA/SxYVw9TIRQbhie5Vj5MqwdU+Gh1iR1LA=", "owner": "logos-co", "repo": "nix-bundle-lgx", - "rev": "9d6f9016c865b9d2793672bc3c45a50b59753c78", + "rev": "9d8f8602b1574ec9ac4c9b31ae0c92570221c268", "type": "github" }, "original": { @@ -3483,7 +3574,7 @@ }, "nix-bundle-lgx_4": { "inputs": { - "logos-nix": "logos-nix_80", + "logos-nix": "logos-nix_82", "logos-package": "logos-package_9", "nix-bundle-dir": "nix-bundle-dir_16", "nixpkgs": [ @@ -3495,11 +3586,11 @@ ] }, "locked": { - "lastModified": 1774455541, - "narHash": "sha256-ku5gG6qKIZeWzJ/jNOxfsx1rwJ3kPrCw8/wnBKq1Uyw=", + "lastModified": 1775836380, + "narHash": "sha256-XbBPcMuDFA/SxYVw9TIRQbhie5Vj5MqwdU+Gh1iR1LA=", "owner": "logos-co", "repo": "nix-bundle-lgx", - "rev": "9d6f9016c865b9d2793672bc3c45a50b59753c78", + "rev": "9d8f8602b1574ec9ac4c9b31ae0c92570221c268", "type": "github" }, "original": { @@ -3521,11 +3612,11 @@ ] }, "locked": { - "lastModified": 1774899467, - "narHash": "sha256-osJph/UNShD8/i80ajUugizxJW0P4IEaZzSOsaSWCsI=", + "lastModified": 1775839388, + "narHash": "sha256-0QH146bzL2kKBYJq2yA35iPwug55j2xjEyKCS7tjhvg=", "owner": "logos-co", "repo": "nix-bundle-logos-module-install", - "rev": "87afbb0241a6f7c1865a12f855dce63c68d1dd7f", + "rev": "89cc9ea91275396d589c767d76926459ac77ef20", "type": "github" }, "original": { @@ -3536,7 +3627,7 @@ }, "nix-bundle-logos-module-install_2": { "inputs": { - "logos-nix": "logos-nix_74", + "logos-nix": "logos-nix_76", "logos-package-manager": "logos-package-manager_5", "nix-bundle-lgx": "nix-bundle-lgx_4", "nixpkgs": [ @@ -3547,11 +3638,11 @@ ] }, "locked": { - "lastModified": 1774899467, - "narHash": "sha256-osJph/UNShD8/i80ajUugizxJW0P4IEaZzSOsaSWCsI=", + "lastModified": 1775839388, + "narHash": "sha256-0QH146bzL2kKBYJq2yA35iPwug55j2xjEyKCS7tjhvg=", "owner": "logos-co", "repo": "nix-bundle-logos-module-install", - "rev": "87afbb0241a6f7c1865a12f855dce63c68d1dd7f", + "rev": "89cc9ea91275396d589c767d76926459ac77ef20", "type": "github" }, "original": { @@ -4872,6 +4963,38 @@ "type": "github" } }, + "nixpkgs_84": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_85": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "nixpkgs_9": { "locked": { "lastModified": 1759036355, @@ -4899,11 +5022,11 @@ ] }, "locked": { - "lastModified": 1774455550, - "narHash": "sha256-T30DJXAMb+hezgnmlZe9qqa9LL5oolvuAdF5fIVz8A0=", + "lastModified": 1775744159, + "narHash": "sha256-hTVAnDREBQOVHML6KU3K7Ge0CRBqnFIg7uYL7qDnD8o=", "owner": "logos-co", "repo": "process-stats", - "rev": "8213ad456b4ac074a214f24fc2b378b1bdbb0234", + "rev": "33ace1270f90c89b3565e803139c0970fcd1ce8f", "type": "github" }, "original": { @@ -4924,11 +5047,11 @@ ] }, "locked": { - "lastModified": 1774455550, - "narHash": "sha256-T30DJXAMb+hezgnmlZe9qqa9LL5oolvuAdF5fIVz8A0=", + "lastModified": 1775744159, + "narHash": "sha256-hTVAnDREBQOVHML6KU3K7Ge0CRBqnFIg7uYL7qDnD8o=", "owner": "logos-co", "repo": "process-stats", - "rev": "8213ad456b4ac074a214f24fc2b378b1bdbb0234", + "rev": "33ace1270f90c89b3565e803139c0970fcd1ce8f", "type": "github" }, "original": { @@ -4950,11 +5073,11 @@ ] }, "locked": { - "lastModified": 1774455550, - "narHash": "sha256-T30DJXAMb+hezgnmlZe9qqa9LL5oolvuAdF5fIVz8A0=", + "lastModified": 1775744159, + "narHash": "sha256-hTVAnDREBQOVHML6KU3K7Ge0CRBqnFIg7uYL7qDnD8o=", "owner": "logos-co", "repo": "process-stats", - "rev": "8213ad456b4ac074a214f24fc2b378b1bdbb0234", + "rev": "33ace1270f90c89b3565e803139c0970fcd1ce8f", "type": "github" }, "original": { @@ -4968,7 +5091,7 @@ "logos-liblogos": "logos-liblogos", "logos-logoscore-cli": "logos-logoscore-cli", "logos-module-builder": "logos-module-builder", - "logos-nix": "logos-nix_83", + "logos-nix": "logos-nix_85", "nixpkgs": [ "logos-nix", "nixpkgs" diff --git a/flake.nix b/flake.nix index dd3bbd7..ebdc6ef 100644 --- a/flake.nix +++ b/flake.nix @@ -19,6 +19,15 @@ configFile = ./test-basic-module/metadata.json; }; + # Pure-C++ mirror of `basic`. Same method matrix, but every signature + # uses std::string / LogosMap / LogosList / StdLogosResult instead of + # Qt types. The builder detects `interface: "universal"` in metadata + # and runs `logos-cpp-generator --from-header` to produce the Qt glue. + basicCpp = mkModule { + src = ./test-basic-module-cpp; + configFile = ./test-basic-module-cpp/metadata.json; + }; + extlib = mkModule { src = ./test-extlib-module; configFile = ./test-extlib-module/metadata.json; @@ -87,6 +96,7 @@ # `.include` for generated API headers, `.lgx` for a package archive). modules = forAllSystems (system: { test_basic_module = basic.packages.${system}; + test_basic_module_cpp = basicCpp.packages.${system}; test_extlib_module = extlib.packages.${system}; test_ipc_module = ipc.packages.${system}; test_ipc_new_api_module = ipc-new-api.packages.${system}; @@ -100,6 +110,7 @@ pkgs = import nixpkgs { inherit system; }; in { test_basic_module = basic.packages.${system}.default; + test_basic_module_cpp = basicCpp.packages.${system}.default; test_extlib_module = extlib.packages.${system}.default; test_ipc_module = ipc.packages.${system}.default; test_ipc_new_api_module = ipc-new-api.packages.${system}.default; @@ -114,6 +125,7 @@ name = "logos-test-modules"; paths = [ basic.packages.${system}.default + basicCpp.packages.${system}.default extlib.packages.${system}.default ipc.packages.${system}.default ipc-new-api.packages.${system}.default @@ -129,6 +141,7 @@ # Use the install outputs (bundle + lgpm install in one step) basicInstall = basic.packages.${system}.install; + basicCppInstall = basicCpp.packages.${system}.install; extlibInstall = extlib.packages.${system}.install; ipcInstall = ipc.packages.${system}.install; ipcNewApiInstall = ipc-new-api.packages.${system}.install; @@ -141,10 +154,10 @@ modulesDir = pkgs.runCommand "test-modules-dir" {} '' mkdir -p $out - for installed in ${basicInstall} ${extlibInstall} ${ipcInstall} ${ipcNewApiInstall}; do + for installed in ${basicInstall} ${basicCppInstall} ${extlibInstall} ${ipcInstall} ${ipcNewApiInstall}; do if [ -d "$installed/modules" ]; then cp -rn "$installed/modules/." "$out/" - + fi done diff --git a/test-basic-module-cpp/CMakeLists.txt b/test-basic-module-cpp/CMakeLists.txt new file mode 100644 index 0000000..add0179 --- /dev/null +++ b/test-basic-module-cpp/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.14) +project(TestBasicModuleCppPlugin LANGUAGES CXX) + +if(DEFINED ENV{LOGOS_MODULE_BUILDER_ROOT}) + include($ENV{LOGOS_MODULE_BUILDER_ROOT}/cmake/LogosModule.cmake) +elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/LogosModule.cmake") + include(cmake/LogosModule.cmake) +else() + message(FATAL_ERROR "LogosModule.cmake not found") +endif() + +# Universal module: `interface: "universal"` in metadata.json makes the +# builder run `logos-cpp-generator --from-header` in preConfigure. The +# generator produces `generated_code/test_basic_module_cpp_qt_glue.h` + +# `generated_code/test_basic_module_cpp_dispatch.cpp` which LogosModule.cmake +# picks up automatically — no loader / dispatch source needs to live here. +logos_module( + NAME test_basic_module_cpp + SOURCES + src/test_basic_module_cpp_impl.h + src/test_basic_module_cpp_impl.cpp +) diff --git a/test-basic-module-cpp/metadata.json b/test-basic-module-cpp/metadata.json new file mode 100644 index 0000000..5f45ab6 --- /dev/null +++ b/test-basic-module-cpp/metadata.json @@ -0,0 +1,22 @@ +{ + "name": "test_basic_module_cpp", + "version": "1.0.0", + "type": "core", + "category": "testing", + "description": "Pure-C++ mirror of test_basic_module: every method uses std/LogosMap/LogosList/StdLogosResult (no Qt in the impl), so the generated qt_glue layer is exercised end-to-end.", + "main": "test_basic_module_cpp_plugin", + "interface": "universal", + "dependencies": [], + + "nix": { + "packages": { + "build": [], + "runtime": ["nlohmann_json"] + }, + "external_libraries": [], + "cmake": { + "find_packages": [], + "extra_sources": [] + } + } +} diff --git a/test-basic-module-cpp/src/test_basic_module_cpp_impl.cpp b/test-basic-module-cpp/src/test_basic_module_cpp_impl.cpp new file mode 100644 index 0000000..b3d0c09 --- /dev/null +++ b/test-basic-module-cpp/src/test_basic_module_cpp_impl.cpp @@ -0,0 +1,209 @@ +#include "test_basic_module_cpp_impl.h" + +#include // std::size_t (used in splitString below) +#include // std::move (used in splitString below) + +// Keep return shapes closely aligned with test-basic-module's Qt versions +// so the docker smoke / integration tests can exercise the same matrix +// against both modules. Some values intentionally differ where they +// identify the concrete module implementation — notably `returnString()` +// reports `"test_basic_module_cpp"` so the test can distinguish which of +// the two modules answered the call. + +// ── void ───────────────────────────────────────────────────────────────── + +void TestBasicModuleCppImpl::doNothing() {} +void TestBasicModuleCppImpl::doNothingWithArgs(const std::string&, int64_t) {} + +// ── bool ───────────────────────────────────────────────────────────────── + +bool TestBasicModuleCppImpl::returnTrue() { return true; } +bool TestBasicModuleCppImpl::returnFalse() { return false; } +bool TestBasicModuleCppImpl::isPositive(int64_t value) { return value > 0; } + +// ── int64_t ────────────────────────────────────────────────────────────── + +int64_t TestBasicModuleCppImpl::returnInt() { return 42; } +int64_t TestBasicModuleCppImpl::addInts(int64_t a, int64_t b) { return a + b; } +int64_t TestBasicModuleCppImpl::stringLength(const std::string& s) { + return static_cast(s.size()); +} + +// ── uint64_t ───────────────────────────────────────────────────────────── + +uint64_t TestBasicModuleCppImpl::returnUint() { return 99u; } +uint64_t TestBasicModuleCppImpl::echoUint(uint64_t n) { return n; } + +// ── double ─────────────────────────────────────────────────────────────── + +double TestBasicModuleCppImpl::returnDouble() { return 3.5; } +double TestBasicModuleCppImpl::addDoubles(double a, double b) { return a + b; } + +// ── std::string ────────────────────────────────────────────────────────── + +std::string TestBasicModuleCppImpl::returnString() { return "test_basic_module_cpp"; } +std::string TestBasicModuleCppImpl::echo(const std::string& input) { return input; } +std::string TestBasicModuleCppImpl::concat(const std::string& a, const std::string& b) { + return a + b; +} + +// ── StdLogosResult ─────────────────────────────────────────────────────── +// Mirrors test_basic_module's `successResult` / `errorResult` / `…WithMap` +// / `…WithList` / `validateInput` — payloads tuned so the pytest assertion +// matrix can compare row-for-row with the Qt-module expectations. + +StdLogosResult TestBasicModuleCppImpl::successResult() { + return {true, "operation succeeded", ""}; +} + +StdLogosResult TestBasicModuleCppImpl::errorResult() { + return {false, {}, "deliberate error for testing"}; +} + +StdLogosResult TestBasicModuleCppImpl::resultWithMap() { + nlohmann::json m; + m["name"] = "test"; + m["count"] = 42; + m["active"] = true; + return {true, m, ""}; +} + +StdLogosResult TestBasicModuleCppImpl::resultWithList() { + nlohmann::json list = nlohmann::json::array(); + list.push_back({{"id", 1}, {"label", "first"}}); + list.push_back({{"id", 2}, {"label", "second"}}); + return {true, list, ""}; +} + +StdLogosResult TestBasicModuleCppImpl::validateInput(const std::string& input) { + if (input.empty()) { + return {false, {}, "input cannot be empty"}; + } + nlohmann::json data; + data["input"] = input; + data["length"] = static_cast(input.size()); + return {true, data, ""}; +} + +// ── LogosMap ───────────────────────────────────────────────────────────── + +LogosMap TestBasicModuleCppImpl::returnMap() { + LogosMap m; + m["key"] = "value"; + m["number"] = 7; + return m; +} + +LogosMap TestBasicModuleCppImpl::makeMap(const std::string& key, + const std::string& value) { + LogosMap m; + m[key] = value; + return m; +} + +// ── LogosList ──────────────────────────────────────────────────────────── + +LogosList TestBasicModuleCppImpl::returnList() { + LogosList list = nlohmann::json::array(); + list.push_back(1); + list.push_back(2); + list.push_back(3); + return list; +} + +LogosList TestBasicModuleCppImpl::makeList(const std::string& a, + const std::string& b) { + LogosList list = nlohmann::json::array(); + list.push_back(a); + list.push_back(b); + return list; +} + +// ── std::vector ───────────────────────────────────────────── + +std::vector TestBasicModuleCppImpl::returnStringList() { + return {"one", "two", "three"}; +} + +std::vector TestBasicModuleCppImpl::splitString(const std::string& input) { + // Split on ','. Simple, matches the Qt module's semantics. + std::vector out; + std::string cur; + for (char c : input) { + if (c == ',') { out.push_back(std::move(cur)); cur.clear(); } + else { cur.push_back(c); } + } + out.push_back(std::move(cur)); + return out; +} + +// ── std::vector ───────────────────────────────────────────────── + +std::vector TestBasicModuleCppImpl::returnBytes() { + return {0x01, 0x02, 0x03, 0x04, 0x05}; +} + +int64_t TestBasicModuleCppImpl::byteArraySize(const std::vector& data) { + return static_cast(data.size()); +} + +// ── Parameter types ────────────────────────────────────────────────────── + +int64_t TestBasicModuleCppImpl::echoInt(int64_t n) { return n; } +bool TestBasicModuleCppImpl::echoBool(bool b) { return b; } + +std::string TestBasicModuleCppImpl::joinStrings(const std::vector& list) { + std::string out; + for (std::size_t i = 0; i < list.size(); ++i) { + if (i > 0) out += ","; + out += list[i]; + } + return out; +} + +// ── 0–5 args ───────────────────────────────────────────────────────────── +// The format-string trick (QString("...arg() / arg()")) the Qt module uses +// doesn't translate directly; plain string concatenation produces the same +// output, which keeps the pytest expected-value strings identical. + +static std::string toDec(int64_t n) { return std::to_string(n); } +static std::string toBoolStr(bool b) { return b ? "true" : "false"; } + +std::string TestBasicModuleCppImpl::noArgs() { + return "noArgs()"; +} +std::string TestBasicModuleCppImpl::oneArg(const std::string& a) { + return "oneArg(" + a + ")"; +} +std::string TestBasicModuleCppImpl::twoArgs(const std::string& a, int64_t b) { + return "twoArgs(" + a + ", " + toDec(b) + ")"; +} +std::string TestBasicModuleCppImpl::threeArgs(const std::string& a, int64_t b, bool c) { + return "threeArgs(" + a + ", " + toDec(b) + ", " + toBoolStr(c) + ")"; +} +std::string TestBasicModuleCppImpl::fourArgs(const std::string& a, int64_t b, + bool c, const std::string& d) { + return "fourArgs(" + a + ", " + toDec(b) + ", " + toBoolStr(c) + ", " + d + ")"; +} +std::string TestBasicModuleCppImpl::fiveArgs(const std::string& a, int64_t b, + bool c, const std::string& d, int64_t e) { + return "fiveArgs(" + a + ", " + toDec(b) + ", " + toBoolStr(c) + ", " + d + ", " + toDec(e) + ")"; +} + +// ── Events ─────────────────────────────────────────────────────────────── + +void TestBasicModuleCppImpl::emitTestEvent(const std::string& data) { + if (emitEvent) emitEvent("testEvent", data); +} + +void TestBasicModuleCppImpl::emitMultiArgEvent(const std::string& name, int64_t count) { + // The generator-wired emitEvent takes (name, data). Pack the multi-arg + // payload as a JSON string so the wire shape is lossless (Python test + // just asserts both fragments appear in the stringified event). + if (emitEvent) { + nlohmann::json payload; + payload["name"] = name; + payload["count"] = count; + emitEvent("multiArgEvent", payload.dump()); + } +} diff --git a/test-basic-module-cpp/src/test_basic_module_cpp_impl.h b/test-basic-module-cpp/src/test_basic_module_cpp_impl.h new file mode 100644 index 0000000..f8329a0 --- /dev/null +++ b/test-basic-module-cpp/src/test_basic_module_cpp_impl.h @@ -0,0 +1,111 @@ +#pragma once + +// Pure-C++ mirror of `test_basic_module`. Exercises every parameter/return +// type the code generator needs to translate between C++ std types and Qt +// on the wire: +// +// void, bool, int64_t, uint64_t, double, std::string, +// std::vector, std::vector, +// LogosMap / LogosList (nlohmann::json aliases), StdLogosResult +// +// Absolutely no Qt headers here — `logos-cpp-generator --from-header` +// parses this file as text to derive method signatures, then emits a +// `test_basic_module_cpp_qt_glue.h` + `_dispatch.cpp` that does all the +// QVariant ↔ std conversion. See spec.md in logos-cpp-sdk/cpp-generator/docs/ +// for the full conversion table. +// +// Event emission: the generator detects the `std::function emitEvent` +// member by name and wires it to LogosProviderBase::emitEvent in the +// generated glue layer, so the impl can fire events without touching Qt. + +#include +#include +#include +#include + +#include // LogosMap, LogosList (nlohmann::json aliases) +#include // StdLogosResult + +class TestBasicModuleCppImpl { +public: + TestBasicModuleCppImpl() = default; + ~TestBasicModuleCppImpl() = default; + + // Generated glue wires this in its ctor — call it to emit events. The + // two-string signature (name, json-serialised data) is the one the + // parser recognises; the generator emits a shim that dispatches to + // LogosProviderBase::emitEvent with a QVariantList payload. + std::function emitEvent; + + // ── Return type: void ──────────────────────────────────────────────── + void doNothing(); + void doNothingWithArgs(const std::string& a, int64_t b); + + // ── Return type: bool ──────────────────────────────────────────────── + bool returnTrue(); + bool returnFalse(); + bool isPositive(int64_t value); + + // ── Return type: int64_t ───────────────────────────────────────────── + int64_t returnInt(); + int64_t addInts(int64_t a, int64_t b); + int64_t stringLength(const std::string& s); + + // ── Return type: uint64_t ──────────────────────────────────────────── + uint64_t returnUint(); + uint64_t echoUint(uint64_t n); + + // ── Return type: double ────────────────────────────────────────────── + double returnDouble(); + double addDoubles(double a, double b); + + // ── Return type: std::string ───────────────────────────────────────── + std::string returnString(); + std::string echo(const std::string& input); + std::string concat(const std::string& a, const std::string& b); + + // ── Return type: StdLogosResult ────────────────────────────────────── + // Generator emits a StdLogosResult → Qt LogosResult conversion in glue, + // so over the wire this comes out the same shape as test_basic_module's + // `LogosResult` methods: { success, value, error }. + StdLogosResult successResult(); + StdLogosResult errorResult(); + StdLogosResult resultWithMap(); + StdLogosResult resultWithList(); + StdLogosResult validateInput(const std::string& input); + + // ── Return type: LogosMap (json object) ───────────────────────────── + // `jsonReturn=true` → glue calls nlohmannToQVariant to unpack into + // QVariantMap, which then serialises as a regular JSON object over RPC. + LogosMap returnMap(); + LogosMap makeMap(const std::string& key, const std::string& value); + + // ── Return type: LogosList (json array) ───────────────────────────── + LogosList returnList(); + LogosList makeList(const std::string& a, const std::string& b); + + // ── Return type: std::vector ─────────────────────────── + std::vector returnStringList(); + std::vector splitString(const std::string& input); + + // ── Return type: std::vector (bytes) ─────────────────────── + std::vector returnBytes(); + int64_t byteArraySize(const std::vector& data); + + // ── Parameter types ───────────────────────────────────────────────── + int64_t echoInt(int64_t n); + bool echoBool(bool b); + std::string joinStrings(const std::vector& list); + + // ── Argument counts 0–5 (same matrix as the Qt module) ────────────── + std::string noArgs(); + std::string oneArg(const std::string& a); + std::string twoArgs(const std::string& a, int64_t b); + std::string threeArgs(const std::string& a, int64_t b, bool c); + std::string fourArgs(const std::string& a, int64_t b, bool c, const std::string& d); + std::string fiveArgs(const std::string& a, int64_t b, bool c, const std::string& d, int64_t e); + + // ── Events ────────────────────────────────────────────────────────── + void emitTestEvent(const std::string& data); + void emitMultiArgEvent(const std::string& name, int64_t count); +}; diff --git a/test-thread-safety/test_thread_safety.cpp b/test-thread-safety/test_thread_safety.cpp index 60ccd49..11a76cf 100644 --- a/test-thread-safety/test_thread_safety.cpp +++ b/test-thread-safety/test_thread_safety.cpp @@ -71,7 +71,7 @@ static void initPluginState() { static void initPluginState(const char* pluginsDir) { logos_core_init(s_argc, s_argv); - logos_core_set_plugins_dir(pluginsDir); + logos_core_set_modules_dir(pluginsDir); logos_core_start(); } @@ -102,7 +102,7 @@ TEST_F(PluginApiTest, ConcurrentLoadUnknownPlugins) { barrier.wait(); for (int i = 0; i < kIterations; ++i) { std::string name = "unknown_" + std::to_string(t) + "_" + std::to_string(i); - int ok = logos_core_load_plugin(name.c_str()); + int ok = logos_core_load_module(name.c_str()); EXPECT_EQ(ok, 0); } }); @@ -112,7 +112,7 @@ TEST_F(PluginApiTest, ConcurrentLoadUnknownPlugins) { } // ----------------------------------------------------------------------------- -// logos_core_load_plugin_with_dependencies on unknown plugins from many threads. +// logos_core_load_module_with_dependencies on unknown plugins from many threads. // Each call must return 0 (failure) without crashing. // ----------------------------------------------------------------------------- TEST_F(PluginApiTest, ConcurrentLoadWithDepsUnknown) { @@ -124,7 +124,7 @@ TEST_F(PluginApiTest, ConcurrentLoadWithDepsUnknown) { barrier.wait(); for (int i = 0; i < kIterations; ++i) { std::string name = "nodeps_" + std::to_string(t) + "_" + std::to_string(i); - int rc = logos_core_load_plugin_with_dependencies(name.c_str()); + int rc = logos_core_load_module_with_dependencies(name.c_str()); EXPECT_EQ(rc, 0); } }); @@ -165,8 +165,8 @@ protected: // ----------------------------------------------------------------------------- // Each thread processes a disjoint slice of the generated plugins via -// logos_core_process_plugin. After joining, every plugin must appear in -// logos_core_get_known_plugins(). +// logos_core_process_module. After joining, every plugin must appear in +// logos_core_get_known_modules(). // ----------------------------------------------------------------------------- TEST_F(RealPluginThreadSafetyTest, ConcurrentProcessPlugins) { Barrier barrier(kThreads); @@ -183,7 +183,7 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentProcessPlugins) { barrier.wait(); for (int i = start; i < end; ++i) { std::string path = modules[i].path.toStdString(); - char* name = logos_core_process_plugin(path.c_str()); + char* name = logos_core_process_module(path.c_str()); if (name) { processed.fetch_add(1, std::memory_order_relaxed); delete[] name; @@ -196,7 +196,7 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentProcessPlugins) { EXPECT_EQ(processed.load(), kModuleCount); - char** known = logos_core_get_known_plugins(); + char** known = logos_core_get_known_modules(); EXPECT_EQ(stringArrayLen(known), kModuleCount); for (const DummyModule& m : modules) { std::string name = m.name.toStdString(); @@ -218,7 +218,7 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentProcessSamePlugins) { barrier.wait(); for (const DummyModule& m : modules) { std::string path = m.path.toStdString(); - char* name = logos_core_process_plugin(path.c_str()); + char* name = logos_core_process_module(path.c_str()); delete[] name; } }); @@ -226,14 +226,14 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentProcessSamePlugins) { for (auto& th : threads) th.join(); - char** known = logos_core_get_known_plugins(); + char** known = logos_core_get_known_modules(); EXPECT_EQ(stringArrayLen(known), kModuleCount); freeStringArray(known); } // ----------------------------------------------------------------------------- // Half the threads process plugins while the other half continuously call -// logos_core_get_known_plugins(). Tests reader safety during concurrent writes. +// logos_core_get_known_modules(). Tests reader safety during concurrent writes. // ----------------------------------------------------------------------------- TEST_F(RealPluginThreadSafetyTest, ConcurrentProcessWhileQuerying) { Barrier barrier(kThreads); @@ -250,7 +250,7 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentProcessWhileQuerying) { barrier.wait(); for (int i = start; i < end; ++i) { std::string path = modules[i].path.toStdString(); - char* name = logos_core_process_plugin(path.c_str()); + char* name = logos_core_process_module(path.c_str()); delete[] name; } writersDone.fetch_add(1, std::memory_order_release); @@ -261,7 +261,7 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentProcessWhileQuerying) { threads.emplace_back([&, writers]() { barrier.wait(); while (writersDone.load(std::memory_order_acquire) < writers) { - char** known = logos_core_get_known_plugins(); + char** known = logos_core_get_known_modules(); int len = stringArrayLen(known); EXPECT_GE(len, 0); freeStringArray(known); @@ -271,13 +271,13 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentProcessWhileQuerying) { for (auto& th : threads) th.join(); - char** known = logos_core_get_known_plugins(); + char** known = logos_core_get_known_modules(); EXPECT_EQ(stringArrayLen(known), kModuleCount); freeStringArray(known); } // ----------------------------------------------------------------------------- -// logos_core_get_known_plugins() and logos_core_get_loaded_plugins() are called +// logos_core_get_known_modules() and logos_core_get_loaded_modules() are called // concurrently while other threads repeatedly load and unload a small set of // plugins. Tests that the list accessors are safe under concurrent state // changes. @@ -286,7 +286,7 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentGetListsDuringLoadUnload) { constexpr int kSmall = kThreads; for (int i = 0; i < kSmall; ++i) { std::string path = modules[i].path.toStdString(); - char* name = logos_core_process_plugin(path.c_str()); + char* name = logos_core_process_module(path.c_str()); delete[] name; } @@ -299,8 +299,8 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentGetListsDuringLoadUnload) { barrier.wait(); for (int iter = 0; iter < kIterations; ++iter) { std::string name = modules[iter % kSmall].name.toStdString(); - (void)logos_core_load_plugin(name.c_str()); - (void)logos_core_unload_plugin(name.c_str()); + (void)logos_core_load_module(name.c_str()); + (void)logos_core_unload_module(name.c_str()); } done.store(true, std::memory_order_release); }); @@ -310,11 +310,11 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentGetListsDuringLoadUnload) { threads.emplace_back([&]() { barrier.wait(); while (!done.load(std::memory_order_acquire)) { - char** known = logos_core_get_known_plugins(); + char** known = logos_core_get_known_modules(); EXPECT_NE(known, nullptr); freeStringArray(known); - char** loaded = logos_core_get_loaded_plugins(); + char** loaded = logos_core_get_loaded_modules(); EXPECT_NE(loaded, nullptr); freeStringArray(loaded); } @@ -326,19 +326,19 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentGetListsDuringLoadUnload) { // ----------------------------------------------------------------------------- // Process all plugins, then each thread loads a disjoint slice via -// logos_core_load_plugin. Tests the load path under concurrent pressure. +// logos_core_load_module. Tests the load path under concurrent pressure. // With logos_host available (LOGOS_HOST_PATH set), loads succeed; without it // they return 0. Either way the registry must remain consistent. // ----------------------------------------------------------------------------- TEST_F(RealPluginThreadSafetyTest, ConcurrentLoadPlugin) { for (const DummyModule& m : modules) { std::string path = m.path.toStdString(); - char* name = logos_core_process_plugin(path.c_str()); + char* name = logos_core_process_module(path.c_str()); delete[] name; } { - char** known = logos_core_get_known_plugins(); + char** known = logos_core_get_known_modules(); ASSERT_EQ(stringArrayLen(known), kModuleCount); freeStringArray(known); } @@ -356,14 +356,14 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentLoadPlugin) { barrier.wait(); for (int i = start; i < end; ++i) { std::string name = modules[i].name.toStdString(); - (void)logos_core_load_plugin(name.c_str()); + (void)logos_core_load_module(name.c_str()); } }); } for (auto& th : threads) th.join(); - char** known = logos_core_get_known_plugins(); + char** known = logos_core_get_known_modules(); EXPECT_EQ(stringArrayLen(known), kModuleCount); for (const DummyModule& m : modules) { std::string name = m.name.toStdString(); @@ -373,19 +373,19 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentLoadPlugin) { } // ----------------------------------------------------------------------------- -// All threads hammer the SAME small set of plugins with logos_core_load_plugin. +// All threads hammer the SAME small set of plugins with logos_core_load_module. // Tests mutex contention and the "already loaded" fast-return branch. // ----------------------------------------------------------------------------- TEST_F(RealPluginThreadSafetyTest, ConcurrentLoadSamePlugin) { constexpr int kSmall = kThreads; for (int i = 0; i < kSmall; ++i) { std::string path = modules[i].path.toStdString(); - char* name = logos_core_process_plugin(path.c_str()); + char* name = logos_core_process_module(path.c_str()); delete[] name; } { - char** known = logos_core_get_known_plugins(); + char** known = logos_core_get_known_modules(); ASSERT_EQ(stringArrayLen(known), kSmall); freeStringArray(known); } @@ -398,31 +398,31 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentLoadSamePlugin) { barrier.wait(); for (int i = 0; i < kSmall; ++i) { std::string name = modules[i].name.toStdString(); - (void)logos_core_load_plugin(name.c_str()); + (void)logos_core_load_module(name.c_str()); } }); } for (auto& th : threads) th.join(); - char** known = logos_core_get_known_plugins(); + char** known = logos_core_get_known_modules(); EXPECT_EQ(stringArrayLen(known), kSmall); freeStringArray(known); } // ----------------------------------------------------------------------------- -// Each thread loads a disjoint slice via logos_core_load_plugin_with_dependencies. +// Each thread loads a disjoint slice via logos_core_load_module_with_dependencies. // Tests dependency resolution and loadMutex acquisition from multiple threads. // ----------------------------------------------------------------------------- TEST_F(RealPluginThreadSafetyTest, ConcurrentLoadWithDeps) { for (const DummyModule& m : modules) { std::string path = m.path.toStdString(); - char* name = logos_core_process_plugin(path.c_str()); + char* name = logos_core_process_module(path.c_str()); delete[] name; } { - char** known = logos_core_get_known_plugins(); + char** known = logos_core_get_known_modules(); ASSERT_EQ(stringArrayLen(known), kModuleCount); freeStringArray(known); } @@ -440,33 +440,33 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentLoadWithDeps) { barrier.wait(); for (int i = start; i < end; ++i) { std::string name = modules[i].name.toStdString(); - (void)logos_core_load_plugin_with_dependencies(name.c_str()); + (void)logos_core_load_module_with_dependencies(name.c_str()); } }); } for (auto& th : threads) th.join(); - char** known = logos_core_get_known_plugins(); + char** known = logos_core_get_known_modules(); EXPECT_EQ(stringArrayLen(known), kModuleCount); freeStringArray(known); } // ----------------------------------------------------------------------------- -// Half the threads call logos_core_load_plugin while the other half call -// logos_core_unload_plugin on the same small module set. Tests the load/unload +// Half the threads call logos_core_load_module while the other half call +// logos_core_unload_module on the same small module set. Tests the load/unload // interplay under concurrent pressure. // ----------------------------------------------------------------------------- TEST_F(RealPluginThreadSafetyTest, ConcurrentLoadUnloadInterleaved) { constexpr int kSmall = kThreads; for (int i = 0; i < kSmall; ++i) { std::string path = modules[i].path.toStdString(); - char* name = logos_core_process_plugin(path.c_str()); + char* name = logos_core_process_module(path.c_str()); delete[] name; } { - char** known = logos_core_get_known_plugins(); + char** known = logos_core_get_known_modules(); ASSERT_EQ(stringArrayLen(known), kSmall); freeStringArray(known); } @@ -483,7 +483,7 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentLoadUnloadInterleaved) { for (int iter = 0; iter < 10; ++iter) { for (int i = 0; i < kSmall; ++i) { std::string name = modules[i].name.toStdString(); - (void)logos_core_load_plugin(name.c_str()); + (void)logos_core_load_module(name.c_str()); } } }); @@ -495,7 +495,7 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentLoadUnloadInterleaved) { for (int iter = 0; iter < 10; ++iter) { for (int i = 0; i < kSmall; ++i) { std::string name = modules[i].name.toStdString(); - (void)logos_core_unload_plugin(name.c_str()); + (void)logos_core_unload_module(name.c_str()); } } }); @@ -504,7 +504,7 @@ TEST_F(RealPluginThreadSafetyTest, ConcurrentLoadUnloadInterleaved) { for (auto& th : threads) th.join(); // All modules must still be registered; load/unload must not corrupt the registry. - char** known = logos_core_get_known_plugins(); + char** known = logos_core_get_known_modules(); EXPECT_EQ(stringArrayLen(known), kSmall); for (int i = 0; i < kSmall; ++i) { std::string name = modules[i].name.toStdString(); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index a15aa7e..475b507 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -19,7 +19,8 @@ UNIT_NEW_API_TEST_BIN="${UNIT_NEW_API_TEST_BIN:-}" CALL_TIMEOUT="${TEST_TIMEOUT:-30}" # TEST_GROUPS: comma-separated list of groups to run (default: all) -# Available groups: basic, extlib, ipc, ipc-new-api, multi, errors, unit, unit-new-api +# Available groups: basic, basic-cpp, extlib, ipc, ipc-new-api, multi, errors, +# unit, unit-new-api # Example: TEST_GROUPS=ipc or TEST_GROUPS=ipc,basic or TEST_GROUPS=ipc-new-api if [[ -n "${TEST_GROUPS:-}" ]]; then IFS=',' read -ra ENABLED_GROUPS <<< "$TEST_GROUPS" @@ -137,6 +138,9 @@ skip_test() { test_basic() { assert_call "$1" "$2" -m "$MODULES_DIR" -l test_basic_module -c "$3" } +test_basic_cpp() { + assert_call "$1" "$2" -m "$MODULES_DIR" -l test_basic_module_cpp -c "$3" +} test_extlib() { assert_call "$1" "$2" -m "$MODULES_DIR" -l test_extlib_module -c "$3" } @@ -281,6 +285,162 @@ test_basic "twoArgs(hi, 3.0) [double→int in mixed]" "Result: twoArgs(hi, 3)" " fi # end basic group +# ═════════════════════════════════════════════════════════════════════════════ +# TEST GROUP 1b: test_basic_module_cpp (pure-C++ mirror of test_basic_module) +# +# Same method matrix as `basic` above, but the impl class uses std / LogosMap +# / LogosList / StdLogosResult — the Qt glue is auto-generated by +# `logos-cpp-generator --from-header`. These cases exercise every branch of +# the generator's type-conversion table end-to-end through the CLI; a +# regression in the glue (e.g. a missing `std::string` ↔ `QString` +# conversion, wrong `nlohmannToQVariant` behaviour, or broken `StdLogosResult` +# unpacking) shows up as a specific failing row here with the same output +# contract as its Qt counterpart. +# ═════════════════════════════════════════════════════════════════════════════ + +if should_run_group "basic-cpp"; then + +echo "" +echo "-----------------------------------------------------------------" +echo " test_basic_module_cpp (pure-C++ impl, generated Qt glue)" +echo "-----------------------------------------------------------------" + +# ── Return type: bool ──────────────────────────────────────────────────────── +echo "" +echo " -- Return type: bool --" +test_basic_cpp "returnTrue()" "Result: true" "test_basic_module_cpp.returnTrue()" +test_basic_cpp "returnFalse()" "Result: false" "test_basic_module_cpp.returnFalse()" +test_basic_cpp "isPositive(5)" "Result: true" "test_basic_module_cpp.isPositive(5)" +test_basic_cpp "isPositive(0)" "Result: false" "test_basic_module_cpp.isPositive(0)" +test_basic_cpp "isPositive(-3)" "Result: false" "test_basic_module_cpp.isPositive(-3)" + +# ── Return type: int64_t ───────────────────────────────────────────────────── +echo "" +echo " -- Return type: int64_t --" +test_basic_cpp "returnInt()" "Result: 42" "test_basic_module_cpp.returnInt()" +test_basic_cpp "addInts(3, 4)" "Result: 7" "test_basic_module_cpp.addInts(3, 4)" +test_basic_cpp "addInts(0, 0)" "Result: 0" "test_basic_module_cpp.addInts(0, 0)" +test_basic_cpp "addInts(-5, 10)" "Result: 5" "test_basic_module_cpp.addInts(-5, 10)" +test_basic_cpp "stringLength(hello)" "Result: 5" "test_basic_module_cpp.stringLength(hello)" +skip_test "stringLength()" "logoscore cannot call 1-arg method with 0 args" + +# ── Return type: uint64_t (unique to the C++ surface) ─────────────────────── +echo "" +echo " -- Return type: uint64_t --" +test_basic_cpp "returnUint()" "Result: 99" "test_basic_module_cpp.returnUint()" +test_basic_cpp "echoUint(123)" "Result: 123" "test_basic_module_cpp.echoUint(123)" +test_basic_cpp "echoUint(0)" "Result: 0" "test_basic_module_cpp.echoUint(0)" + +# ── Return type: double ───────────────────────────────────────────────────── +# CLI formats doubles unpredictably ("3.5" vs "3.500000"). Just check the +# dispatch exits cleanly and the "Result:" prefix is there — the Python +# integration suite covers exact-value assertions. +echo "" +echo " -- Return type: double --" +test_basic_cpp "returnDouble()" "Result:" "test_basic_module_cpp.returnDouble()" +test_basic_cpp "addDoubles(1.5, 2.5)" "Result:" "test_basic_module_cpp.addDoubles(1.5, 2.5)" + +# ── Return type: std::string ──────────────────────────────────────────────── +echo "" +echo " -- Return type: std::string --" +test_basic_cpp "returnString()" "Result: test_basic_module_cpp" "test_basic_module_cpp.returnString()" +test_basic_cpp "echo(hello)" "Result: hello" "test_basic_module_cpp.echo(hello)" +test_basic_cpp "echo(world)" "Result: world" "test_basic_module_cpp.echo(world)" +test_basic_cpp "concat(foo, bar)" "Result: foobar" "test_basic_module_cpp.concat(foo, bar)" +skip_test "concat(, )" "logoscore cannot pass empty args" + +# ── Return type: StdLogosResult ───────────────────────────────────────────── +# Generator emits a StdLogosResult → Qt LogosResult conversion in the glue, +# so the CLI's "Method call successful" sentinel (used for any structured +# return it can't stringify inline) fires identically to the Qt module. +echo "" +echo " -- Return type: StdLogosResult --" +test_basic_cpp "successResult()" "Method call successful" "test_basic_module_cpp.successResult()" +test_basic_cpp "errorResult()" "Method call successful" "test_basic_module_cpp.errorResult()" +test_basic_cpp "resultWithMap()" "Method call successful" "test_basic_module_cpp.resultWithMap()" +test_basic_cpp "resultWithList()" "Method call successful" "test_basic_module_cpp.resultWithList()" +test_basic_cpp "validateInput(hi)" "Method call successful" "test_basic_module_cpp.validateInput(hi)" + +# ── Return type: LogosMap (nlohmann::json object) ─────────────────────────── +# `jsonReturn=true` path: glue calls `nlohmannToQVariant` to produce a +# QVariantMap, which the CLI prints as structured JSON. +echo "" +echo " -- Return type: LogosMap --" +test_basic_cpp "returnMap()" "Method call successful" "test_basic_module_cpp.returnMap()" +test_basic_cpp "makeMap(hello, world)" "Method call successful" "test_basic_module_cpp.makeMap(hello, world)" + +# ── Return type: LogosList (nlohmann::json array) ─────────────────────────── +echo "" +echo " -- Return type: LogosList --" +test_basic_cpp "returnList()" "Method call successful" "test_basic_module_cpp.returnList()" +test_basic_cpp "makeList(x, y)" "Method call successful" "test_basic_module_cpp.makeList(x, y)" + +# ── Return type: std::vector ─────────────────────────────────── +echo "" +echo " -- Return type: std::vector --" +test_basic_cpp "returnStringList()" "Method call successful" "test_basic_module_cpp.returnStringList()" +skip_test "splitString(a,b,c)" "commas in arg value parsed as arg separators by logoscore" + +# ── Return type: std::vector ─────────────────────────────────────── +# CLI can't serialize bytes to stdout meaningfully (base64 / hex / raw is an +# encoding choice), and can't accept a vector literal as a CLI arg. +# Python integration suite exercises the round-trip through the actual wire. +echo "" +echo " -- Return type: std::vector --" +skip_test "returnBytes()" "CLI can't render std::vector" +test_basic_cpp "byteArraySize(12345)" "Result: 5" "test_basic_module_cpp.byteArraySize(12345)" + +# ── Parameter types ───────────────────────────────────────────────────────── +echo "" +echo " -- Parameter types --" +test_basic_cpp "echoInt(42)" "Result: 42" "test_basic_module_cpp.echoInt(42)" +test_basic_cpp "echoInt(0)" "Result: 0" "test_basic_module_cpp.echoInt(0)" +test_basic_cpp "echoInt(-7)" "Result: -7" "test_basic_module_cpp.echoInt(-7)" +test_basic_cpp "echoBool(true)" "Result: true" "test_basic_module_cpp.echoBool(true)" +test_basic_cpp "echoBool(false)" "Result: false" "test_basic_module_cpp.echoBool(false)" +skip_test "joinStrings(vector)" "logoscore cannot pass vector params" + +# ── Argument counts 0–5 ───────────────────────────────────────────────────── +# Format strings are produced by std::to_string (not QString::arg), but the +# expected output strings match the Qt module's bit-for-bit — the impl is +# careful to emit the same shape. +echo "" +echo " -- Argument counts 0-5 --" +test_basic_cpp "noArgs()" "Result: noArgs()" "test_basic_module_cpp.noArgs()" +test_basic_cpp "oneArg(x)" "Result: oneArg(x)" "test_basic_module_cpp.oneArg(x)" +test_basic_cpp "twoArgs(x, 1)" "Result: twoArgs(x, 1)" "test_basic_module_cpp.twoArgs(x, 1)" +test_basic_cpp "threeArgs(x, 1, true)" "Result: threeArgs(x, 1, true)" "test_basic_module_cpp.threeArgs(x, 1, true)" +test_basic_cpp "fourArgs(x, 1, true, y)" "Result: fourArgs(x, 1, true, y)" "test_basic_module_cpp.fourArgs(x, 1, true, y)" +test_basic_cpp "fiveArgs(x, 1, true, y, 2)" "Result: fiveArgs(x, 1, true, y, 2)" "test_basic_module_cpp.fiveArgs(x, 1, true, y, 2)" + +# ── Void methods ──────────────────────────────────────────────────────────── +echo "" +echo " -- Void methods (logoscore returns non-zero for void, testing no crash) --" +skip_test "doNothing()" "void return → invalid QVariant → logoscore exit 1" +skip_test "doNothingWithArgs(a,1)" "void return → invalid QVariant → logoscore exit 1" + +# ── Events ────────────────────────────────────────────────────────────────── +# The impl's `std::function emitEvent` is wired by the generator to the +# LogosProviderBase::emitEvent path. Same void-return limitation as the Qt +# module: fire-and-forget through the CLI produces exit 1. +echo "" +echo " -- Events --" +skip_test "emitTestEvent(data)" "void return → invalid QVariant → logoscore exit 1" +skip_test "emitMultiArgEvent(ev, 5)" "void return → invalid QVariant → logoscore exit 1" + +# ── Type coercion ─────────────────────────────────────────────────────────── +# Same logoscore-side coercion rules as the Qt module, but the receiving end +# is int64_t instead of int — the generator's std-to-Qt glue should still +# land on the same result after QVariant::convert. +echo "" +echo " -- Type coercion --" +test_basic_cpp "addInts(3.0, 4.0) [double→int64]" "Result: 7" "test_basic_module_cpp.addInts(3.0, 4.0)" +test_basic_cpp "echoInt(42.0) [double→int64]" "Result: 42" "test_basic_module_cpp.echoInt(42.0)" +test_basic_cpp "isPositive(5.0) [double→int64→bool]" "Result: true" "test_basic_module_cpp.isPositive(5.0)" +test_basic_cpp "twoArgs(hi, 3.0) [double→int64 mixed]" "Result: twoArgs(hi, 3)" "test_basic_module_cpp.twoArgs(hi, 3.0)" + +fi # end basic-cpp group + # ═════════════════════════════════════════════════════════════════════════════ # TEST GROUP 2: test_extlib_module (external C library wrapper) # ═════════════════════════════════════════════════════════════════════════════