Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing stryker mutator #600

Closed
wants to merge 11 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,6 @@ link-plugins.sh
test.sh

.docker/**
!**/.gitkeep
!**/.gitkeep
# stryker temp files
.stryker-tmp
2 changes: 1 addition & 1 deletion .mocharc.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
reporter: dot
timeout: 25000
exit: true
bail: true
bail: false
Binary file added dump.rdb
Binary file not shown.
199 changes: 199 additions & 0 deletions package 2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
{
"name": "nodebb",
"license": "GPL-3.0",
"description": "NodeBB Forum",
"version": "3.8.4",
"homepage": "https://www.nodebb.org",
"repository": {
"type": "git",
"url": "https://github.com/NodeBB/NodeBB/"
},
"main": "app.js",
"scripts": {
"start": "node loader.js",
"lint": "eslint --cache ./nodebb .",
"test": "nyc --reporter=html --reporter=text-summary mocha",
"coverage": "nyc report --reporter=text-lcov > ./coverage/lcov.info",
"coveralls": "nyc report --reporter=text-lcov | coveralls && rm -r coverage"
},
"nyc": {
"exclude": [
"src/upgrades/*",
"test/*"
]
},
"lint-staged": {
"*.js": [
"eslint --fix"
]
},
"dependencies": {
"@adactive/bootstrap-tagsinput": "0.8.2",
"@fontsource/inter": "5.0.18",
"@fontsource/poppins": "5.0.14",
"@fortawesome/fontawesome-free": "6.5.2",
"@isaacs/ttlcache": "1.4.1",
"@nodebb/spider-detector": "2.0.3",
"@popperjs/core": "2.11.8",
"@socket.io/redis-adapter": "8.3.0",
"ace-builds": "1.33.2",
"archiver": "7.0.1",
"async": "3.2.5",
"autoprefixer": "10.4.19",
"bcryptjs": "2.4.3",
"benchpressjs": "2.5.1",
"body-parser": "1.20.2",
"bootbox": "6.0.0",
"bootstrap": "5.3.3",
"bootswatch": "5.3.3",
"chalk": "4.1.2",
"chart.js": "4.4.2",
"cli-graph": "3.2.2",
"clipboard": "2.0.11",
"colors": "1.4.0",
"commander": "12.0.0",
"compare-versions": "6.1.0",
"compression": "1.7.4",
"connect-flash": "0.1.1",
"connect-mongo": "5.1.0",
"connect-multiparty": "2.2.0",
"connect-pg-simple": "9.0.1",
"connect-redis": "7.1.1",
"cookie-parser": "1.4.6",
"cron": "3.1.7",
"cropperjs": "1.6.2",
"csrf-sync": "4.0.3",
"daemon": "1.1.0",
"diff": "5.2.0",
"esbuild": "0.21.2",
"express": "4.19.2",
"express-session": "1.18.0",
"express-useragent": "1.0.15",
"fetch-cookie": "3.0.1",
"file-loader": "6.2.0",
"fs-extra": "11.2.0",
"graceful-fs": "4.2.11",
"helmet": "7.1.0",
"html-to-text": "9.0.5",
"imagesloaded": "5.0.0",
"ioredis": "5.4.1",
"ipaddr.js": "2.2.0",
"jquery": "3.7.1",
"jquery-deserialize": "2.0.0",
"jquery-form": "4.3.0",
"jquery-serializeobject": "1.0.0",
"jquery-ui": "1.13.3",
"jsesc": "3.0.2",
"json2csv": "5.0.7",
"jsonwebtoken": "9.0.2",
"lodash": "4.17.21",
"logrotate-stream": "0.2.9",
"lru-cache": "10.2.2",
"mime": "3.0.0",
"mkdirp": "3.0.1",
"mongodb": "6.6.1",
"morgan": "1.10.0",
"mousetrap": "1.6.5",
"multiparty": "4.2.3",
"nconf": "0.12.1",
"nodebb-plugin-2factor": "7.5.3",
"nodebb-plugin-composer-default": "10.2.36",
"nodebb-plugin-dbsearch": "6.2.5",
"nodebb-plugin-emoji": "5.1.15",
"nodebb-plugin-emoji-android": "4.0.0",
"nodebb-plugin-location-to-map": "^0.1.1",
"nodebb-plugin-markdown": "12.2.6",
"nodebb-plugin-mentions": "4.4.3",
"nodebb-plugin-ntfy": "1.7.4",
"nodebb-plugin-spam-be-gone": "2.2.2",
"nodebb-rewards-essentials": "1.0.0",
"nodebb-theme-harmony": "1.2.63",
"nodebb-theme-lavender": "7.1.8",
"nodebb-theme-peace": "2.2.6",
"nodebb-theme-persona": "13.3.25",
"nodebb-widget-essentials": "7.0.18",
"nodemailer": "6.9.13",
"nprogress": "0.2.0",
"passport": "0.7.0",
"passport-http-bearer": "1.0.1",
"passport-local": "1.0.0",
"pg": "8.11.5",
"pg-cursor": "2.10.5",
"postcss": "8.4.38",
"postcss-clean": "1.2.0",
"progress-webpack-plugin": "1.0.16",
"prompt": "1.3.0",
"rimraf": "5.0.7",
"rss": "1.2.2",
"rtlcss": "4.1.1",
"sanitize-html": "2.13.0",
"sass": "1.77.1",
"semver": "7.6.2",
"serve-favicon": "2.5.0",
"sharp": "0.32.6",
"sitemap": "7.1.1",
"socket.io": "4.7.5",
"socket.io-client": "4.7.5",
"sortablejs": "1.15.2",
"spdx-license-list": "6.9.0",
"terser-webpack-plugin": "5.3.10",
"textcomplete": "0.18.2",
"textcomplete.contenteditable": "0.1.1",
"timeago": "1.6.7",
"tinycon": "0.6.8",
"toobusy-js": "0.5.1",
"tough-cookie": "4.1.4",
"validator": "13.12.0",
"webpack": "5.91.0",
"webpack-merge": "5.10.0",
"winston": "3.13.0",
"workerpool": "9.1.1",
"xml": "1.0.1",
"xregexp": "5.1.1",
"yargs": "17.7.2",
"zxcvbn": "4.4.2"
},
"devDependencies": {
"@apidevtools/swagger-parser": "10.1.0",
"@commitlint/cli": "19.3.0",
"@commitlint/config-angular": "19.3.0",
"coveralls": "3.1.1",
"eslint": "8.57.0",
"eslint-config-nodebb": "0.2.1",
"eslint-plugin-import": "2.29.1",
"grunt": "1.6.1",
"grunt-contrib-watch": "1.1.0",
"husky": "8.0.3",
"jsdom": "24.0.0",
"lint-staged": "15.2.2",
"mocha": "10.4.0",
"mocha-lcov-reporter": "1.3.0",
"mockdate": "3.0.5",
"nyc": "15.1.0",
"smtp-server": "3.13.4"
},
"optionalDependencies": {
"sass-embedded": "1.77.1"
},
"resolutions": {
"*/jquery": "3.7.1"
},
"bugs": {
"url": "https://github.com/NodeBB/NodeBB/issues"
},
"engines": {
"node": ">=18"
},
"maintainers": [
{
"name": "Julian Lam",
"email": "[email protected]",
"url": "https://github.com/julianlam"
},
{
"name": "Barış Soner Uşaklı",
"email": "[email protected]",
"url": "https://github.com/barisusakli"
}
]
}
1 change: 0 additions & 1 deletion src/cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ prestart.versionCheck();

if (!configExists && process.argv[2] !== 'setup') {
require('./setup').webInstall();
return;
}

if (configExists) {
Expand Down
114 changes: 61 additions & 53 deletions src/database/postgres/main.js
Original file line number Diff line number Diff line change
@@ -1,75 +1,83 @@
'use strict';

const helpers = require('./helpers');

module.exports = function (module) {
const helpers = require('./helpers');
// Helper Functions
async function executeQuery(client, query) {
return await client.query(query);
}

async function checkIfKeysExist(module, keys) {
const query = {
name: 'existsArray',
text: `
SELECT o."_key" k
FROM "legacy_object_live" o
WHERE o."_key" = ANY($1::TEXT[])`,
values: [keys],
};
console.log("Andrew")

Check failure on line 20 in src/database/postgres/main.js

View workflow job for this annotation

GitHub Actions / test

Strings must use singlequote

Check failure on line 20 in src/database/postgres/main.js

View workflow job for this annotation

GitHub Actions / test

Missing semicolon
const res = await executeQuery(module.pool, query);
return keys.map(k => res.rows.some(r => r.k === k));
}

async function checkIfzSetsExist(module, keys) {
const members = await Promise.all(
keys.map(key => module.getSortedSetRange(key, 0, 0))
);
console.log("Andrew")

Check failure on line 29 in src/database/postgres/main.js

View workflow job for this annotation

GitHub Actions / test

Strings must use singlequote

Check failure on line 29 in src/database/postgres/main.js

View workflow job for this annotation

GitHub Actions / test

Missing semicolon
return members.map(member => member.length > 0);
}

async function checkExists(module, key) {
console.log("Andrew")

Check failure on line 34 in src/database/postgres/main.js

View workflow job for this annotation

GitHub Actions / test

Strings must use singlequote

Check failure on line 34 in src/database/postgres/main.js

View workflow job for this annotation

GitHub Actions / test

Missing semicolon
const type = await module.type(key);
if (type === 'zset') {
const members = await module.getSortedSetRange(key, 0, 0);
return members.length > 0;
}
const query = {
name: 'exists',
text: `
SELECT EXISTS(SELECT * FROM "legacy_object_live" WHERE "_key" = $1::TEXT LIMIT 1) e`,
values: [key],
};
const res = await executeQuery(module.pool, query);

Check failure on line 47 in src/database/postgres/main.js

View workflow job for this annotation

GitHub Actions / test

Trailing spaces not allowed
return res.rows[0].e;
}

// Module Functions
module.flushdb = async function () {
await module.pool.query(`DROP SCHEMA "public" CASCADE`);
await module.pool.query(`CREATE SCHEMA "public"`);
await executeQuery(module.pool, { text: `DROP SCHEMA "public" CASCADE` });
await executeQuery(module.pool, { text: `CREATE SCHEMA "public"` });
};

module.emptydb = async function () {
await module.pool.query(`DELETE FROM "legacy_object"`);
await executeQuery(module.pool, { text: `DELETE FROM "legacy_object"` });
};

module.exists = async function (key) {
if (!key) {
return;
}
const isArray = Array.isArray(key);
if (isArray && !key.length) {
return [];
}
if (!key) return;

async function checkIfzSetsExist(keys) {
const members = await Promise.all(
keys.map(key => module.getSortedSetRange(key, 0, 0))
);
return members.map(member => member.length > 0);
}

async function checkIfKeysExist(keys) {
const res = await module.pool.query({
name: 'existsArray',
text: `
SELECT o."_key" k
FROM "legacy_object_live" o
WHERE o."_key" = ANY($1::TEXT[])`,
values: [keys],
});
return keys.map(k => res.rows.some(r => r.k === k));
}
const isArray = Array.isArray(key);
if (isArray && !key.length) return [];

// Redis/Mongo consider empty zsets as non-existent, match that behaviour
if (isArray) {
const types = await Promise.all(key.map(module.type));
const zsetKeys = key.filter((_key, i) => types[i] === 'zset');
const otherKeys = key.filter((_key, i) => types[i] !== 'zset');
const [zsetExits, otherExists] = await Promise.all([
checkIfzSetsExist(zsetKeys),
checkIfKeysExist(otherKeys),
const zsetKeys = key.filter((_, i) => types[i] === 'zset');
const otherKeys = key.filter((_, i) => types[i] !== 'zset');
const [zsetExists, otherExists] = await Promise.all([
checkIfzSetsExist(module, zsetKeys),
checkIfKeysExist(module, otherKeys),
]);
const existsMap = Object.create(null);
zsetKeys.forEach((k, i) => { existsMap[k] = zsetExits[i]; });
const existsMap = {};
zsetKeys.forEach((k, i) => { existsMap[k] = zsetExists[i]; });
otherKeys.forEach((k, i) => { existsMap[k] = otherExists[i]; });
return key.map(k => existsMap[k]);
}
const type = await module.type(key);
if (type === 'zset') {
const members = await module.getSortedSetRange(key, 0, 0);
return members.length > 0;
}
const res = await module.pool.query({
name: 'exists',
text: `
SELECT EXISTS(SELECT *
FROM "legacy_object_live"
WHERE "_key" = $1::TEXT
LIMIT 1) e`,
values: [key],
});

return res.rows[0].e;
return await checkExists(module, key);
};

module.scan = async function (params) {
Expand Down
13 changes: 13 additions & 0 deletions stryker.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "./node_modules/@stryker-mutator/core/schema/stryker-schema.json",
"_comment": "This config was generated using 'stryker init'. Please take a look at: https://stryker-mutator.io/docs/stryker-js/configuration/ for more information.",
"packageManager": "npm",
"reporters": [
"html",
"clear-text",
"progress"
],
"testRunner": "command",
"testRunner_comment": "Take a look at (missing 'homepage' URL in package.json) for information about the command plugin.",
"coverageAnalysis": "off"
}
10 changes: 10 additions & 0 deletions test/database/keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ describe('Key methods', () => {
});
});

it('should check for existence of both regular keys and zset keys', async () => {
await db.set('testRegularKey', 'value1');
await db.sortedSetAdd('testZsetKey', 1, 'member1');
const result = await db.exists(['testRegularKey', 'testZsetKey']);
assert.deepStrictEqual(result, [true, true]);
const nonExistingResult = await db.exists(['testRegularKey', 'nonExistingKey']);
assert.deepStrictEqual(nonExistingResult, [true, false]);
});


it('should return false if key does not exist', (done) => {
db.exists('doesnotexist', function (err, exists) {
assert.ifError(err);
Expand Down
Loading