Skip to content

Commit 97eeadb

Browse files
XiaochenCuiKernelDeimos
authored andcommitted
fs: fix failed tests in move and stat
1 parent f3b09cf commit 97eeadb

File tree

6 files changed

+149
-11
lines changed

6 files changed

+149
-11
lines changed

src/backend/src/filesystem/hl_operations/hl_move.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ class HLMove extends HLFilesystemOperation {
147147
if ( await dest.exists() ) {
148148
if ( ! values.overwrite && ! values.dedupe_name ) {
149149
throw APIError.create('item_with_same_name_exists', null, {
150-
entry_name: target_name,
150+
entry_name: await dest.get('name'),
151151
});
152152
}
153153

src/backend/src/filesystem/hl_operations/hl_stat.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ class HLStat extends HLFilesystemOperation {
5555

5656
if (return_size) await subject.fetchSize(user);
5757
if (return_subdomains) await subject.fetchSubdomains(user)
58-
if (return_permissions) await subject.fetchShares();
58+
if (return_permissions) {
59+
subject.entry.permissions = [];
60+
await subject.fetchShares();
61+
}
5962
if (return_versions) await subject.fetchVersions();
6063

6164
await subject.fetchIsEmpty();

tools/api-tester/README.md

Lines changed: 129 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,130 @@
1-
## It takes 3 steps to run the tests :)
1+
# API Tester
22

3-
1. run `npm install`
4-
2. copy `example_config.yml` and add the correct values
5-
3. run `node apitest.js --config=your_config_file.yml`
3+
A test framework for testing the backend API of puter.
4+
5+
## Table of Contents
6+
7+
- [API Tester](#api-tester)
8+
- [How to use](#how-to-use)
9+
- [Workflow](#workflow)
10+
- [Shorthands](#shorthands)
11+
- [Basic Concepts](#basic-concepts)
12+
- [Behaviors](#behaviors)
13+
- [Isolation of `t.cwd`](#isolation-of-t-cwd)
14+
- [Implementation](#implementation)
15+
- [TODO](#todo)
16+
17+
## How to use
18+
19+
### Workflow
20+
21+
All commands below should be run from the root directory of puter.
22+
23+
1. (Optional) Start a backend server:
24+
25+
```bash
26+
npm start
27+
```
28+
29+
2. Copy `example_config.yml` and add the correct values:
30+
31+
```bash
32+
cp ./tools/api-tester/example_config.yml ./tools/api-tester/config.yml
33+
```
34+
35+
Fields:
36+
- url: The endpoint of the backend server. (default: http://api.puter.localhost:4100/)
37+
- username: The username of the admin user. (e.g. admin)
38+
- token: The token of the user. (can be obtained by typing `puter.authToken` in Developer Tools's console)
39+
40+
3. Run the tests:
41+
42+
```bash
43+
node ./tools/api-tester/apitest.js --config=./tools/api-tester/config.yml
44+
```
45+
46+
### Shorthands
47+
48+
- Run unit tests only:
49+
50+
```bash
51+
node ./tools/api-tester/apitest.js --config=./tools/api-tester/config.yml --unit
52+
```
53+
54+
- Filter tests by suite name:
55+
56+
```bash
57+
node ./tools/api-tester/apitest.js --config=./tools/api-tester/config.yml --unit --suite=mkdir
58+
```
59+
60+
- Rerun failed tests in the last run:
61+
62+
```bash
63+
node ./tools/api-tester/apitest.js --config=./tools/api-tester/config.yml --rerun-failed
64+
```
65+
66+
## Basic Concepts
67+
68+
A *test case* is a function that tests a specific behavior of the backend API. Test cases can be nested:
69+
70+
```js
71+
await t.case('normal mkdir', async () => {
72+
const result = await t.mkdir_v2('foo');
73+
expect(result.name).equal('foo');
74+
75+
await t.case('can stat the created directory', async () => {
76+
const stat = await t.stat('foo');
77+
expect(stat.name).equal('foo');
78+
});
79+
});
80+
```
81+
82+
A *test suite* is a collection of test cases. A `.js` file should contain exactly one test suite.
83+
84+
```js
85+
module.exports = {
86+
name: 'mkdir',
87+
do: async t => {
88+
await t.case('normal mkdir', async () => {
89+
...
90+
});
91+
92+
await t.case('recursive mkdir', async () => {
93+
...
94+
});
95+
}
96+
};
97+
```
98+
99+
## Behaviors
100+
101+
### Isolation of `t.cwd`
102+
103+
- `t.cwd` is reset at the beginning of each test suite, since a test suite usually doesn't want to be affected by other test suites.
104+
- `t.cwd` will be inherited from the cases in the same test suite, since a leaf case might want to share the context with its parent/sibling cases.
105+
106+
```js
107+
module.exports = {
108+
name: 'readdir',
109+
do: async t => {
110+
// t.cwd is reset to /admin/api_test
111+
112+
await t.case('normal mkdir', async () => {
113+
// inherits cwd from parent/sibling cases
114+
115+
await t.case('mkdir in subdir', async () => {
116+
// inherits cwd from parent/sibling cases
117+
});
118+
});
119+
}
120+
};
121+
```
122+
123+
## Implementation
124+
125+
- Test suites are registered in `tools/api-tester/tests/__entry__.js`.
126+
127+
## TODO
128+
129+
- [ ] Update usage of apitest.js. (Is it possible to generate the usage automatically?)
130+
- [ ] Integrate it into CI, optionally running it only in specific scenarios (e.g., when backend code changes).

tools/api-tester/apitest.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const { parseArgs } = require('node:util');
99

1010
const args = process.argv.slice(2);
1111

12-
let config, report;
12+
let config, report, suiteName;
1313

1414
try {
1515
const parsed = parseArgs({
@@ -23,6 +23,7 @@ try {
2323
onlycase: { type: 'string' },
2424
bench: { type: 'boolean' },
2525
unit: { type: 'boolean' },
26+
suite: { type: 'string' },
2627
},
2728
allowPositionals: true,
2829
});
@@ -33,9 +34,12 @@ try {
3334
onlycase,
3435
bench,
3536
unit,
37+
suite: suiteName,
3638
}, positionals: [id] } = parsed);
3739

3840
onlycase = onlycase !== undefined ? Number.parseInt(onlycase) : undefined;
41+
// Ensure suiteName is a string or undefined
42+
suiteName = suiteName || undefined;
3943
} catch (e) {
4044
console.error(e);
4145
console.error(
@@ -44,6 +48,7 @@ try {
4448
'Options:\n' +
4549
' --config=<path> (required) Path to configuration file\n' +
4650
' --report=<path> (optional) Output file for full test results\n' +
51+
' --suite=<name> (optional) Run only tests with matching suite name\n' +
4752
''
4853
);
4954
process.exit(1);
@@ -56,6 +61,7 @@ const main = async () => {
5661
const context = {
5762
options: {
5863
onlycase,
64+
suite: suiteName,
5965
}
6066
};
6167
const ts = new TestSDK(conf, context);
@@ -87,7 +93,7 @@ const main = async () => {
8793
}
8894

8995
if ( unit ) {
90-
await registry.run_all_tests();
96+
await registry.run_all_tests(suiteName);
9197
} else if ( bench ) {
9298
await registry.run_all_benches();
9399
} else {

tools/api-tester/lib/TestRegistry.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@ module.exports = class TestRegistry {
1818
this.benches[id] = benchDefinition;
1919
}
2020

21-
async run_all_tests () {
21+
async run_all_tests(suiteName) {
2222
for ( const id in this.tests ) {
23+
if (suiteName && id !== suiteName) {
24+
continue;
25+
}
26+
2327
const testDefinition = this.tests[id];
2428
await this.t.runTestPackage(testDefinition);
2529
}

tools/api-tester/lib/TestSDK.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ module.exports = class TestSDK {
9696
async case (id, fn) {
9797
this.nameStack.push(id);
9898

99-
// Always reset cwd for top-level cases to prevent them from affecting
100-
// each other.
99+
// Always reset cwd at the beginning of a test suite to prevent it
100+
// from affected by others.
101101
if (this.nameStack.length === 1) {
102102
this.resetCwd();
103103
}

0 commit comments

Comments
 (0)