Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ jobs:
timeout-minutes: 35
run: |
source ../venv/bin/activate
BASILISK_REBUILD=true npx ts-node --transpile-only --ignore=false test.ts 2>&1 || {
npm test 2>&1 || {
echo "::error::Test failed for ${{ matrix.example_directories }}"
exit 1
}
Expand Down
2 changes: 1 addition & 1 deletion basilisk/compiler/cpython_canister_template/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ serde_json = "1.0"
async-recursion = "1.0.0"
ic-stable-structures = "0.5.2"
slotmap = "1.0.6"
ic-wasi-polyfill = { version = "0.6.1", features = ["transient"] }
ic-wasi-polyfill = { version = "0.6.1" }

[patch.crates-io]
num-bigint = { git = "https://github.com/rust-num/num-bigint" }
24 changes: 24 additions & 0 deletions examples/filesystem/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,27 @@ def test_fs_nested_mkdir() -> Vec[str]:
results.append(str(os.path.exists("/test_nested/a/b/c")))
results.append(str(os.path.isdir("/test_nested/a/b/c")))
return results


@update
def write_file(path: str, content: str) -> str:
"""Write content to a file. Returns 'OK' on success or error message."""
try:
parent = os.path.dirname(path)
if parent and parent != "/":
os.makedirs(parent, exist_ok=True)
with open(path, "w") as f:
f.write(content)
return "OK"
except Exception as e:
return f"ERROR: {e}"


@query
def read_file(path: str) -> str:
"""Read content from a file. Returns file content or error message."""
try:
with open(path, "r") as f:
return f.read()
except Exception as e:
return f"ERROR: {e}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
service : {
"test_fs_diagnostics" : () -> (vec text);
"test_fs_mkdir" : () -> (vec text);
"test_fs_path_exists" : () -> (vec text);
"test_fs_rename" : () -> (vec text);
"test_fs_rmdir" : () -> (vec text);
"test_fs_nested_mkdir" : () -> (vec text);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { Principal } from '@dfinity/principal';
import type { ActorMethod } from '@dfinity/agent';
import type { IDL } from '@dfinity/candid';

export interface _SERVICE {
'test_fs_diagnostics' : ActorMethod<[], Array<string>>,
'test_fs_mkdir' : ActorMethod<[], Array<string>>,
'test_fs_nested_mkdir' : ActorMethod<[], Array<string>>,
'test_fs_path_exists' : ActorMethod<[], Array<string>>,
'test_fs_rename' : ActorMethod<[], Array<string>>,
'test_fs_rmdir' : ActorMethod<[], Array<string>>,
}
export declare const idlFactory: IDL.InterfaceFactory;
export declare const init: (args: { IDL: typeof IDL }) => IDL.Type[];
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const idlFactory = ({ IDL }) => {
return IDL.Service({
'test_fs_diagnostics' : IDL.Func([], [IDL.Vec(IDL.Text)], []),
'test_fs_mkdir' : IDL.Func([], [IDL.Vec(IDL.Text)], []),
'test_fs_nested_mkdir' : IDL.Func([], [IDL.Vec(IDL.Text)], []),
'test_fs_path_exists' : IDL.Func([], [IDL.Vec(IDL.Text)], []),
'test_fs_rename' : IDL.Func([], [IDL.Vec(IDL.Text)], []),
'test_fs_rmdir' : IDL.Func([], [IDL.Vec(IDL.Text)], []),
});
};
export const init = ({ IDL }) => { return []; };
50 changes: 50 additions & 0 deletions examples/filesystem/test/dfx_generated/filesystem/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type {
ActorSubclass,
HttpAgentOptions,
ActorConfig,
Agent,
} from "@dfinity/agent";
import type { Principal } from "@dfinity/principal";
import type { IDL } from "@dfinity/candid";

import { _SERVICE } from './filesystem.did';

export declare const idlFactory: IDL.InterfaceFactory;
export declare const canisterId: string;

export declare interface CreateActorOptions {
/**
* @see {@link Agent}
*/
agent?: Agent;
/**
* @see {@link HttpAgentOptions}
*/
agentOptions?: HttpAgentOptions;
/**
* @see {@link ActorConfig}
*/
actorOptions?: ActorConfig;
}

/**
* Intializes an {@link ActorSubclass}, configured with the provided SERVICE interface of a canister.
* @constructs {@link ActorSubClass}
* @param {string | Principal} canisterId - ID of the canister the {@link Actor} will talk to
* @param {CreateActorOptions} options - see {@link CreateActorOptions}
* @param {CreateActorOptions["agent"]} options.agent - a pre-configured agent you'd like to use. Supercedes agentOptions
* @param {CreateActorOptions["agentOptions"]} options.agentOptions - options to set up a new agent
* @see {@link HttpAgentOptions}
* @param {CreateActorOptions["actorOptions"]} options.actorOptions - options for the Actor
* @see {@link ActorConfig}
*/
export declare const createActor: (
canisterId: string | Principal,
options?: CreateActorOptions
) => ActorSubclass<_SERVICE>;

/**
* Intialized Actor using default settings, ready to talk to a canister using its candid interface
* @constructs {@link ActorSubClass}
*/
export declare const filesystem: ActorSubclass<_SERVICE>;
40 changes: 40 additions & 0 deletions examples/filesystem/test/dfx_generated/filesystem/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Actor, HttpAgent } from "@dfinity/agent";

// Imports and re-exports candid interface
import { idlFactory } from "./filesystem.did.js";
export { idlFactory } from "./filesystem.did.js";

/* CANISTER_ID is replaced by webpack based on node environment
* Note: canister environment variable will be standardized as
* process.env.CANISTER_ID_<CANISTER_NAME_UPPERCASE>
* beginning in dfx 0.15.0
*/
export const canisterId =
process.env.CANISTER_ID_FILESYSTEM;

export const createActor = (canisterId, options = {}) => {
const agent = options.agent || new HttpAgent({ ...options.agentOptions });

if (options.agent && options.agentOptions) {
console.warn(
"Detected both agent and agentOptions passed to createActor. Ignoring agentOptions and proceeding with the provided agent."
);
}

// Fetch root key for certificate validation during development
if (process.env.DFX_NETWORK !== "ic") {
agent.fetchRootKey().catch((err) => {
console.warn(
"Unable to fetch root key. Check to ensure that your local replica is running"
);
console.error(err);
});
}

// Creates an actor with using the candid interface and the HttpAgent
return Actor.createActor(idlFactory, {
agent,
canisterId,
...options.actorOptions,
});
};
18 changes: 12 additions & 6 deletions examples/filesystem/test/test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { getCanisterId, runTests } from 'azle/test';
import { createActor } from './dfx_generated/filesystem';
import { getTests } from './tests';
import { HttpAgent } from '@dfinity/agent';

const filesystemCanister = createActor(getCanisterId('filesystem'), {
agentOptions: {
host: 'http://127.0.0.1:8000'
}
});
async function main() {
const agent = new HttpAgent({ host: 'http://127.0.0.1:8000' });
await agent.fetchRootKey();

runTests(getTests(filesystemCanister));
const filesystemCanister = createActor(getCanisterId('filesystem'), {
agent
});

runTests(getTests(filesystemCanister));
}

main();
49 changes: 49 additions & 0 deletions examples/filesystem/test/tests.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Test } from 'azle/test';
import { _SERVICE } from './dfx_generated/filesystem/filesystem.did';
import { ActorSubclass } from '@dfinity/agent';
import { execSync } from 'child_process';

export function getTests(actor: ActorSubclass<_SERVICE>): Test[] {
return [
Expand Down Expand Up @@ -76,6 +77,54 @@ export function getTests(actor: ActorSubclass<_SERVICE>): Test[] {
Ok: result.every((v: string) => v === 'True')
};
}
},
{
name: 'test_fs_persistence: write file before upgrade',
test: async () => {
const result = await actor.write_file(
'/persist_test/hello.txt',
'Hello from before upgrade!'
);
console.log('write_file result:', result);
return {
Ok: result === 'OK'
};
}
},
{
name: 'test_fs_persistence: verify file readable before upgrade',
test: async () => {
const result = await actor.read_file('/persist_test/hello.txt');
console.log('read_file before upgrade:', result);
return {
Ok: result === 'Hello from before upgrade!'
};
}
},
{
name: 'test_fs_persistence: upgrade canister',
test: async () => {
try {
execSync(
`dfx deploy filesystem --upgrade-unchanged`,
{ stdio: 'inherit' }
);
return { Ok: true };
} catch (e) {
console.error('upgrade failed:', e);
return { Ok: false };
}
}
},
{
name: 'test_fs_persistence: read file after upgrade',
test: async () => {
const result = await actor.read_file('/persist_test/hello.txt');
console.log('read_file after upgrade:', result);
return {
Ok: result === 'Hello from before upgrade!'
};
}
}
];
}
Loading