Skip to content

Commit

Permalink
add more unit tests for catching invalid lockfiles early
Browse files Browse the repository at this point in the history
  • Loading branch information
hsjobeki committed Oct 13, 2023
1 parent fe14519 commit 6f05f9d
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 43 deletions.
36 changes: 5 additions & 31 deletions lib/internal/nodejsLockUtils.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@

sanitizeLockfile = lock:
# Every project MUST have a name
assert lock ? name;
if ! lock ? name then throw "Invalid lockfile: Every project MUST have a name" else
# Every project MUST have a version
assert lock ? version;
if ! lock ? version then throw "Invalid lockfile: Every project MUST have a version" else
# This lockfile module only supports lockfileVersion 2 and 3
assert !lock ? lockfileVersion || lock.lockfileVersion >= 2;
if ! lock ? lockfileVersion || lock.lockfileVersion <= 1 then throw "This lockfile module only supports lockfileVersion 2 and 3" else
# The Lockfile must contain a 'packages' attribute.
assert lock ? packages;
if ! lock ? packages then throw "Invalid lockfile: The Lockfile must contain 'packages' attribute." else
lock;

findEntry =
Expand All @@ -35,32 +35,6 @@
then throw "${search} not found in package-lock.json."
else findEntry packageLock (stripPath currentPath) search;

# Returns the names of all "bundledDependencies".
# People depend on different types and different names. Unfortunatly those fields are not part of the offical npm documentation.
# Which may also be the reason for the mess.
#
# TODO: define unit tests.
# Adopted from https://github.com/aakropotkin/floco/blob/708c4ffa0c05033c29fe6886a238cb20c3ba3fb4/modules/plock/implementation.nix#L139
#
# getBundledDependencies :: Pent -> {}
getBundledDependencies = pent: let
# b :: bool | []
b = pent.bundledDependencies or pent.bundleDependencies or [];
in
# The following asserts is the XOR logic.
# "bundle" and "bundled" dependencies are both valid but invalid if both or none keys exist
assert ( pent ? bundledDependencies ) ->
( ! ( pent ? bundleDependencies ) );
assert ( pent ? bundleDependencies ) ->
( ! ( pent ? bundledDependencies ) );
if b == [] then {} else
if builtins.isList b then { bundledDependencies = b; } else
if ! b then {} else {
# b :: true
bundledDependencies = builtins.attrNames (
( pent.dependencies or {} ) // ( pent.requires or {} )
);
};
in {
inherit findEntry stripPath getBundledDependencies sanitizeLockfile;
inherit findEntry stripPath sanitizeLockfile;
}
1 change: 1 addition & 0 deletions modules/dream2nix/nodejs-package-lock-v3/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
Pent :: {
See: https://docs.npmjs.com/cli/v9/configuring-npm/package-lock-json#packages
}
> We should mention that docs are imcomplete on npmjs.com
pent is one entry of 'packages'
*/
parseSource = pent:
Expand Down
16 changes: 7 additions & 9 deletions tests/nix-unit/test_nodejs_lock_v3/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -297,18 +297,16 @@ in {
imports = [
dream2nix.modules.dream2nix.nodejs-package-lock-v3
];
nodejs-package-lock-v3.packageLock = lib.mkForce {
# Example content of lockfile
# "lockfileVersion" = 1;
};
nodejs-package-lock-v3.packageLock =
lib.mkForce {
};
};
config = evaled.config;
in {
expr = builtins.tryEval (config.nodejs-package-lock-v3.pdefs);
expected = {
success = false;
value = false;
expr = config.nodejs-package-lock-v3.pdefs;
expectedError = {
type = "ThrownError";
msg = "Invalid lockfile";
};
};

}
68 changes: 65 additions & 3 deletions tests/nix-unit/test_nodejs_lockutils/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@
expr = path;
expected = "node_modules/underscore";
};
# test the lock

# test the lock
test_nodejsLockUtils_lockfile_v3 = let
plock = {
name = "foo";
Expand Down Expand Up @@ -110,7 +110,69 @@
};
in {
expr = nodejsLockUtils.sanitizeLockfile plock;
expectedError = plock;
expectedError = {
type = "ThrownError";
msg = "This lockfile module only supports lockfileVersion 2 and 3";
};
};

test_nodejsLockUtils_lockfile_missing_name = let
plock = {
# name = "foo";
version = "1.0.0";
lockfileVersion = 3;
packages = {};
};
in {
expr = nodejsLockUtils.sanitizeLockfile plock;
expectedError = {
type = "ThrownError";
msg = "MUST have a name";
};
};

test_nodejsLockUtils_lockfile_missing_version = let
plock = {
name = "foo";
# version = "1.0.0";
lockfileVersion = 3;
packages = {};
};
in {
expr = nodejsLockUtils.sanitizeLockfile plock;
expectedError = {
type = "ThrownError";
msg = "MUST have a version";
};
};

test_nodejsLockUtils_lockfile_missing_lockfileVersion = let
plock = {
name = "foo";
version = "1.0.0";
# lockfileVersion = 3;
packages = {};
};
in {
expr = nodejsLockUtils.sanitizeLockfile plock;
expectedError = {
type = "ThrownError";
msg = "lockfileVersion";
};
};

test_nodejsLockUtils_lockfile_missing_packages = let
plock = {
name = "foo";
version = "1.0.0";
lockfileVersion = 3;
# packages = {};
};
in {
expr = nodejsLockUtils.sanitizeLockfile plock;
expectedError = {
type = "ThrownError";
msg = "must contain 'packages'";
};
};
}

0 comments on commit 6f05f9d

Please sign in to comment.