From 913c1b7836aaf490548b4896169c50376e6e1e53 Mon Sep 17 00:00:00 2001 From: KernelDeimos Date: Tue, 28 Jan 2025 16:16:00 -0500 Subject: [PATCH] test: add unit test for TimeWindow TimeWindow is used by TrackSpendingService for two purposes: - tracking cost within a time window - preventing duplicate alarms within a cooldown period It is important to test this to ensure alarms related to AI costs are accurate. --- src/backend/src/util/opmath.js | 7 ++--- src/backend/src/util/opmath.test.js | 40 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 src/backend/src/util/opmath.test.js diff --git a/src/backend/src/util/opmath.js b/src/backend/src/util/opmath.js index 6dd15512..e2dce874 100644 --- a/src/backend/src/util/opmath.js +++ b/src/backend/src/util/opmath.js @@ -143,16 +143,17 @@ class MovingMode extends StreamReducer { } class TimeWindow { - constructor ({ window_duration, reducer }) { + constructor ({ window_duration, reducer, now }) { this.window_duration = window_duration; this.reducer = reducer; this.entries_ = []; + this.now = now ?? Date.now; } add (value) { this.remove_stale_entries_(); - const timestamp = Date.now(); + const timestamp = this.now(); this.entries_.push({ timestamp, value, @@ -174,7 +175,7 @@ class TimeWindow { remove_stale_entries_ () { let i = 0; - const current_ts = Date.now(); + const current_ts = this.now(); for ( ; i < this.entries_.length ; i++ ) { const entry = this.entries_[i]; // as soon as an entry is in the window we can break, diff --git a/src/backend/src/util/opmath.test.js b/src/backend/src/util/opmath.test.js new file mode 100644 index 00000000..1914e321 --- /dev/null +++ b/src/backend/src/util/opmath.test.js @@ -0,0 +1,40 @@ +const { expect } = require('chai'); + +describe('opmath', () => { + describe('TimeWindow', () => { + it('clears old entries', () => { + const { TimeWindow } = require('./opmath'); + let now_value = 0; + const now = () => now_value; + const window = new TimeWindow({ window_duration: 1000, now }); + + window.add(1); + window.add(2); + window.add(3); + + now_value = 900; + + window.add(4); + window.add(5); + window.add(6); + + expect(window.get()).to.deep.equal([1, 2, 3, 4, 5, 6]); + + now_value = 1100; + + window.add(7); + window.add(8); + window.add(9); + + expect(window.get()).to.deep.equal([4, 5, 6, 7, 8, 9]); + + now_value = 2000; + + expect(window.get()).to.deep.equal([7, 8, 9]); + + now_value = 2200; + + expect(window.get()).to.deep.equal([]); + }) + }) +}); \ No newline at end of file