Skip to content

Commit

Permalink
[FIX] Resource#getSize: Retrieve Resource's size (#256)
Browse files Browse the repository at this point in the history
Stats.size was not set for a stream.
To ensure Resource's size can be retrieved for:
* stream
* string
* buffer
async method is introduced which uses #getBuffer to
ensure that size retrieval works for all content types.

followup of #253
  • Loading branch information
tobiasso85 authored Jul 13, 2020
1 parent 32edead commit 9d2cc6c
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 33 deletions.
27 changes: 15 additions & 12 deletions lib/Resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ class Resource {
this._buffer = buffer;
this._contentDrained = false;
this._streamDrained = false;
this._setSize(this._buffer.byteLength);
}

/**
Expand Down Expand Up @@ -211,17 +210,6 @@ class Resource {
this._streamDrained = false;
}

/**
* Set the size in bytes
*
* @param {number} size byte size
* @private
* @see https://nodejs.org/api/fs.html#fs_stats_size
*/
_setSize(size) {
this._statInfo.size = size;
}

/**
* Gets the resources path
*
Expand Down Expand Up @@ -254,6 +242,21 @@ class Resource {
return this._statInfo;
}

/**
* Size in bytes allocated by the underlying buffer.
*
* @see {TypedArray#byteLength}
* @returns {Promise<number>} size in bytes, <code>0</code> if there is no content yet
*/
async getSize() {
// if resource does not have any content it should have 0 bytes
if (!this._buffer && !this._createStream && !this._stream) {
return 0;
}
const buffer = await this.getBuffer();
return buffer.byteLength;
}

_getNameFromPath(virPath) {
return path.posix.basename(virPath);
}
Expand Down
50 changes: 29 additions & 21 deletions test/lib/Resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,52 +148,60 @@ test("Resource: size modification", async (t) => {
const resource = new Resource({
path: "my/path/to/resource"
});
t.falsy(resource.getStatInfo().size, "initial size is not defined");
t.is(await resource.getSize(), 0, "initial size without content");

// string
resource.setString("Content");

t.is(resource.getStatInfo().size, 7, "size after manually setting the string");
t.is(new Resource({
t.is(await resource.getSize(), 7, "size after manually setting the string");
t.is(await new Resource({
path: "my/path/to/resource",
string: "Content"
}).getStatInfo().size, 7, "size when passing string to constructor");
}).getSize(), 7, "size when passing string to constructor");


// buffer
resource.setBuffer(Buffer.from("Super"));

t.is(resource.getStatInfo().size, 5, "size after manually setting the string");
t.is(await resource.getSize(), 5, "size after manually setting the string");

const clonedResource1 = await resource.clone();
t.is(clonedResource1.getStatInfo().size, 5, "size after cloning the resource");
t.is(await clonedResource1.getSize(), 5, "size after cloning the resource");


// buffer with alloc
const buf = Buffer.alloc(1234);
buf.write("some string", 0, "utf8");
resource.setBuffer(buf);

t.is(resource.getStatInfo().size, 1234, "buffer with alloc after setting the buffer");
t.is(new Resource({
t.is(await resource.getSize(), 1234, "buffer with alloc after setting the buffer");
t.is(await new Resource({
path: "my/path/to/resource",
buffer: buf
}).getStatInfo().size, 1234, "buffer with alloc when passing buffer to constructor");
}).getSize(), 1234, "buffer with alloc when passing buffer to constructor");

const clonedResource2 = await resource.clone();
t.is(clonedResource2.getStatInfo().size, 1234, "buffer with alloc atfer clone");
});

test("Resource: _setSize", (t) => {
t.plan(1);
t.is(await clonedResource2.getSize(), 1234, "buffer with alloc after clone");

const resource = new Resource({
path: "my/path/to/resource"
// stream
const streamResource = new Resource({
path: "my/path/to/resource",
});
const stream = new Stream.Readable();
stream._read = function() {};
stream.push("I am a ");
stream.push("readable ");
stream.push("stream!");
stream.push(null);

resource._setSize(1337);
streamResource.setStream(stream);

t.is(resource.getStatInfo().size, 1337);
// stream is read and stored in buffer
// test parallel size retrieval
const [size1, size2] = await Promise.all([streamResource.getSize(), streamResource.getSize()]);
t.is(size1, 23, "size for streamResource, parallel 1");
t.is(size2, 23, "size for streamResource, parallel 2");
t.is(await streamResource.getSize(), 23, "size for streamResource read again");
});

test("Resource: setStream", (t) => {
Expand Down Expand Up @@ -333,12 +341,12 @@ test("integration stat - resource size", async (t) => {
return fs.createReadStream(fsPath);
}
});
t.is(resource.getStatInfo().size, 91);
t.is(await resource.getSize(), 91);

// Setting the same content again should end up with the same size
resource.setString(await resource.getString());
t.is(resource.getStatInfo().size, 91);
t.is(await resource.getSize(), 91);

resource.setString("myvalue");
t.is(resource.getStatInfo().size, 7);
t.is(await resource.getSize(), 7);
});

0 comments on commit 9d2cc6c

Please sign in to comment.