Skip to content

Commit 4ed1c78

Browse files
committed
Test deadlock in callbacks
We want to test two scenarios: - When libgit2 spawns threads to do the work (when doing a checkout). - When libigt2 leverages a single thread to do the work (for example when working with submodules). In each scenario, we'll run synchronous work inside the callbacks, where no locking is applied, so they should succeed. We'll also run asynchronous work inside the callbacks that lock the same objects already locked. These tests should be able to run by temporary unlocking those objects until the callback ends.
1 parent 1acd78f commit 4ed1c78

2 files changed

Lines changed: 108 additions & 0 deletions

File tree

test/tests/filter.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,80 @@ describe("Filter", function() {
333333
});
334334
});
335335

336+
it("can run sync callback on checkout without deadlocking", function() { // jshint ignore:line
337+
var test = this;
338+
var syncCallbackResult = true;
339+
340+
return Registry.register(filterName, {
341+
apply: function() {
342+
syncCallbackResult = test.repository.isEmpty();
343+
},
344+
check: function() {
345+
return NodeGit.Error.CODE.OK;
346+
}
347+
}, 0)
348+
.then(function(result) {
349+
assert.strictEqual(result, NodeGit.Error.CODE.OK);
350+
return fse.writeFile(
351+
packageJsonPath,
352+
"Changing content to trigger checkout",
353+
{ encoding: "utf-8" }
354+
);
355+
})
356+
.then(function() {
357+
var opts = {
358+
checkoutStrategy: Checkout.STRATEGY.FORCE,
359+
paths: "package.json"
360+
};
361+
return Checkout.head(test.repository, opts);
362+
})
363+
.then(function() {
364+
assert.strictEqual(syncCallbackResult, 0);
365+
});
366+
});
367+
368+
// 'Checkout.head' and 'Submodule.lookup' do work with the repo locked.
369+
// They should work together without deadlocking.
370+
it("can run async callback on checkout without deadlocking", function() { // jshint ignore:line
371+
var test = this;
372+
var submoduleNameIn = "vendor/libgit2";
373+
var asyncCallbackResult = "";
374+
375+
return Registry.register(filterName, {
376+
apply: function() {
377+
return NodeGit.Submodule.lookup(test.repository, submoduleNameIn)
378+
.then(function(submodule) {
379+
return submodule.name();
380+
})
381+
.then(function(name) {
382+
asyncCallbackResult = name;
383+
return NodeGit.Error.CODE.OK;
384+
});
385+
},
386+
check: function() {
387+
return NodeGit.Error.CODE.OK;
388+
}
389+
}, 0)
390+
.then(function(result) {
391+
assert.strictEqual(result, NodeGit.Error.CODE.OK);
392+
return fse.writeFile(
393+
packageJsonPath,
394+
"Changing content to trigger checkout",
395+
{ encoding: "utf-8" }
396+
);
397+
})
398+
.then(function() {
399+
var opts = {
400+
checkoutStrategy: Checkout.STRATEGY.FORCE,
401+
paths: "package.json"
402+
};
403+
return Checkout.head(test.repository, opts);
404+
})
405+
.then(function() {
406+
assert.equal(asyncCallbackResult, submoduleNameIn);
407+
});
408+
});
409+
336410
// this test is useless on 32 bit CI, because we cannot construct
337411
// a buffer big enough to test anything of significance :)...
338412
if (process.arch === "x64") {

test/tests/submodule.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,38 @@ describe("Submodule", function() {
157157
assert.equal(entries[1].path, submodulePath);
158158
});
159159
});
160+
161+
it("can run sync callback without deadlocking", function() {
162+
var repo = this.workdirRepository;
163+
var submodules = [];
164+
var submoduleCallback = function(submodule, name, payload) {
165+
var submoduleName = submodule.name();
166+
assert.equal(submoduleName, name);
167+
submodules.push(name);
168+
};
169+
170+
return Submodule.foreach(repo, submoduleCallback).then(function() {
171+
assert.equal(submodules.length, 1);
172+
});
173+
});
174+
175+
// 'Submodule.foreach' and 'Submodule.lookup' do work with the repo locked.
176+
// They should work together without deadlocking.
177+
it("can run async callback without deadlocking", function() {
178+
var repo = this.workdirRepository;
179+
var submodules = [];
180+
var submoduleCallback = function(submodule, name, payload) {
181+
var owner = submodule.owner();
182+
183+
return Submodule.lookup(owner, name)
184+
.then(function(submodule) {
185+
assert.equal(submodule.name(), name);
186+
submodules.push(name);
187+
});
188+
};
189+
190+
return Submodule.foreach(repo, submoduleCallback).then(function() {
191+
assert.equal(submodules.length, 1);
192+
});
193+
});
160194
});

0 commit comments

Comments
 (0)