hellboy
hellboy

Reputation: 1618

How to check if two files have the same content?

I am using mocha/supertest/should.js to test REST Service

GET /files/<hash> returns file as stream.

How can I assert in should.js that file contents are the same?

it('should return file as stream', function (done) {
    var writeStream = fs.createWriteStream('test/fixtures/tmp.json');
    
    var req = api.get('/files/676dfg1430af3595');
    req.on('end', function(){
       var tmpBuf = fs.readFileSync('test/fixtures/tmp.json');
       var testBuf = fs.readFileSync('test/fixtures/test.json');
    
       // How to assert with should.js file contents are the same (tmpBuf == testBuf )
       // ...
    
       done();
    });
});

Upvotes: 40

Views: 41153

Answers (6)

ChesuCR
ChesuCR

Reputation: 9670

I think that you should use non-blocking calls in JavaScript to get a better performance, at least to prevent from blocking other operations:

Blocking is when the execution of additional JavaScript in the Node.js process must wait until a non-JavaScript operation completes. This happens because the event loop is unable to continue running JavaScript while a blocking operation is occurring.

In Node.js, JavaScript that exhibits poor performance due to being CPU intensive rather than waiting on a non-JavaScript operation, such as I/O, isn't typically referred to as blocking. Synchronous methods in the Node.js standard library that use libuv are the most commonly used blocking operations. Native modules may also have blocking methods.

So, I would change the Sync calls with something like the following code. Also, I would use the method equals that Max suggest to compare both files:

const fs = require('fs')

fs.readFile('file1', (err, data1) => {
    if (err) throw err;
    fs.readFile('file2', (err, data2) => {
        if (err) throw err;
        if (data1.equals(data2)) {
            console.log('EQUAL')
        } else {
            console.log('NON EQUAL')
        }

    });
});

Though for a small and a single script the result would be almost the same

Upvotes: 1

Max
Max

Reputation: 1435

Surprisingly, no one has suggested Buffer.equals. That seems to be the fastest and simplest approach and has been around since v0.11.

So your code would become tmpBuf.equals(testBuf)

Upvotes: 55

smoebody
smoebody

Reputation: 648

for comparing large files e.g. images when asserting file uploads a comparison of buffers or strings with should.eql takes ages. i recommend asserting the buffer hash with the crypto module:

const buf1Hash = crypto.createHash('sha256').update(buf1).digest();
const buf2Hash = crypto.createHash('sha256').update(buf2).digest();
buf1Hash.should.eql(buf2Hash);

an easier approach is asserting the buffer length like so:

buf1.length.should.eql(buf2.length)

instead of using shouldjs as assertion module you can surely use a different tool

Upvotes: 3

hellboy
hellboy

Reputation: 1618

Solution using file-compare and node-temp:

it('should return test2.json as a stream', function (done) {
    var writeStream = temp.createWriteStream();
    temp.track();

    var req = api.get('/files/7386afde8992');

    req.on('end', function() {
        comparator.compare(writeStream.path, TEST2_JSON_FILE, function(result, err) {
            if (err) {
                return done(err);
            }

            result.should.true;
            done();
        });
    });

    req.pipe(writeStream);
});

Upvotes: 3

den bardadym
den bardadym

Reputation: 2825

In should.js you can use .eql to compare Buffer's instances:

> var buf1 = new Buffer('abc');
undefined
> var buf2 = new Buffer('abc');
undefined
> var buf3 = new Buffer('dsfg');
undefined
> buf1.should.be.eql(buf1)
...
> buf1.should.be.eql(buf2)
...
> buf1.should.be.eql(buf3)
AssertionError: expected <Buffer 61 62 63> to equal <Buffer 64 73 66 67>
    ...
> 

Upvotes: 4

micnic
micnic

Reputation: 11275

You have 3 solutions:

First:

Compare the result strings

tmpBuf.toString() === testBuf.toString();

Second:

Using a loop to read the buffers byte by byte

var index = 0,
    length = tmpBuf.length,
    match = true;

while (index < length) {
    if (tmpBuf[index] === testBuf[index]) {
        index++;
    } else {
        match = false;
        break;
    }
}

match; // true -> contents are the same, false -> otherwise

Third:

Using a third-party module like buffertools and buffertools.compare(buffer, buffer|string) method.

Upvotes: 4

Related Questions