@@ -2,7 +2,13 @@ import { describe, expect, test } from 'bun:test'
22import { existsSync , mkdirSync , mkdtempSync , readFileSync , rmSync , writeFileSync } from 'node:fs'
33import { tmpdir } from 'node:os'
44import { join } from 'node:path'
5- import { generateHostCrate , readCrateName , resolveExtensions } from './generate-host-crate'
5+ import {
6+ generateHostCrate ,
7+ parseToolchainVersion ,
8+ readCrateName ,
9+ resolveExtensions ,
10+ resolveToolchain ,
11+ } from './generate-host-crate'
612
713describe ( 'generate-host-crate' , ( ) => {
814 describe ( 'readCrateName' , ( ) => {
@@ -49,12 +55,119 @@ describe('generate-host-crate', () => {
4955 } )
5056 } )
5157
58+ describe ( 'parseToolchainVersion' , ( ) => {
59+ test ( 'parses semver channel from rust-toolchain.toml' , ( ) => {
60+ const tmp = mkdtempSync ( join ( tmpdir ( ) , 'cre-tc-' ) )
61+ try {
62+ writeFileSync (
63+ join ( tmp , 'rust-toolchain.toml' ) ,
64+ '[toolchain]\nchannel = "1.85.0"\ntargets = ["wasm32-wasip1"]\n' ,
65+ )
66+ expect ( parseToolchainVersion ( join ( tmp , 'rust-toolchain.toml' ) ) ) . toEqual ( [ 1 , 85 , 0 ] )
67+ } finally {
68+ rmSync ( tmp , { recursive : true } )
69+ }
70+ } )
71+
72+ test ( 'returns null for non-semver channel (nightly)' , ( ) => {
73+ const tmp = mkdtempSync ( join ( tmpdir ( ) , 'cre-tc-' ) )
74+ try {
75+ writeFileSync (
76+ join ( tmp , 'rust-toolchain.toml' ) ,
77+ '[toolchain]\nchannel = "nightly-2024-01-01"\n' ,
78+ )
79+ expect ( parseToolchainVersion ( join ( tmp , 'rust-toolchain.toml' ) ) ) . toBeNull ( )
80+ } finally {
81+ rmSync ( tmp , { recursive : true } )
82+ }
83+ } )
84+
85+ test ( 'returns null for missing file' , ( ) => {
86+ expect ( parseToolchainVersion ( '/nonexistent/rust-toolchain.toml' ) ) . toBeNull ( )
87+ } )
88+ } )
89+
90+ describe ( 'resolveToolchain' , ( ) => {
91+ test ( 'uses SDK version when no extensions have toolchain files' , ( ) => {
92+ const sdkDir = mkdtempSync ( join ( tmpdir ( ) , 'cre-sdk-' ) )
93+ try {
94+ writeFileSync (
95+ join ( sdkDir , 'rust-toolchain.toml' ) ,
96+ '[toolchain]\nchannel = "1.85.0"\ntargets = ["wasm32-wasip1"]\n' ,
97+ )
98+ const result = resolveToolchain ( join ( sdkDir , 'rust-toolchain.toml' ) , [ ] )
99+ expect ( result ) . toContain ( 'channel = "1.85.0"' )
100+ expect ( result ) . toContain ( 'wasm32-wasip1' )
101+ } finally {
102+ rmSync ( sdkDir , { recursive : true } )
103+ }
104+ } )
105+
106+ test ( 'picks higher extension version over SDK' , ( ) => {
107+ const sdkDir = mkdtempSync ( join ( tmpdir ( ) , 'cre-sdk-' ) )
108+ const extDir = mkdtempSync ( join ( tmpdir ( ) , 'cre-ext-' ) )
109+ try {
110+ writeFileSync ( join ( sdkDir , 'rust-toolchain.toml' ) , '[toolchain]\nchannel = "1.85.0"\n' )
111+ writeFileSync ( join ( extDir , 'rust-toolchain.toml' ) , '[toolchain]\nchannel = "1.87.0"\n' )
112+ const result = resolveToolchain ( join ( sdkDir , 'rust-toolchain.toml' ) , [
113+ { crateName : 'ext' , path : extDir } ,
114+ ] )
115+ expect ( result ) . toContain ( 'channel = "1.87.0"' )
116+ } finally {
117+ rmSync ( sdkDir , { recursive : true } )
118+ rmSync ( extDir , { recursive : true } )
119+ }
120+ } )
121+
122+ test ( 'keeps SDK version when extension is older' , ( ) => {
123+ const sdkDir = mkdtempSync ( join ( tmpdir ( ) , 'cre-sdk-' ) )
124+ const extDir = mkdtempSync ( join ( tmpdir ( ) , 'cre-ext-' ) )
125+ try {
126+ writeFileSync ( join ( sdkDir , 'rust-toolchain.toml' ) , '[toolchain]\nchannel = "1.85.0"\n' )
127+ writeFileSync ( join ( extDir , 'rust-toolchain.toml' ) , '[toolchain]\nchannel = "1.80.0"\n' )
128+ const result = resolveToolchain ( join ( sdkDir , 'rust-toolchain.toml' ) , [
129+ { crateName : 'ext' , path : extDir } ,
130+ ] )
131+ expect ( result ) . toContain ( 'channel = "1.85.0"' )
132+ } finally {
133+ rmSync ( sdkDir , { recursive : true } )
134+ rmSync ( extDir , { recursive : true } )
135+ }
136+ } )
137+
138+ test ( 'ignores extensions with nightly channel' , ( ) => {
139+ const sdkDir = mkdtempSync ( join ( tmpdir ( ) , 'cre-sdk-' ) )
140+ const extDir = mkdtempSync ( join ( tmpdir ( ) , 'cre-ext-' ) )
141+ try {
142+ writeFileSync ( join ( sdkDir , 'rust-toolchain.toml' ) , '[toolchain]\nchannel = "1.85.0"\n' )
143+ writeFileSync ( join ( extDir , 'rust-toolchain.toml' ) , '[toolchain]\nchannel = "nightly"\n' )
144+ const result = resolveToolchain ( join ( sdkDir , 'rust-toolchain.toml' ) , [
145+ { crateName : 'ext' , path : extDir } ,
146+ ] )
147+ expect ( result ) . toContain ( 'channel = "1.85.0"' )
148+ } finally {
149+ rmSync ( sdkDir , { recursive : true } )
150+ rmSync ( extDir , { recursive : true } )
151+ }
152+ } )
153+ } )
154+
52155 describe ( 'generateHostCrate' , ( ) => {
53- test ( 'requires at least one extension ' , ( ) => {
156+ test ( 'generates host crate with zero extensions (standalone) ' , ( ) => {
54157 const outDir = mkdtempSync ( join ( tmpdir ( ) , 'cre-host-' ) )
55158 const pluginDir = join ( import . meta. dir , '..' )
56159 try {
57- expect ( ( ) => generateHostCrate ( outDir , pluginDir , [ ] ) ) . toThrow ( / a t l e a s t o n e - - c r e - e x p o r t s / )
160+ generateHostCrate ( outDir , pluginDir , [ ] )
161+ const cargo = readFileSync ( join ( outDir , 'Cargo.toml' ) , 'utf8' )
162+ expect ( cargo ) . toContain ( 'name = "cre_generated_host"' )
163+ expect ( cargo ) . toContain ( 'crate-type = ["cdylib"]' )
164+ expect ( cargo ) . toContain ( 'javy_chainlink_sdk = { path' )
165+ expect ( cargo ) . not . toContain ( 'cre_wasm_exports' )
166+ const libRs = readFileSync ( join ( outDir , 'src' , 'lib.rs' ) , 'utf8' )
167+ expect ( libRs ) . toContain ( 'javy_chainlink_sdk::config' )
168+ expect ( libRs ) . toContain ( 'javy_chainlink_sdk::modify_runtime' )
169+ expect ( libRs ) . not . toContain ( 'register' )
170+ expect ( libRs ) . not . toContain ( 'context().with' )
58171 } finally {
59172 rmSync ( outDir , { recursive : true } )
60173 }
@@ -94,7 +207,7 @@ describe('generate-host-crate', () => {
94207 }
95208 } )
96209
97- test ( 'Cargo.toml uses path deps for javy_chainlink_sdk, cre_wasm_exports, and extensions' , ( ) => {
210+ test ( 'Cargo.toml uses path deps for javy_chainlink_sdk and extensions' , ( ) => {
98211 const outDir = mkdtempSync ( join ( tmpdir ( ) , 'cre-host-' ) )
99212 const pluginDir = join ( import . meta. dir , '..' )
100213 const examplesDir = join ( pluginDir , '..' , 'cre-sdk-examples' , 'rust-inject' )
@@ -110,38 +223,67 @@ describe('generate-host-crate', () => {
110223 expect ( cargo ) . toContain ( 'javy-plugin-api = "6.0.0"' )
111224 expect ( cargo ) . toContain ( 'javy = "7.0.0"' )
112225 expect ( cargo ) . toContain ( 'javy_chainlink_sdk = { path' )
113- expect ( cargo ) . toContain ( 'cre_wasm_exports = { path' )
114226 expect ( cargo ) . toContain ( 'alpha = { path' )
115227 expect ( cargo ) . toContain ( 'lib_beta = { path' )
116228 const libRs = readFileSync ( join ( outDir , 'src' , 'lib.rs' ) , 'utf8' )
117229 expect ( libRs ) . toContain ( 'alpha::register' )
118230 expect ( libRs ) . toContain ( 'lib_beta::register' )
119- expect ( libRs ) . toContain ( 'cre_wasm_exports::reset_registry' )
120- expect ( libRs ) . toContain ( 'cre_wasm_exports::check_duplicates' )
121231 expect ( libRs ) . toContain ( 'javy_chainlink_sdk::config' )
122232 expect ( libRs ) . toContain ( 'javy_chainlink_sdk::modify_runtime' )
123233 } finally {
124234 rmSync ( outDir , { recursive : true } )
125235 }
126236 } )
127237
128- test ( 'copies rust-toolchain.toml into generated crate' , ( ) => {
238+ test ( 'writes rust-toolchain.toml with resolved version' , ( ) => {
239+ const outDir = mkdtempSync ( join ( tmpdir ( ) , 'cre-host-' ) )
240+ const pluginDir = join ( import . meta. dir , '..' )
241+ try {
242+ generateHostCrate ( outDir , pluginDir , [ ] )
243+ const toolchainPath = join ( outDir , 'rust-toolchain.toml' )
244+ expect ( existsSync ( toolchainPath ) ) . toBe ( true )
245+ const content = readFileSync ( toolchainPath , 'utf8' )
246+ expect ( content ) . toContain ( 'wasm32-wasip1' )
247+ expect ( content ) . toMatch ( / c h a n n e l = " \d + \. \d + \. \d + " / )
248+ } finally {
249+ rmSync ( outDir , { recursive : true } )
250+ }
251+ } )
252+
253+ test ( 'rust-toolchain.toml picks higher extension version' , ( ) => {
129254 const outDir = mkdtempSync ( join ( tmpdir ( ) , 'cre-host-' ) )
130255 const extDir = mkdtempSync ( join ( tmpdir ( ) , 'cre-ext-' ) )
131256 const pluginDir = join ( import . meta. dir , '..' )
132257 try {
133258 writeFileSync (
134259 join ( extDir , 'Cargo.toml' ) ,
135- '[package]\nname = "toolchain_ext "\nversion = "0.1.0"' ,
260+ '[package]\nname = "newer_ext "\nversion = "0.1.0"' ,
136261 )
137262 mkdirSync ( join ( extDir , 'src' ) )
138263 writeFileSync ( join ( extDir , 'src' , 'lib.rs' ) , 'pub fn register(_ctx: &()) {}' )
139- const extensions = [ { crateName : 'toolchain_ext' , path : extDir } ]
264+ writeFileSync ( join ( extDir , 'rust-toolchain.toml' ) , '[toolchain]\nchannel = "1.99.0"\n' )
265+ const extensions = [ { crateName : 'newer_ext' , path : extDir } ]
140266 generateHostCrate ( outDir , pluginDir , extensions )
141- const toolchainPath = join ( outDir , 'rust-toolchain.toml' )
142- expect ( existsSync ( toolchainPath ) ) . toBe ( true )
143- const content = readFileSync ( toolchainPath , 'utf8' )
144- expect ( content ) . toContain ( 'wasm32-wasip1' )
267+ const content = readFileSync ( join ( outDir , 'rust-toolchain.toml' ) , 'utf8' )
268+ expect ( content ) . toContain ( 'channel = "1.99.0"' )
269+ } finally {
270+ rmSync ( outDir , { recursive : true } )
271+ rmSync ( extDir , { recursive : true } )
272+ }
273+ } )
274+
275+ test ( 'Cargo.toml does not use default-features = false' , ( ) => {
276+ const outDir = mkdtempSync ( join ( tmpdir ( ) , 'cre-host-' ) )
277+ const extDir = mkdtempSync ( join ( tmpdir ( ) , 'cre-ext-' ) )
278+ const pluginDir = join ( import . meta. dir , '..' )
279+ try {
280+ writeFileSync ( join ( extDir , 'Cargo.toml' ) , '[package]\nname = "test_ext"\nversion = "0.1.0"' )
281+ mkdirSync ( join ( extDir , 'src' ) )
282+ writeFileSync ( join ( extDir , 'src' , 'lib.rs' ) , 'pub fn register(_ctx: &()) {}' )
283+ const extensions = [ { crateName : 'test_ext' , path : extDir } ]
284+ generateHostCrate ( outDir , pluginDir , extensions )
285+ const cargo = readFileSync ( join ( outDir , 'Cargo.toml' ) , 'utf8' )
286+ expect ( cargo ) . not . toContain ( 'default-features' )
145287 } finally {
146288 rmSync ( outDir , { recursive : true } )
147289 rmSync ( extDir , { recursive : true } )
0 commit comments