diff --git a/lib/Resource.js b/lib/Resource.js index 860b68e6..3d38fd55 100644 --- a/lib/Resource.js +++ b/lib/Resource.js @@ -70,11 +70,14 @@ class Resource { birthtime: new Date() }; - this._createStream = createStream || null; - this._stream = stream || null; - this._buffer = buffer || null; - if (typeof string === "string" || string instanceof String) { - this._buffer = Buffer.from(string, "utf8"); + if (createStream) { + this._createStream = createStream; + } else if (stream) { + this._stream = stream; + } else if (buffer) { + this.setBuffer(buffer); + } else if (typeof string === "string" || string instanceof String) { + this.setString(string); } // Tracing: @@ -117,6 +120,7 @@ class Resource { this._buffer = buffer; this._contentDrained = false; this._streamDrained = false; + this._setSize(this._buffer.byteLength); } /** @@ -207,6 +211,17 @@ 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 * diff --git a/test/lib/Resource.js b/test/lib/Resource.js index c2400601..fef77d1e 100644 --- a/test/lib/Resource.js +++ b/test/lib/Resource.js @@ -2,6 +2,8 @@ const test = require("ava"); const Stream = require("stream"); const fs = require("fs"); const path = require("path"); +const {promisify} = require("util"); +const stat = promisify(fs.stat); const Resource = require("../../lib/Resource"); function createBasicResource() { @@ -142,6 +144,58 @@ test("Resource: setString", (t) => { }); }); +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"); + + // string + resource.setString("Content"); + + t.is(resource.getStatInfo().size, 7, "size after manually setting the string"); + t.is(new Resource({ + path: "my/path/to/resource", + string: "Content" + }).getStatInfo().size, 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"); + + const clonedResource1 = await resource.clone(); + t.is(clonedResource1.getStatInfo().size, 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({ + path: "my/path/to/resource", + buffer: buf + }).getStatInfo().size, 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); + + const resource = new Resource({ + path: "my/path/to/resource" + }); + + resource._setSize(1337); + + t.is(resource.getStatInfo().size, 1337); +}); + test("Resource: setStream", (t) => { t.plan(1); @@ -267,3 +321,24 @@ test("getBuffer from Stream content: Subsequent content requests should not thro // to throw "Content stream of Resource /app/index.html is flagged as drained." await t.notThrowsAsync(p2); }); + +test("integration stat - resource size", async (t) => { + const fsPath = path.join("test", "fixtures", "application.a", "webapp", "index.html"); + const statInfo = await stat(fsPath); + + const resource = new Resource({ + path: fsPath, + statInfo, + createStream: () => { + return fs.createReadStream(fsPath); + } + }); + t.is(resource.getStatInfo().size, 91); + + // Setting the same content again should end up with the same size + resource.setString(await resource.getString()); + t.is(resource.getStatInfo().size, 91); + + resource.setString("myvalue"); + t.is(resource.getStatInfo().size, 7); +});