mfncooper / mockery

Simplifying the use of mocks with Node.js
Other
1.1k stars 60 forks source link

Bad cache restore for addon modules #34

Open sandstar opened 9 years ago

sandstar commented 9 years ago

Mockery's restoration of the cache on disable() seems inadequate for addon modules.

I'm using Windows 7, SP2, 64bit, node 0.12.4 (32 bit) and Mockery 1.4.0.

Clone node-addon-examples and add a couple of javascript files to the root folder of the first example: node-addon-examples\1_hello_world\node_0.12.

File 1: tock.js (12 lines)

var mockery = require('mockery');
// useCleanCache: true is necessary to reproduce the problem
mockery.enable(
{useCleanCache: true}
);
// registerSubstitute() is a workaround for the problem.
// mockery.registerSubstitute('./build/Release/hello.node', './tick.js');
var addon = require('./build/Release/hello.node');
console.log(addon.hello());
mockery.disable();
var addon2 = require('./build/Release/hello.node');
console.log(addon2.hello());

File 2: tick.js (1 line)

module.exports.hello = function () { return "world";};

In a command window, cd to the root folder and run the following commands.

npm install
npm install mockery
node tock.js

The output was the following.

D:\Builds\node-addon-examples\1_hello_world\node_0.12>node tock.js
WARNING: loading non-allowed module: ./build/Release/hello.node
world
module.js:355
    Module._extensions[extension](this, filename);
                           ^
Error: Module did not self-register.
    at Error (native)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (D:\Builds\node-addon-examples\1_hello_world\node_0.12\tock.js:11:14)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)

If we alter the code to turn off useCleanCache or if we uncomment the line to registerSubstitute() and rerun, then it runs without error.

I tried a similar test on other examples in this repo of addon examples, with similar results.

istian commented 9 years ago

I have the same issue when using java bridge for node (node-java).

Disabling the useCleanCache puts away the error Error: Module did not self-register but I wonder what is the effect on doing this and if there's a way to fix it without altering the setting?

ghost commented 8 years ago

Disabling useCleanCache also remove the Error: Module did not self-register for gcloud.

cspotcode commented 8 years ago

My guess is that native modules can only be loaded once. When mockery clears the cache, node tries to load the native module a second time since it's not in cache. However, the native module doesn't "self-register" a second time because it knows it's already been loaded once.

To fix this, mockery can cache ".node" modules in node's original cache even when useCleanCache is enabled. That way, they never need to be loaded multiple times.

This fix would be a problem if ".node" modules required other modules, but I'm pretty sure that doesn't happen.

ddolcimascolo commented 8 years ago

Hi there,

Any chance you'll fix this in mockery ?

Thx