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

Enhance plugins with an inline arithmetic feature #1004

Merged
merged 43 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
ca6b523
feat(builtins): add inline arithmetic logic into plugins
manushak Sep 6, 2024
796cf7e
test(builtins): add tests related to inline arithmetic feature
manushak Sep 6, 2024
27f6e27
feat(package): update if-core version
manushak Sep 9, 2024
3e198bf
feat(config): add strings for explain feature
manushak Aug 28, 2024
ccec981
feat(lib): update explain feature logic
manushak Aug 28, 2024
cd877b1
feat(types): add `ExplainStorageType` type
manushak Aug 28, 2024
c4574a5
test(lib): update tests and add new ones
manushak Aug 28, 2024
7d07ada
fix(lib): change default aggregation method
narekhovhannisyan Sep 4, 2024
5a86cf3
fix(builtins): add a bit of doc, remove additional 1 second
narekhovhannisyan Sep 4, 2024
20e56ee
test(builtins): update time sync
narekhovhannisyan Sep 4, 2024
943921e
feat(util): enable granular aggregation in helper
narekhovhannisyan Sep 9, 2024
4f01a8e
feat(types): use aggregation options as method
narekhovhannisyan Sep 9, 2024
35f8142
feat(types): enable time and component aggregations
narekhovhannisyan Sep 9, 2024
b58cbbf
fix(lib): update docs, improve readablity in initialize
narekhovhannisyan Sep 9, 2024
23bc5f9
feat(lib): use granular aggregation in explain
narekhovhannisyan Sep 9, 2024
5832a24
feat(lib): introduce granular aggregation to aggregate
narekhovhannisyan Sep 9, 2024
ee6c2ab
feat(config): rename additional params to time metrics
narekhovhannisyan Sep 9, 2024
3c07a4a
feat(builtins): use granular aggregation in time sync
narekhovhannisyan Sep 9, 2024
1f278ec
feat(builtins): use granular aggregation methods in sci embodied
narekhovhannisyan Sep 9, 2024
f76ab33
feat(builtins): use granular aggregation methods in sci
narekhovhannisyan Sep 9, 2024
ae24412
feat(src): simplify if-run index
narekhovhannisyan Sep 9, 2024
78de556
feat(util): introduce granular aggregation to validation
narekhovhannisyan Sep 9, 2024
dc1ccc7
feat(types): enable time and component aggregations in manifest
narekhovhannisyan Sep 9, 2024
39367ac
test(util): tune aggregation helper units
narekhovhannisyan Sep 9, 2024
e9999d7
test(lib): tune explain units
narekhovhannisyan Sep 9, 2024
dd88ca8
test(lib): tune aggregate units
narekhovhannisyan Sep 9, 2024
91180e0
test(builtins): tune time-sync units
narekhovhannisyan Sep 9, 2024
921f461
feat(package): update if-core version
narekhovhannisyan Sep 10, 2024
116e48f
fix(builtins): fix output param of sci embodied
narekhovhannisyan Sep 10, 2024
cda5681
feat(src): add support for appending to existing outputs
jamescrowley Aug 4, 2024
4e8c5e1
test(lib): make the regroup intended behaviour clearer
jamescrowley Aug 16, 2024
a9ab295
test(lib): fix typos in test names
jamescrowley Aug 17, 2024
3d51191
refactor(lib): refactor regroup so we can then include outputs
jamescrowley Aug 19, 2024
c860286
refactor(lib): extract function for looking up group key value
jamescrowley Aug 19, 2024
fa06cfa
refactor(lib): remove unnecessary spread
jamescrowley Aug 19, 2024
4aa79e1
feat(lib): apply regroup to outputs not just inputs
jamescrowley Aug 20, 2024
7279f92
fix(builtins): minor fix
manushak Sep 17, 2024
af3c600
fix(builtins): minor fix
manushak Sep 17, 2024
e3fd10f
fix(builtins): minor fix
manushak Sep 17, 2024
982cfca
feat(src): add support for appending to existing outputs
jamescrowley Aug 4, 2024
7618d8b
feat(lib): apply regroup to outputs not just inputs
jamescrowley Aug 20, 2024
f381e56
fix(builtins): fix linter error
manushak Sep 17, 2024
13761ed
Merge branch 'main' into inline-arithmetic
manushak Sep 17, 2024
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
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"dependencies": {
"@commitlint/cli": "^18.6.0",
"@commitlint/config-conventional": "^18.6.0",
"@grnsft/if-core": "^0.0.22",
"@grnsft/if-core": "^0.0.23",
"axios": "^1.7.2",
"csv-parse": "^5.5.6",
"csv-stringify": "^6.4.6",
Expand Down
74 changes: 73 additions & 1 deletion src/__tests__/if-run/builtins/coefficient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {ERRORS} from '@grnsft/if-core/utils';
import {Coefficient} from '../../../if-run/builtins/coefficient';

import {STRINGS} from '../../../if-run/config';
import {CoefficientConfig} from '@grnsft/if-core/types';

const {InputValidationError, ConfigError} = ERRORS;
const {MISSING_CONFIG} = STRINGS;
Expand Down Expand Up @@ -113,7 +114,78 @@ describe('builtins/coefficient: ', () => {
expect(result).toStrictEqual(expectedResult);
});

it('throws an error when global config is not provided.', () => {
it('successfully executes when a parameter has an arithmetic expression.', () => {
expect.assertions(1);
const config = {
'input-parameter': '=3*carbon',
coefficient: 3,
'output-parameter': 'carbon-product',
};
const parametersMetadata = {
inputs: {},
outputs: {},
};
const coefficient = Coefficient(config, parametersMetadata, {});

const expectedResult = [
{
duration: 3600,
carbon: 3,
'carbon-product': 27,
timestamp: '2021-01-01T00:00:00Z',
},
];

const result = coefficient.execute([
{
duration: 3600,
carbon: 3,
timestamp: '2021-01-01T00:00:00Z',
},
]);

expect.assertions(1);

expect(result).toStrictEqual(expectedResult);
});

it('throws an error when the `coefficient` has wrong arithmetic expression.', () => {
const config = {
'input-parameter': 'carbon',
coefficient: 'mock-param',
'output-parameter': 'carbon-product',
};
const parametersMetadata = {
inputs: {},
outputs: {},
};
const coefficient = Coefficient(
config as any as CoefficientConfig,
parametersMetadata,
{}
);

expect.assertions(2);

try {
coefficient.execute([
{
duration: 3600,
carbon: 'some-param',
timestamp: '2021-01-01T00:00:00Z',
},
]);
} catch (error) {
expect(error).toBeInstanceOf(Error);
expect(error).toEqual(
new InputValidationError(
'"coefficient" parameter is expected number, received string. Error code: invalid_type.'
)
);
}
});

it('throws an error when config is not provided.', () => {
const config = undefined;
const coefficient = Coefficient(config!, parametersMetadata, {});

Expand Down
30 changes: 30 additions & 0 deletions src/__tests__/if-run/builtins/copy-param.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,36 @@ describe('builtins/copy: ', () => {

expect(result).toStrictEqual(expectedResult);
});

it('successfully executes when the `from` contains arithmetic expression', () => {
const config = {
'keep-existing': false,
from: '=3*size',
to: 'if-size',
};
const copy = Copy(config, parametersMetadata, {});

const inputs = [
{
timestamp: '2024-07-05T13:45:48.398Z',
duration: 3600,
size: 0.05,
},
];

const expectedResult = [
{
timestamp: '2024-07-05T13:45:48.398Z',
duration: 3600,
'if-size': 0.15000000000000002,
},
];

expect.assertions(1);
const result = copy.execute(inputs);

expect(result).toEqual(expectedResult);
});
});
});
});
61 changes: 60 additions & 1 deletion src/__tests__/if-run/builtins/divide.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ describe('builtins/divide: ', () => {
expect(result).toStrictEqual(expectedResult);
});

it('returns a result when `denominator` is provded in input.', async () => {
it('returns a result when `denominator` is provided in input.', async () => {
expect.assertions(1);
const config = {
numerator: 'vcpus-allocated',
Expand Down Expand Up @@ -137,6 +137,65 @@ describe('builtins/divide: ', () => {
expect(response).toEqual(expectedResult);
});

it('successfully executes when a parameter contains arithmetic expression.', () => {
expect.assertions(1);

const config = {
numerator: '=3*"vcpus-allocated"',
denominator: 'duration',
output: 'vcpus-allocated-per-second',
};

const divide = Divide(config, parametersMetadata, {});
const input = [
{
timestamp: '2021-01-01T00:00:00Z',
duration: 3600,
'vcpus-allocated': 24,
},
];
const response = divide.execute(input);

const expectedResult = [
{
timestamp: '2021-01-01T00:00:00Z',
duration: 3600,
'vcpus-allocated': 24,
'vcpus-allocated-per-second': 72 / 3600,
},
];

expect(response).toEqual(expectedResult);
});

it('throws an error the `numerator` parameter has wrong arithmetic expression.', () => {
const config = {
numerator: '3*"vcpus-allocated"',
denominator: 'duration',
output: 'vcpus-allocated-per-second',
};

const divide = Divide(config, parametersMetadata, {});
const inputs = [
{
timestamp: '2021-01-01T00:00:00Z',
duration: 3600,
'vcpus-allocated': 24,
},
];
expect.assertions(2);
try {
divide.execute(inputs);
} catch (error) {
expect(error).toBeInstanceOf(Error);
expect(error).toEqual(
new InputValidationError(
'The `numerator` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`.'
)
);
}
});

it('throws an error on missing params in input.', async () => {
const expectedMessage =
'"vcpus-allocated" parameter is required. Error code: invalid_type.';
Expand Down
100 changes: 97 additions & 3 deletions src/__tests__/if-run/builtins/exponent.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import {ExponentConfig} from '@grnsft/if-core/types';
import {ERRORS} from '@grnsft/if-core/utils';

import {STRINGS} from '../../../if-run/config';
import {Exponent} from '../../../if-run/builtins/exponent';

const {InputValidationError} = ERRORS;
const {InputValidationError, ConfigError} = ERRORS;

const {MISSING_CONFIG} = STRINGS;

describe('builtins/exponent: ', () => {
describe('Exponent: ', () => {
Expand Down Expand Up @@ -124,7 +128,7 @@ describe('builtins/exponent: ', () => {
} catch (error) {
expect(error).toStrictEqual(
new InputValidationError(
'"input-parameter" parameter is required. Error code: invalid_type.'
'"energy/base" parameter is required. Error code: invalid_type.'
)
);
}
Expand All @@ -145,7 +149,7 @@ describe('builtins/exponent: ', () => {
} catch (error) {
expect(error).toStrictEqual(
new InputValidationError(
'"input-parameter" parameter is expected number, received string. Error code: invalid_type.'
'"energy/base" parameter is expected number, received string. Error code: invalid_type.'
)
);
}
Expand Down Expand Up @@ -180,6 +184,96 @@ describe('builtins/exponent: ', () => {

expect(response).toEqual(expectedResult);
});

it('successfully executes when a parameter contains arithmetic expression.', () => {
const config = {
'input-parameter': "=2*'energy/base'",
exponent: 3,
'output-parameter': 'energy',
};
const parametersMetadata = {
inputs: {},
outputs: {},
};

const exponent = Exponent(config, parametersMetadata, {});

expect.assertions(1);

const expectedResult = [
{
duration: 3600,
'energy/base': 4,
energy: 512,
timestamp: '2021-01-01T00:00:00Z',
},
];

const result = exponent.execute([
{
duration: 3600,
'energy/base': 4,
timestamp: '2021-01-01T00:00:00Z',
},
]);

expect(result).toStrictEqual(expectedResult);
});

it('throws an error when the `exponent` has wrong arithmetic expression.', () => {
const config = {
'input-parameter': "=2*'energy/base'",
exponent: "3*'mock-param'",
'output-parameter': 'energy',
};
const parametersMetadata = {
inputs: {},
outputs: {},
};

const exponent = Exponent(
config as any as ExponentConfig,
parametersMetadata,
{}
);

expect.assertions(2);

try {
exponent.execute([
{
duration: 3600,
'energy/base': 4,
timestamp: '2021-01-01T00:00:00Z',
},
]);
} catch (error) {
expect(error).toBeInstanceOf(Error);
expect(error).toEqual(
new InputValidationError(
'The `exponent` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`.'
)
);
}
});
});

it('throws an error on missing config.', async () => {
const config = undefined;
const divide = Exponent(config!, parametersMetadata, {});

expect.assertions(1);

try {
await divide.execute([
{
timestamp: '2021-01-01T00:00:00Z',
duration: 3600,
},
]);
} catch (error) {
expect(error).toStrictEqual(new ConfigError(MISSING_CONFIG));
}
});
});
});
Loading