Skip to content
This repository has been archived by the owner on Jun 10, 2022. It is now read-only.

Commit

Permalink
add basic code coverage support (via nyc + coveralls) to all subprojects
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaguar0625 committed May 17, 2018
1 parent a9db744 commit 481f4b1
Show file tree
Hide file tree
Showing 17 changed files with 5,457 additions and 221 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ npm-*.log*
typings.json
typings/
jsconfig.json
.nyc_output/
5 changes: 2 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ env:

cache: yarn

before_script:
- sh yarn_setup.sh
before_script: sh yarn_setup.sh

script: cd ${SUBPROJECT} && yarn test
script: cd ${SUBPROJECT} && yarn run test:travis
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# catapult-rest

[![Build Status](https://api.travis-ci.org/nemtech/catapult-rest.svg?branch=master)](https://travis-ci.org/nemtech/catapult-rest)
[![Coverage Status](https://coveralls.io/repos/github/nemtech/catapult-rest/badge.svg?branch=master)](https://coveralls.io/github/nemtech/catapult-rest?branch=master)

## Requirements

Expand Down
10 changes: 10 additions & 0 deletions catapult-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"build": "ncp src/ _build && cross-env BABEL_ENV=production babel src -d _build_browser --source-maps",
"rebuild": "npm run clean && npm run build",
"test": "mocha --full-trace --recursive",
"test:coverage": "nyc yarn test && nyc report --reporter=text-lcov",
"test:jenkins": "cross-env JUNIT_REPORT_PATH=test-results.xml mocha --reporter mocha-jenkins-reporter --forbid-only --full-trace --recursive test || exit 0",
"test:travis": "nyc yarn test && nyc report --reporter=text-lcov | coveralls",
"lint": "eslint src test",
"lint:jenkins": "eslint -o tests.catapult.lint.xml -f junit src test || exit 0"
},
Expand All @@ -21,6 +23,7 @@
"babel-plugin-transform-inline-environment-variables": "^6.8.0",
"babel-preset-env": "^1.6.1",
"chai": "^4.1.2",
"coveralls": "^3.0.1",
"cross-env": "^5.1.3",
"eslint": "^4.18.2",
"eslint-config-airbnb": "^16.1.0",
Expand All @@ -30,11 +33,18 @@
"mocha": "^5.0.1",
"mocha-jenkins-reporter": "^0.3.10",
"ncp": "^2.0.0",
"nyc": "^11.8.0",
"rimraf": "^2.6.2"
},
"dependencies": {
"js-sha3": "^0.7.0",
"ripemd160": "^2.0.1",
"tweetnacl": "^1.0.0"
},
"nyc": {
"exclude": [
"src/external/*.js",
"test/**/*"
]
}
}
204 changes: 106 additions & 98 deletions catapult-sdk/src/model/status.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,111 +20,119 @@

/** @module model/status */

/* istanbul ignore next */
const toStringInternal = code => {
switch (code) {
case 0x00000000: return 'Success';
case 0x40000000: return 'Neutral';
case 0x80000000: return 'Failure';
case 0x80430003: return 'Failure_Core_Past_Deadline';
case 0x80430004: return 'Failure_Core_Future_Deadline';
case 0x80430005: return 'Failure_Core_Insufficient_Balance';
case 0x8043000A: return 'Failure_Core_Timestamp_Too_Far_In_Future';
case 0x8043000F: return 'Failure_Core_Too_Many_Transactions';
case 0x80430012: return 'Failure_Core_Nemesis_Account_Signed_After_Nemesis_Block';
case 0x80430014: return 'Failure_Core_Wrong_Network';
case 0x80430015: return 'Failure_Core_Invalid_Address';
case 0x80430069: return 'Failure_Core_Block_Harvester_Ineligible';
case 0x81480007: return 'Failure_Hash_Exists';
case 0x80530008: return 'Failure_Signature_Not_Verifiable';
case 0x80410001: return 'Failure_Aggregate_Too_Many_Transactions';
case 0x80410002: return 'Failure_Aggregate_No_Transactions';
case 0x80410003: return 'Failure_Aggregate_Too_Many_Cosignatures';
case 0x80410004: return 'Failure_Aggregate_Redundant_Cosignatures';
case 0x80411001: return 'Failure_Aggregate_Ineligible_Cosigners';
case 0x80411002: return 'Failure_Aggregate_Missing_Cosigners';
case 0x804C0001: return 'Failure_Lock_Invalid_Hash_Algorithm';
case 0x804C0002: return 'Failure_Lock_Invalid_Mosaic_Id';
case 0x804C0003: return 'Failure_Lock_Invalid_Mosaic_Amount';
case 0x804C0004: return 'Failure_Lock_Hash_Exists';
case 0x804C0005: return 'Failure_Lock_Hash_Does_Not_Exist';
case 0x804C0006: return 'Failure_Lock_Missing_Secret_Padding';
case 0x804C0007: return 'Failure_Lock_Hash_Not_Implemented';
case 0x804C0008: return 'Failure_Lock_Proof_Size_Out_Of_Bounds';
case 0x804C0009: return 'Failure_Lock_Secret_Mismatch';
case 0x804C000A: return 'Failure_Lock_Unknown_Secret';
case 0x804C000B: return 'Failure_Lock_Inactive_Hash';
case 0x804C000C: return 'Failure_Lock_Inactive_Secret';
case 0x804C000D: return 'Failure_Lock_Hash_Algorithm_Mismatch';
case 0x804C000E: return 'Failure_Lock_Hash_Already_Used';
case 0x804C000F: return 'Failure_Lock_Secret_Already_Used';
case 0x804C0010: return 'Failure_Lock_Invalid_Duration';
case 0x80550001: return 'Failure_Multisig_Modify_Account_In_Both_Sets';
case 0x80550002: return 'Failure_Multisig_Modify_Multiple_Deletes';
case 0x80550003: return 'Failure_Multisig_Modify_Redundant_Modifications';
case 0x80550004: return 'Failure_Multisig_Modify_Unknown_Multisig_Account';
case 0x80550005: return 'Failure_Multisig_Modify_Not_A_Cosigner';
case 0x80550006: return 'Failure_Multisig_Modify_Already_A_Cosigner';
case 0x80550007: return 'Failure_Multisig_Modify_Min_Setting_Out_Of_Range';
case 0x80550008: return 'Failure_Multisig_Modify_Min_Setting_Larger_Than_Num_Cosignatories';
case 0x80550009: return 'Failure_Multisig_Modify_Unsupported_Modification_Type';
case 0x8055000A: return 'Failure_Multisig_Modify_Max_Cosigned_Accounts';
case 0x8055000B: return 'Failure_Multisig_Modify_Max_Cosigners';
case 0x8055000C: return 'Failure_Multisig_Modify_Loop';
case 0x8055000D: return 'Failure_Multisig_Modify_Max_Multisig_Depth';
case 0x80550800: return 'Failure_Multisig_Operation_Not_Permitted_By_Account';
case 0x804E0001: return 'Failure_Namespace_Invalid_Duration';
case 0x804D0001: return 'Failure_Mosaic_Invalid_Duration';
case 0x804E0002: return 'Failure_Namespace_Invalid_Name';
case 0x804D0002: return 'Failure_Mosaic_Invalid_Name';
case 0x804E0003: return 'Failure_Namespace_Name_Id_Mismatch';
case 0x804D0003: return 'Failure_Mosaic_Name_Id_Mismatch';
case 0x804E0004: return 'Failure_Namespace_Expired';
case 0x804D0004: return 'Failure_Mosaic_Expired';
case 0x804E0005: return 'Failure_Namespace_Owner_Conflict';
case 0x804D0005: return 'Failure_Mosaic_Owner_Conflict';
case 0x804E0064: return 'Failure_Namespace_Invalid_Namespace_Type';
case 0x804E0065: return 'Failure_Namespace_Root_Name_Reserved';
case 0x804E0066: return 'Failure_Namespace_Too_Deep';
case 0x804E0067: return 'Failure_Namespace_Parent_Unknown';
case 0x804E0096: return 'Failure_Namespace_Already_Exists';
case 0x804E0097: return 'Failure_Namespace_Already_Active';
case 0x804E0098: return 'Failure_Namespace_Eternal_After_Nemesis_Block';
case 0x804D0064: return 'Failure_Mosaic_Parent_Id_Conflict';
case 0x804D0065: return 'Failure_Mosaic_Invalid_Property';
case 0x804D0066: return 'Failure_Mosaic_Invalid_Flags';
case 0x804D0067: return 'Failure_Mosaic_Invalid_Divisibility';
case 0x804D0068: return 'Failure_Mosaic_Invalid_Supply_Change_Direction';
case 0x804D0069: return 'Failure_Mosaic_Invalid_Supply_Change_Amount';
case 0x804D006A: return 'Failure_Mosaic_Name_Reserved';
case 0x804D0096: return 'Failure_Mosaic_Modification_Disallowed';
case 0x804D0097: return 'Failure_Mosaic_Modification_No_Changes';
case 0x804D00A1: return 'Failure_Mosaic_Supply_Immutable';
case 0x804D00A2: return 'Failure_Mosaic_Supply_Negative';
case 0x804D00A3: return 'Failure_Mosaic_Supply_Exceeded';
case 0x804D00A4: return 'Failure_Mosaic_Non_Transferable';
case 0x80540006: return 'Failure_Transfer_Message_Too_Large';
case 0x805400C8: return 'Failure_Transfer_Out_Of_Order_Mosaics';
case 0x80FF0066: return 'Failure_Chain_Unlinked';
case 0x80FF0068: return 'Failure_Chain_Block_Not_Hit';
case 0x80FE0001: return 'Failure_Consumer_Empty_Input';
case 0x80FE1001: return 'Failure_Consumer_Block_Transactions_Hash_Mismatch';
case 0x81FE1002: return 'Failure_Consumer_Hash_In_Recency_Cache';
case 0x80FE2001: return 'Failure_Consumer_Remote_Chain_Too_Many_Blocks';
case 0x80FE2002: return 'Failure_Consumer_Remote_Chain_Improper_Link';
case 0x80FE2003: return 'Failure_Consumer_Remote_Chain_Duplicate_Transactions';
case 0x80FE3001: return 'Failure_Consumer_Remote_Chain_Unlinked';
case 0x80FE3002: return 'Failure_Consumer_Remote_Chain_Mismatched_Difficulties';
case 0x80FE3003: return 'Failure_Consumer_Remote_Chain_Score_Not_Better';
case 0x80FE3004: return 'Failure_Consumer_Remote_Chain_Too_Far_Behind';
case 0x80450101: return 'Failure_Extension_Partial_Transaction_Cache_Prune';
case 0x80450102: return 'Failure_Extension_Partial_Transaction_Dependency_Removed';
default: return undefined;
}
};

const status = {
/**
* Converts a status code to a string.
* @param {numeric} code The status code.
* @returns {string} The string representation of the status code.
*/
toString: code => {
switch (code) {
case 0x00000000: return 'Success';
case 0x40000000: return 'Neutral';
case 0x80000000: return 'Failure';
case 0x80430003: return 'Failure_Core_Past_Deadline';
case 0x80430004: return 'Failure_Core_Future_Deadline';
case 0x80430005: return 'Failure_Core_Insufficient_Balance';
case 0x8043000A: return 'Failure_Core_Timestamp_Too_Far_In_Future';
case 0x8043000F: return 'Failure_Core_Too_Many_Transactions';
case 0x80430012: return 'Failure_Core_Nemesis_Account_Signed_After_Nemesis_Block';
case 0x80430014: return 'Failure_Core_Wrong_Network';
case 0x80430015: return 'Failure_Core_Invalid_Address';
case 0x80430069: return 'Failure_Core_Block_Harvester_Ineligible';
case 0x81480007: return 'Failure_Hash_Exists';
case 0x80530008: return 'Failure_Signature_Not_Verifiable';
case 0x80410001: return 'Failure_Aggregate_Too_Many_Transactions';
case 0x80410002: return 'Failure_Aggregate_No_Transactions';
case 0x80410003: return 'Failure_Aggregate_Too_Many_Cosignatures';
case 0x80410004: return 'Failure_Aggregate_Redundant_Cosignatures';
case 0x80411001: return 'Failure_Aggregate_Ineligible_Cosigners';
case 0x80411002: return 'Failure_Aggregate_Missing_Cosigners';
case 0x804C0001: return 'Failure_Lock_Invalid_Hash_Algorithm';
case 0x804C0002: return 'Failure_Lock_Invalid_Mosaic_Id';
case 0x804C0003: return 'Failure_Lock_Invalid_Mosaic_Amount';
case 0x804C0004: return 'Failure_Lock_Hash_Exists';
case 0x804C0005: return 'Failure_Lock_Hash_Does_Not_Exist';
case 0x804C0006: return 'Failure_Lock_Missing_Secret_Padding';
case 0x804C0007: return 'Failure_Lock_Hash_Not_Implemented';
case 0x804C0008: return 'Failure_Lock_Proof_Size_Out_Of_Bounds';
case 0x804C0009: return 'Failure_Lock_Secret_Mismatch';
case 0x804C000A: return 'Failure_Lock_Unknown_Secret';
case 0x804C000B: return 'Failure_Lock_Inactive_Hash';
case 0x804C000C: return 'Failure_Lock_Inactive_Secret';
case 0x804C000D: return 'Failure_Lock_Hash_Algorithm_Mismatch';
case 0x804C000E: return 'Failure_Lock_Hash_Already_Used';
case 0x804C000F: return 'Failure_Lock_Secret_Already_Used';
case 0x804C0010: return 'Failure_Lock_Invalid_Duration';
case 0x80550001: return 'Failure_Multisig_Modify_Account_In_Both_Sets';
case 0x80550002: return 'Failure_Multisig_Modify_Multiple_Deletes';
case 0x80550003: return 'Failure_Multisig_Modify_Redundant_Modifications';
case 0x80550004: return 'Failure_Multisig_Modify_Unknown_Multisig_Account';
case 0x80550005: return 'Failure_Multisig_Modify_Not_A_Cosigner';
case 0x80550006: return 'Failure_Multisig_Modify_Already_A_Cosigner';
case 0x80550007: return 'Failure_Multisig_Modify_Min_Setting_Out_Of_Range';
case 0x80550008: return 'Failure_Multisig_Modify_Min_Setting_Larger_Than_Num_Cosignatories';
case 0x80550009: return 'Failure_Multisig_Modify_Unsupported_Modification_Type';
case 0x8055000A: return 'Failure_Multisig_Modify_Max_Cosigned_Accounts';
case 0x8055000B: return 'Failure_Multisig_Modify_Max_Cosigners';
case 0x8055000C: return 'Failure_Multisig_Modify_Loop';
case 0x8055000D: return 'Failure_Multisig_Modify_Max_Multisig_Depth';
case 0x80550800: return 'Failure_Multisig_Operation_Not_Permitted_By_Account';
case 0x804E0001: return 'Failure_Namespace_Invalid_Duration';
case 0x804D0001: return 'Failure_Mosaic_Invalid_Duration';
case 0x804E0002: return 'Failure_Namespace_Invalid_Name';
case 0x804D0002: return 'Failure_Mosaic_Invalid_Name';
case 0x804E0003: return 'Failure_Namespace_Name_Id_Mismatch';
case 0x804D0003: return 'Failure_Mosaic_Name_Id_Mismatch';
case 0x804E0004: return 'Failure_Namespace_Expired';
case 0x804D0004: return 'Failure_Mosaic_Expired';
case 0x804E0005: return 'Failure_Namespace_Owner_Conflict';
case 0x804D0005: return 'Failure_Mosaic_Owner_Conflict';
case 0x804E0064: return 'Failure_Namespace_Invalid_Namespace_Type';
case 0x804E0065: return 'Failure_Namespace_Root_Name_Reserved';
case 0x804E0066: return 'Failure_Namespace_Too_Deep';
case 0x804E0067: return 'Failure_Namespace_Parent_Unknown';
case 0x804E0096: return 'Failure_Namespace_Already_Exists';
case 0x804E0097: return 'Failure_Namespace_Already_Active';
case 0x804E0098: return 'Failure_Namespace_Eternal_After_Nemesis_Block';
case 0x804D0064: return 'Failure_Mosaic_Parent_Id_Conflict';
case 0x804D0065: return 'Failure_Mosaic_Invalid_Property';
case 0x804D0066: return 'Failure_Mosaic_Invalid_Flags';
case 0x804D0067: return 'Failure_Mosaic_Invalid_Divisibility';
case 0x804D0068: return 'Failure_Mosaic_Invalid_Supply_Change_Direction';
case 0x804D0069: return 'Failure_Mosaic_Invalid_Supply_Change_Amount';
case 0x804D006A: return 'Failure_Mosaic_Name_Reserved';
case 0x804D0096: return 'Failure_Mosaic_Modification_Disallowed';
case 0x804D0097: return 'Failure_Mosaic_Modification_No_Changes';
case 0x804D00A1: return 'Failure_Mosaic_Supply_Immutable';
case 0x804D00A2: return 'Failure_Mosaic_Supply_Negative';
case 0x804D00A3: return 'Failure_Mosaic_Supply_Exceeded';
case 0x804D00A4: return 'Failure_Mosaic_Non_Transferable';
case 0x80540006: return 'Failure_Transfer_Message_Too_Large';
case 0x805400C8: return 'Failure_Transfer_Out_Of_Order_Mosaics';
case 0x80FF0066: return 'Failure_Chain_Unlinked';
case 0x80FF0068: return 'Failure_Chain_Block_Not_Hit';
case 0x80FE0001: return 'Failure_Consumer_Empty_Input';
case 0x80FE1001: return 'Failure_Consumer_Block_Transactions_Hash_Mismatch';
case 0x81FE1002: return 'Failure_Consumer_Hash_In_Recency_Cache';
case 0x80FE2001: return 'Failure_Consumer_Remote_Chain_Too_Many_Blocks';
case 0x80FE2002: return 'Failure_Consumer_Remote_Chain_Improper_Link';
case 0x80FE2003: return 'Failure_Consumer_Remote_Chain_Duplicate_Transactions';
case 0x80FE3001: return 'Failure_Consumer_Remote_Chain_Unlinked';
case 0x80FE3002: return 'Failure_Consumer_Remote_Chain_Mismatched_Difficulties';
case 0x80FE3003: return 'Failure_Consumer_Remote_Chain_Score_Not_Better';
case 0x80FE3004: return 'Failure_Consumer_Remote_Chain_Too_Far_Behind';
case 0x80450101: return 'Failure_Extension_Partial_Transaction_Cache_Prune';
case 0x80450102: return 'Failure_Extension_Partial_Transaction_Dependency_Removed';
}
const str = toStringInternal(code);
if (undefined !== str)
return str;

let hexString = code.toString(16).toUpperCase();
if (8 > hexString.length)
Expand Down
2 changes: 1 addition & 1 deletion catapult-sdk/src/plugins/catapultModelSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const catapultModelSystem = {
const schemaBuilder = new ModelSchemaBuilder();
const codecBuilder = new ModelCodecBuilder();
const formatterBuilder = new ModelFormatterBuilder();
(pluginNames || []).forEach(pluginName => {
pluginNames.forEach(pluginName => {
if (!plugins[pluginName])
throw Error(`plugin '${pluginName}' not supported by model system`);

Expand Down
22 changes: 9 additions & 13 deletions catapult-sdk/src/plugins/multisig.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,10 @@ const multisigPlugin = {
const numModifications = parser.uint8();
transaction.modifications = [];

if (0 < numModifications) {
while (transaction.modifications.length < numModifications) {
const type = parser.uint8();
const cosignatoryPublicKey = parser.buffer(constants.sizes.signer);
transaction.modifications.push({ type, cosignatoryPublicKey });
}
while (transaction.modifications.length < numModifications) {
const type = parser.uint8();
const cosignatoryPublicKey = parser.buffer(constants.sizes.signer);
transaction.modifications.push({ type, cosignatoryPublicKey });
}

return transaction;
Expand All @@ -78,15 +76,13 @@ const multisigPlugin = {
serializer.writeUint8(convert.int8ToUint8(transaction.minRemovalDelta));
serializer.writeUint8(convert.int8ToUint8(transaction.minApprovalDelta));

const numModifications = transaction.modifications ? transaction.modifications.length : 0;
const numModifications = transaction.modifications.length;
serializer.writeUint8(numModifications);

if (0 < numModifications) {
transaction.modifications.forEach(modification => {
serializer.writeUint8(modification.type);
serializer.writeBuffer(modification.cosignatoryPublicKey);
});
}
transaction.modifications.forEach(modification => {
serializer.writeUint8(modification.type);
serializer.writeBuffer(modification.cosignatoryPublicKey);
});
}
});
}
Expand Down
6 changes: 1 addition & 5 deletions catapult-sdk/src/utils/uint64.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,7 @@ const uint64Module = {
if (16 !== input.length)
throw Error(`hex string has unexpected size '${input.length}'`);

let hexString = input;
if (16 > hexString.length)
hexString = '0'.repeat(16 - hexString.length) + hexString;

const uint8Array = convert.hexToUint8(hexString);
const uint8Array = convert.hexToUint8(input);
const view = new DataView(uint8Array.buffer);
return [view.getUint32(4), view.getUint32(0)];
},
Expand Down
9 changes: 9 additions & 0 deletions catapult-sdk/test/model/ModelFormatterBuilder_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,5 +236,14 @@ describe('model formatter builder', () => {
// Assert:
expect(subFormatterTypes).to.deep.equal({ id: 'uint64', amount: 'uint64' });
});

it('cannot add arbitrary formatter multiple times', () => {
// Arrange:
const builder = new ModelFormatterBuilder();
builder.addFormatter('mosaic');

// Act + Assert:
expect(() => { builder.addFormatter('mosaic'); }).to.throw('formatter already registered');
});
});
});
25 changes: 22 additions & 3 deletions catapult-sdk/test/model/address_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,20 @@ describe('address', () => {
// Assert:
expect(encoded).to.equal(expected);
});

it('cannot create encoded address from invalid address', () => {
// Arrange:
const decodedHexStrings = [
'6823BB7C3C089D996585466380EDBDC19D4959184893E38C', // too short
'6823BB7C3C089D996585466380EDBDC19D4959184893E38CA678' // too long
];

// Act + Assert:
decodedHexStrings.forEach(decodedHex => {
expect(() => { address.addressToString(convert.hexToUint8(decodedHex)); }, decodedHex)
.to.throw(`${decodedHex} does not represent a valid decoded address`);
});
});
});

describe('publicKeyToAddress', () => {
Expand Down Expand Up @@ -190,11 +204,16 @@ describe('address', () => {
});

it('returns false for invalid encoded address', () => {
// Arrange: changed last char
const encoded = 'NAR3W7B4BCOZSZMFIZRYB3N5YGOUSWIYJCJ6HDFH';
// Arrange:
const encodedAddresses = [
'NAR3W7B4BCOZSZMFIZRYB3N5YGOUSWIYJCJ6HDFH', // changed last char
'NAR3W7B4BCOZSZMFIZRYx3N5YGOUSWIYJCJ6HDFG' // non-base32 char ('x')
];

// Assert:
expect(address.isValidEncodedAddress(encoded)).to.equal(false);
encodedAddresses.forEach(encoded => {
expect(address.isValidEncodedAddress(encoded), encoded).to.equal(false);
});
});

it('returns false for encoded address with wrong length', () => {
Expand Down
Loading

0 comments on commit 481f4b1

Please sign in to comment.