Skip to content

Commit d6fa20b

Browse files
authored
[feat]: handle non-existing directories as empty if they have a meta file (#2999)
* add failing tests * fix unused import * now test should fail due to missing meta * fix tests now * also add a negative test * fix neg test
1 parent f005b73 commit d6fa20b

File tree

2 files changed

+44
-9
lines changed

2 files changed

+44
-9
lines changed

packages/controller/test/lib/testFiles.ts

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { TestContext } from '../_Types.js';
2-
import { objectsUtils as utils } from '@iobroker/db-objects-redis';
32

43
export function register(it: Mocha.TestFunction, expect: Chai.ExpectStatic, context: TestContext): void {
54
const testName = `${context.name} ${context.adapterShortName} files: `;
@@ -10,7 +9,7 @@ export function register(it: Mocha.TestFunction, expect: Chai.ExpectStatic, cont
109
const fileName = 'testFile.bin';
1110
const dataBinary = Buffer.from('1234');
1211
// create an object of type file first
13-
await context.adapter.setForeignObjectAsync(objId, {
12+
await context.adapter.setForeignObject(objId, {
1413
type: 'meta',
1514
common: {
1615
name: 'Files and more',
@@ -224,12 +223,42 @@ export function register(it: Mocha.TestFunction, expect: Chai.ExpectStatic, cont
224223
});
225224
});
226225

227-
it(`${testName}should respond with 'ERROR_NOT_FOUND' if calling readDir on a single file`, async () => {
226+
it(`${testName}should read empty directory`, async () => {
227+
const objects = context.objects;
228+
const id = `${testId}.meta.files`;
229+
230+
await objects.setObject(id, {
231+
type: 'meta',
232+
common: { name: 'test', type: 'meta.user' },
233+
native: {},
234+
});
235+
236+
const res = await objects.readDirAsync(id, '');
237+
expect(res).to.be.empty;
238+
});
239+
240+
it(`${testName}should read empty directory with path`, async () => {
241+
const objects = context.objects;
242+
const id = `${testId}.meta.files`;
243+
244+
const res = await objects.readDirAsync(id, 'random/path');
245+
expect(res).to.be.empty;
246+
});
247+
248+
it(`${testName}should not read directory without meta object`, () => {
249+
const objects = context.objects;
250+
const id = `${testId}.meta.nonExisting`;
251+
252+
expect(objects.readDirAsync(id, '')).to.be.eventually.rejectedWith(`${id} is not an object of type "meta"`);
253+
});
254+
255+
it(`${testName}should respond with empty array if calling readDir on a single file`, async () => {
228256
const objects = context.objects;
229257
const fileName = 'dir/notADir.txt';
230258

231259
await objects.writeFileAsync(testId, fileName, 'dataInFile');
232-
expect(objects.readDirAsync(testId, fileName)).to.be.eventually.rejectedWith(utils.ERRORS.ERROR_NOT_FOUND);
260+
const res = await objects.readDirAsync(testId, fileName);
261+
expect(res).to.be.empty;
233262
});
234263

235264
it(`${testName}should read file and prevent path traversing`, done => {

packages/db-objects-redis/src/lib/objects/objectsInRedisClient.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -847,15 +847,15 @@ export class ObjectsInRedisClient {
847847
async validateMetaObject(id: string): Promise<void> {
848848
if (this.existingMetaObjects[id] === undefined) {
849849
// if not cached -> getObject
850-
const obj = await this.getObjectAsync(id);
850+
const obj = await this.getObject(id);
851851
if (obj && obj.type === 'meta') {
852852
this.existingMetaObjects[id] = true;
853853
} else {
854854
this.existingMetaObjects[id] = false;
855-
return Promise.reject(new Error(`${id} is not an object of type "meta"`));
855+
throw new Error(`${id} is not an object of type "meta"`);
856856
}
857857
} else if (this.existingMetaObjects[id] === false) {
858-
return Promise.reject(new Error(`${id} is not an object of type "meta"`));
858+
throw new Error(`${id} is not an object of type "meta"`);
859859
}
860860
}
861861

@@ -990,7 +990,7 @@ export class ObjectsInRedisClient {
990990
const obj = await this.getObject(id);
991991
if (obj && !obj.acl) {
992992
obj.acl = defaultAcl;
993-
await this.setObjectAsync(id, obj, null);
993+
await this.setObject(id, obj, null);
994994
}
995995
} catch (e) {
996996
this.log.error(
@@ -1442,6 +1442,12 @@ export class ObjectsInRedisClient {
14421442
return tools.maybeCallbackWithError(callback, null, result);
14431443
}
14441444

1445+
try {
1446+
await this.validateMetaObject(id);
1447+
} catch (e) {
1448+
return tools.maybeCallbackWithRedisError(callback, e);
1449+
}
1450+
14451451
const dirID = this.getFileId(id, `${name}${name.length ? '/' : ''}*`);
14461452

14471453
let keys;
@@ -1462,7 +1468,7 @@ export class ObjectsInRedisClient {
14621468
const dirs: string[] = [];
14631469
const deepLevel = baseName.split('/').length;
14641470
if (!keys || !keys.length) {
1465-
return tools.maybeCallbackWithError(callback, ERRORS.ERROR_NOT_FOUND, []);
1471+
return tools.maybeCallbackWithError(callback, null, []);
14661472
}
14671473
keys = keys.sort().filter(key => {
14681474
if (key.endsWith('$%$meta')) {

0 commit comments

Comments
 (0)