You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by vl...@apache.org on 2026/03/25 14:32:26 UTC
(jmeter) branch master updated: Replace vendored matrix_builder with npm @vlsi/github-actions-random-matrix
This is an automated email from the ASF dual-hosted git repository.
vladimirsitnikov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git
The following commit(s) were added to refs/heads/master by this push:
new e25de766e7 Replace vendored matrix_builder with npm @vlsi/github-actions-random-matrix
e25de766e7 is described below
commit e25de766e7ef72dfbfd84b0ac7641310683bd0b5
Author: Vladimir Sitnikov <si...@gmail.com>
AuthorDate: Wed Mar 25 16:42:37 2026 +0300
Replace vendored matrix_builder with npm @vlsi/github-actions-random-matrix
Use the published npm package instead of vendored matrix_builder.js,
converting to ESM modules (.mjs) with seeded RNG from the package.
Co-Authored-By: Claude Opus 4.6 (1M context) <no...@anthropic.com>
---
.github/workflows/main.yml | 3 +-
.github/workflows/{matrix.js => matrix.mjs} | 14 +-
.github/workflows/matrix_builder.js | 255 ----------------------------
.github/workflows/package-lock.json | 21 +++
.github/workflows/package.json | 7 +
.gitignore | 1 +
6 files changed, 38 insertions(+), 263 deletions(-)
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 14164ac079..4a44114626 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -30,7 +30,8 @@ jobs:
- uses: actions/checkout@v6
- id: set-matrix
run: |
- node .github/workflows/matrix.js
+ npm ci --prefix .github/workflows
+ node .github/workflows/matrix.mjs
test:
needs: matrix_prep
diff --git a/.github/workflows/matrix.js b/.github/workflows/matrix.mjs
similarity index 93%
rename from .github/workflows/matrix.js
rename to .github/workflows/matrix.mjs
index aad48000fd..fa4f79ca9d 100644
--- a/.github/workflows/matrix.js
+++ b/.github/workflows/matrix.mjs
@@ -1,10 +1,10 @@
// The script generates a random subset of valid jdk, os, timezone, and other axes.
-// You can preview the results by running "node matrix.js"
+// You can preview the results by running "node matrix.mjs"
// See https://github.com/vlsi/github-actions-random-matrix
-let fs = require('fs');
-let os = require('os');
-let {MatrixBuilder} = require('./matrix_builder');
-const matrix = new MatrixBuilder();
+import { appendFileSync } from 'fs';
+import { EOL } from 'os';
+import { createGitHubMatrixBuilder } from '@vlsi/github-actions-random-matrix/github';
+const { matrix, random } = createGitHubMatrixBuilder();
matrix.addAxis({
name: 'java_distribution',
values: [
@@ -130,7 +130,7 @@ include.forEach(v => {
v.oracle_java_website = v.java_version === eaJava ? 'jdk.java.net' : 'oracle.com';
}
v.non_ea_java_version = v.java_version === eaJava ? '' : v.java_version;
- if (v.java_distribution !== 'semeru' && Math.random() > 0.5) {
+ if (v.java_distribution !== 'semeru' && random() > 0.5) {
// The following options randomize instruction selection in JIT compiler
// so it might reveal missing synchronization
v.name += ', stress JIT';
@@ -164,7 +164,7 @@ console.log(include);
let filePath = process.env['GITHUB_OUTPUT'] || '';
if (filePath) {
- fs.appendFileSync(filePath, `matrix<<MATRIX_BODY${os.EOL}${JSON.stringify({include})}${os.EOL}MATRIX_BODY${os.EOL}`, {
+ appendFileSync(filePath, `matrix<<MATRIX_BODY${EOL}${JSON.stringify({include})}${EOL}MATRIX_BODY${EOL}`, {
encoding: 'utf8'
});
}
diff --git a/.github/workflows/matrix_builder.js b/.github/workflows/matrix_builder.js
deleted file mode 100644
index 0c17190ede..0000000000
--- a/.github/workflows/matrix_builder.js
+++ /dev/null
@@ -1,255 +0,0 @@
-// License: Apache-2.0
-// Copyright Vladimir Sitnikov, 2021
-// See https://github.com/vlsi/github-actions-random-matrix
-
-class Axis {
- constructor({name, title, values}) {
- this.name = name;
- this.title = title;
- this.values = values;
- // If all entries have same weight, the axis has uniform distribution
- this.uniform = values.reduce((a, b) => a === (b.weight || 1) ? a : 0, values[0].weight || 1) !== 0
- this.totalWeight = this.uniform ? values.length : values.reduce((a, b) => a + (b.weight || 1), 0);
- }
-
- static matches(row, filter) {
- if (typeof filter === 'function') {
- return filter(row);
- }
- if (Array.isArray(filter)) {
- // e.g. row={os: 'windows'}; filter=[{os: 'linux'}, {os: 'linux'}]
- return filter.some(v => Axis.matches(row, v));
- }
- if (typeof filter === 'object') {
- // e.g. row={jdk: {name: 'openjdk', version: 8}}; filter={jdk: {version: 8}}
- for (const [key, value] of Object.entries(filter)) {
- if (!row.hasOwnProperty(key) || !Axis.matches(row[key], value)) {
- return false;
- }
- }
- return true;
- }
- return row === filter;
- }
-
- pickValue(filter) {
- let values = this.values;
- if (filter) {
- values = values.filter(v => Axis.matches(v, filter));
- }
- if (values.length === 0) {
- const filterStr = typeof filter === 'string' ? filter.toString() : JSON.stringify(filter);
- throw Error(`No values produces for axis '${this.name}' from ${JSON.stringify(this.values)}, filter=${filterStr}`);
- }
- if (values.length === 1) {
- return values[0];
- }
- if (this.uniform) {
- return values[Math.floor(Math.random() * values.length)];
- }
- const totalWeight = !filter ? this.totalWeight : values.reduce((a, b) => a + (b.weight || 1), 0);
- let weight = Math.random() * totalWeight;
- for (let i = 0; i < values.length; i++) {
- const value = values[i];
- weight -= value.weight || 1;
- if (weight <= 0) {
- return value;
- }
- }
- return values[values.length - 1];
- }
-}
-
-class MatrixBuilder {
- constructor() {
- this.axes = [];
- this.axisByName = {};
- this.rows = [];
- this.duplicates = {};
- this.excludes = [];
- this.includes = [];
- this.implications = [];
- this.failOnUnsatisfiableFilters = false;
- }
-
- /**
- * Specifies include filter (all the generated rows would comply with all the include filters)
- * @param filter
- */
- include(filter) {
- this.includes.push(filter);
- }
-
- /**
- * Specifies exclude filter (e.g. exclude a forbidden combination).
- * @param filter
- */
- exclude(filter) {
- this.excludes.push(filter);
- }
-
- /**
- * Adds implication like `antecedent -> consequent`.
- * In other words, if `antecedent` holds, then `consequent` must also hold.
- * @param antecedent
- * @param consequent
- */
- imply(antecedent, consequent) {
- this.implications.push({antecedent: antecedent, consequent: consequent});
- }
-
- addAxis({name, title, values}) {
- const axis = new Axis({name, title, values});
- this.axes.push(axis);
- this.axisByName[name] = axis;
- return axis;
- }
-
- setNamePattern(names) {
- this.namePattern = names;
- }
-
- /**
- * Returns true if the row matches the include and exclude filters.
- * @param row input row
- * @returns {boolean}
- */
- matches(row) {
- return (this.excludes.length === 0 || !this.excludes.some(f => Axis.matches(row, f))) &&
- (this.includes.length === 0 || this.includes.some(f => Axis.matches(row, f))) &&
- (this.implications.length === 0 || (
- this.implications.every(i => !Axis.matches(row, i.antecedent) || Axis.matches(row, i.consequent))));
- }
-
- failOnUnsatisfiableFilters(value) {
- this.failOnUnsatisfiableFilters = value;
- }
-
- /**
- * Adds a row that matches the given filter to the resulting matrix.
- * filter values could be
- * - literal values: filter={os: 'windows-latest'}
- * - arrays: filter={os: ['windows-latest', 'linux-latest']}
- * - functions: filter={os: x => x!='windows-latest'}
- * @param filter object with keys matching axes names
- * @returns {*}
- */
- generateRow(filter) {
- let res;
- if (filter) {
- // If matching row already exists, no need to generate more
- res = this.rows.some(v => Axis.matches(v, filter));
- if (res) {
- return res;
- }
- }
- for (let i = 0; i < 142; i++) {
- res = this.axes.reduce(
- (prev, next) =>
- Object.assign(prev, {
- [next.name]: next.pickValue(filter ? filter[next.name] : undefined)
- }),
- {}
- );
- if (!this.matches(res)) {
- continue;
- }
- const key = JSON.stringify(res);
- if (!this.duplicates.hasOwnProperty(key)) {
- this.duplicates[key] = true;
- res.name =
- this.namePattern.map(axisName => {
- let value = res[axisName];
- const title = value.title;
- if (typeof title != 'undefined') {
- return title;
- }
- const computeTitle = this.axisByName[axisName].title;
- if (computeTitle) {
- return computeTitle(value);
- }
- if (typeof value === 'object' && value.hasOwnProperty('value')) {
- return value.value;
- }
- return value;
- }).filter(Boolean).join(", ");
- this.rows.push(res);
- return res;
- }
- }
- const filterStr = typeof filter === 'string' ? filter.toString() : JSON.stringify(filter);
- const msg = `Unable to generate row for ${filterStr}. Please check include and exclude filters`;
- if (this.failOnUnsatisfiableFilters) {
- throw Error(msg);
- } else {
- console.warn(msg);
- }
- }
-
- generateRows(maxRows, filter) {
- for (let i = 0; this.rows.length < maxRows && i < maxRows; i++) {
- this.generateRow(filter);
- }
- return this.rows;
- }
-
- /**
- * Computes the number of all the possible combinations.
- * @returns {{bad: number, good: number}}
- */
- summary() {
- let position = -1;
- let indices = [];
- let values = {};
- const axes = this.axes;
- function resetValuesUpTo(nextPosition) {
- for(let i=0; i<nextPosition; i++) {
- const axis = axes[i];
- values[axis.name] = axis.values[0];
- indices[i] = 1; // next index
- }
- position = 0;
- }
-
- function nextAvailablePosition() {
- let size = axes.length;
- for (let i = position; i < size; i++) {
- if (indices[i] < axes[i].values.length) {
- return i;
- }
- }
- return -1;
- }
- // The first initialization of the values
- resetValuesUpTo(this.axes.length);
- let good = 0;
- let bad = 0;
- while (true) {
- if (indices[position] < this.axes[position].values.length) {
- // Advance iterator at the current position if possible
- const axis = this.axes[position];
- values[axis.name] = axis.values[indices[position]];
- indices[position]++;
- } else {
- // Advance the next iterator, and reset [0..nextPosition)
- position++;
- let nextPosition = nextAvailablePosition();
- if (nextPosition === -1) {
- break;
- }
- const axis = this.axes[nextPosition];
- values[axis.name] = axis.values[indices[nextPosition]];
- indices[nextPosition]++;
- resetValuesUpTo(nextPosition);
- }
- if (this.matches(values)) {
- good++;
- } else {
- bad++;
- }
- }
- return {good: good, bad: bad};
- }
-}
-
-module.exports = {Axis, MatrixBuilder};
diff --git a/.github/workflows/package-lock.json b/.github/workflows/package-lock.json
new file mode 100644
index 0000000000..8e51ba5949
--- /dev/null
+++ b/.github/workflows/package-lock.json
@@ -0,0 +1,21 @@
+{
+ "name": "workflows",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "dependencies": {
+ "@vlsi/github-actions-random-matrix": "2.0.0"
+ }
+ },
+ "node_modules/@vlsi/github-actions-random-matrix": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@vlsi/github-actions-random-matrix/-/github-actions-random-matrix-2.0.0.tgz",
+ "integrity": "sha512-8lEb4eadMBKs+Hnj9dCmcHtgHoWelT4RMXAQ/VcQ1r3vjR8P2hSMVGhkRXaXibCBf0lMttS934CGo2mlBMopPA==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=16"
+ }
+ }
+ }
+}
diff --git a/.github/workflows/package.json b/.github/workflows/package.json
new file mode 100644
index 0000000000..a66b1aa6f4
--- /dev/null
+++ b/.github/workflows/package.json
@@ -0,0 +1,7 @@
+{
+ "private": true,
+ "type": "module",
+ "dependencies": {
+ "@vlsi/github-actions-random-matrix": "2.0.0"
+ }
+}
diff --git a/.gitignore b/.gitignore
index b4714dd560..31dc34b4b3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,6 +84,7 @@ jmeter-fb.*
*.iml
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+node_modules
hs_err_pid*
# other jvm related files
.attach_*