blob: 0f5c1aec881e9acf5efc177d2b1d0b09392ec9a1 [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { GET_STATS } from './get-stats.command.js';
import { DeserializeError } from '../error.utils.js';
const u32 = (value: number) => {
const b = Buffer.alloc(4);
b.writeUInt32LE(value);
return b;
};
const u64 = (value: bigint) => {
const b = Buffer.alloc(8);
b.writeBigUInt64LE(value);
return b;
};
const f32 = (value: number) => {
const b = Buffer.alloc(4);
b.writeFloatLE(value);
return b;
};
const str = (value: string) =>
Buffer.concat([u32(Buffer.byteLength(value)), Buffer.from(value)]);
const cacheMetric = (streamId: number, topicId: number, partitionId: number) =>
Buffer.concat([
u32(streamId), u32(topicId), u32(partitionId),
u64(1000n), u64(50n), f32(0.95)
]);
const buildStatsPayload = (openFiles?: { count: bigint, limit: bigint }) =>
Buffer.concat([
u32(1234), f32(25.5), f32(50),
u64(1_073_741_824n), u64(8_589_934_592n), u64(4_294_967_296n),
u64(3600n), u64(1_710_000_000_000n), u64(1_000_000n), u64(500_000n),
u64(2_000_000n),
u32(3), u32(10), u32(30), u32(90), u64(50_000n), u32(5), u32(2),
str('node-1'), str('Linux'), str('6.1'), str('6.1.0'), str('0.6.0'),
u32(600),
u32(2), cacheMetric(1, 1, 0), cacheMetric(2, 3, 1),
u32(16), u64(107_374_182_400n), u64(512_110_190_592n),
...(openFiles ? [u64(openFiles.count), u64(openFiles.limit)] : [])
]);
const deserialize = (data: Buffer) =>
GET_STATS.deserialize({ status: 0, length: data.length, data });
describe('GetStats Command', () => {
it('deserializes open files count and limit', () => {
const stats = deserialize(
buildStatsPayload({ count: 1_234n, limit: 1_048_576n })
);
assert.equal(stats.processId, 1234);
assert.equal(stats.kernelVersion, '6.1.0');
assert.equal(stats.openFilesCount, 1_234n);
assert.equal(stats.openFilesLimit, 1_048_576n);
});
it('deserializes server version, cache metrics, threads and disk space', () => {
const stats = deserialize(buildStatsPayload());
assert.equal(stats.iggyServerVersion, '0.6.0');
assert.equal(stats.iggyServerSemver, 600);
assert.deepEqual(stats.cacheMetrics, [
{
streamId: 1, topicId: 1, partitionId: 0,
hits: 1000n, misses: 50n, hitRatio: Math.fround(0.95)
},
{
streamId: 2, topicId: 3, partitionId: 1,
hits: 1000n, misses: 50n, hitRatio: Math.fround(0.95)
}
]);
assert.equal(stats.threadsCount, 16);
assert.equal(stats.freeDiskSpace, 107_374_182_400n);
assert.equal(stats.totalDiskSpace, 512_110_190_592n);
});
it('reads open files fields as 0 when the reply ends at total_disk_space', () => {
const stats = deserialize(buildStatsPayload());
assert.equal(stats.kernelVersion, '6.1.0');
assert.equal(stats.openFilesCount, 0n);
assert.equal(stats.openFilesLimit, 0n);
});
it('throws on truncated open files fields', () => {
const payload = buildStatsPayload({ count: 1_234n, limit: 1_048_576n });
for (let cut = 1; cut < 16; cut += 1)
assert.throws(
() => deserialize(payload.subarray(0, payload.length - cut)),
DeserializeError
);
});
it('throws on a reply truncated before total_disk_space ends', () => {
const payload = buildStatsPayload();
for (let length = 0; length < payload.length; length += 1)
assert.throws(
() => deserialize(payload.subarray(0, length)),
DeserializeError,
`a reply cut to ${length} bytes must not decode`
);
});
});