@synnaxlabs/client 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.DS_Store +0 -0
- package/.editorconfig +15 -0
- package/.eslintrc.json +33 -0
- package/.gitignore +9 -0
- package/.nyc_output/20720f2d-6abe-420f-a3c5-304d52d60827.json +1 -0
- package/.nyc_output/4725921c-6f1b-4ae9-9819-e455f702d31c.json +1 -0
- package/.nyc_output/47478588-5ffd-4332-873c-facaa4a2fc38.json +1 -0
- package/.nyc_output/48180641-e0b2-49ab-a6eb-e7910e9eac2f.json +1 -0
- package/.nyc_output/cb0abf31-740f-47db-b94a-8e3f8f117cb8.json +1 -0
- package/.nyc_output/fc77fce2-dad0-49a8-8d4b-0a9014ecf8c5.json +1 -0
- package/.nyc_output/processinfo/20720f2d-6abe-420f-a3c5-304d52d60827.json +1 -0
- package/.nyc_output/processinfo/4725921c-6f1b-4ae9-9819-e455f702d31c.json +1 -0
- package/.nyc_output/processinfo/47478588-5ffd-4332-873c-facaa4a2fc38.json +1 -0
- package/.nyc_output/processinfo/48180641-e0b2-49ab-a6eb-e7910e9eac2f.json +1 -0
- package/.nyc_output/processinfo/cb0abf31-740f-47db-b94a-8e3f8f117cb8.json +1 -0
- package/.nyc_output/processinfo/fc77fce2-dad0-49a8-8d4b-0a9014ecf8c5.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -0
- package/.prettierignore +2 -0
- package/CHANGELOG.md +5 -0
- package/build/main/index.d.ts +1 -1
- package/build/main/index.js +2 -3
- package/build/main/lib/auth.d.ts +54 -0
- package/build/main/lib/auth.js +62 -0
- package/build/main/lib/auth.spec.d.ts +1 -0
- package/build/main/lib/auth.spec.js +39 -0
- package/build/main/lib/channel/channel.spec.js +17 -3
- package/build/main/lib/channel/client.d.ts +2 -2
- package/build/main/lib/channel/client.js +6 -3
- package/build/main/lib/channel/payload.d.ts +2 -2
- package/build/main/lib/client.d.ts +13 -6
- package/build/main/lib/client.js +16 -4
- package/build/main/lib/segment/iterator.spec.js +14 -3
- package/build/main/lib/segment/typed.js +4 -4
- package/build/main/lib/segment/writer.spec.js +17 -3
- package/build/main/lib/telem.d.ts +2 -2
- package/build/main/lib/telem.js +4 -4
- package/build/main/lib/telem.spec.js +4 -2
- package/build/main/lib/transport.d.ts +2 -1
- package/build/main/lib/transport.js +5 -1
- package/build/main/lib/user/payload.d.ts +12 -0
- package/build/main/lib/user/payload.js +9 -0
- package/build/main/setupspecs.d.ts +4 -0
- package/build/main/setupspecs.js +17 -0
- package/build/module/index.d.ts +1 -1
- package/build/module/index.js +2 -2
- package/build/module/lib/auth.d.ts +54 -0
- package/build/module/lib/auth.js +63 -0
- package/build/module/lib/auth.spec.d.ts +1 -0
- package/build/module/lib/auth.spec.js +34 -0
- package/build/module/lib/channel/channel.spec.js +17 -3
- package/build/module/lib/channel/client.d.ts +2 -2
- package/build/module/lib/channel/client.js +6 -3
- package/build/module/lib/channel/payload.d.ts +2 -2
- package/build/module/lib/client.d.ts +13 -6
- package/build/module/lib/client.js +17 -4
- package/build/module/lib/segment/iterator.spec.js +14 -3
- package/build/module/lib/segment/typed.js +5 -5
- package/build/module/lib/segment/writer.spec.js +18 -4
- package/build/module/lib/telem.d.ts +2 -2
- package/build/module/lib/telem.js +4 -4
- package/build/module/lib/telem.spec.js +5 -3
- package/build/module/lib/transport.d.ts +2 -1
- package/build/module/lib/transport.js +5 -1
- package/build/module/lib/user/payload.d.ts +12 -0
- package/build/module/lib/user/payload.js +6 -0
- package/build/module/setupspecs.d.ts +4 -0
- package/build/module/setupspecs.js +16 -0
- package/build/tsconfig.module.tsbuildinfo +1 -0
- package/build/tsconfig.tsbuildinfo +1 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +191 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +191 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov-report/src/index.html +116 -0
- package/coverage/lcov-report/src/lib/auth.ts.html +340 -0
- package/coverage/lcov-report/src/lib/channel/client.ts.html +604 -0
- package/coverage/lcov-report/src/lib/channel/creator.ts.html +304 -0
- package/coverage/lcov-report/src/lib/channel/index.html +176 -0
- package/coverage/lcov-report/src/lib/channel/payload.ts.html +139 -0
- package/coverage/lcov-report/src/lib/channel/registry.ts.html +202 -0
- package/coverage/lcov-report/src/lib/channel/retriever.ts.html +244 -0
- package/coverage/lcov-report/src/lib/client.ts.html +244 -0
- package/coverage/lcov-report/src/lib/errors.ts.html +484 -0
- package/coverage/lcov-report/src/lib/index.html +176 -0
- package/coverage/lcov-report/src/lib/segment/client.ts.html +463 -0
- package/coverage/lcov-report/src/lib/segment/index.html +206 -0
- package/coverage/lcov-report/src/lib/segment/iterator.ts.html +928 -0
- package/coverage/lcov-report/src/lib/segment/payload.ts.html +139 -0
- package/coverage/lcov-report/src/lib/segment/splitter.ts.html +181 -0
- package/coverage/lcov-report/src/lib/segment/typed.ts.html +307 -0
- package/coverage/lcov-report/src/lib/segment/validator.ts.html +331 -0
- package/coverage/lcov-report/src/lib/segment/writer.ts.html +727 -0
- package/coverage/lcov-report/src/lib/telem.ts.html +2056 -0
- package/coverage/lcov-report/src/lib/transport.ts.html +196 -0
- package/coverage/lcov-report/src/lib/user/index.html +116 -0
- package/coverage/lcov-report/src/lib/user/payload.ts.html +109 -0
- package/coverage/lcov-report/src/lib/util/index.html +116 -0
- package/coverage/lcov-report/src/lib/util/telem.ts.html +124 -0
- package/coverage/lcov-report/src/setupspecs.ts.html +133 -0
- package/coverage/lcov.info +1230 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +196 -0
- package/coverage/src/index.html +116 -0
- package/coverage/src/lib/auth.ts.html +340 -0
- package/coverage/src/lib/channel/client.ts.html +604 -0
- package/coverage/src/lib/channel/creator.ts.html +304 -0
- package/coverage/src/lib/channel/index.html +176 -0
- package/coverage/src/lib/channel/payload.ts.html +139 -0
- package/coverage/src/lib/channel/registry.ts.html +202 -0
- package/coverage/src/lib/channel/retriever.ts.html +244 -0
- package/coverage/src/lib/client.ts.html +244 -0
- package/coverage/src/lib/errors.ts.html +484 -0
- package/coverage/src/lib/index.html +176 -0
- package/coverage/src/lib/segment/client.ts.html +463 -0
- package/coverage/src/lib/segment/index.html +206 -0
- package/coverage/src/lib/segment/iterator.ts.html +928 -0
- package/coverage/src/lib/segment/payload.ts.html +139 -0
- package/coverage/src/lib/segment/splitter.ts.html +181 -0
- package/coverage/src/lib/segment/typed.ts.html +307 -0
- package/coverage/src/lib/segment/validator.ts.html +331 -0
- package/coverage/src/lib/segment/writer.ts.html +727 -0
- package/coverage/src/lib/telem.ts.html +2056 -0
- package/coverage/src/lib/transport.ts.html +196 -0
- package/coverage/src/lib/user/index.html +116 -0
- package/coverage/src/lib/user/payload.ts.html +109 -0
- package/coverage/src/lib/util/index.html +116 -0
- package/coverage/src/lib/util/telem.ts.html +124 -0
- package/coverage/src/setupspecs.ts.html +133 -0
- package/package.json +2 -2
- package/src/index.ts +13 -0
- package/src/lib/.DS_Store +0 -0
- package/src/lib/auth.spec.ts +36 -0
- package/src/lib/auth.ts +85 -0
- package/src/lib/channel/channel.spec.ts +49 -0
- package/src/lib/channel/client.ts +173 -0
- package/src/lib/channel/creator.ts +73 -0
- package/src/lib/channel/payload.ts +18 -0
- package/src/lib/channel/registry.ts +39 -0
- package/src/lib/channel/retriever.ts +53 -0
- package/src/lib/client.ts +53 -0
- package/src/lib/errors.ts +133 -0
- package/src/lib/segment/client.ts +126 -0
- package/src/lib/segment/iterator.spec.ts +78 -0
- package/src/lib/segment/iterator.ts +281 -0
- package/src/lib/segment/payload.ts +18 -0
- package/src/lib/segment/splitter.ts +32 -0
- package/src/lib/segment/typed.ts +74 -0
- package/src/lib/segment/validator.ts +82 -0
- package/src/lib/segment/writer.spec.ts +85 -0
- package/src/lib/segment/writer.ts +214 -0
- package/src/lib/telem.spec.ts +200 -0
- package/src/lib/telem.ts +657 -0
- package/src/lib/transport.ts +37 -0
- package/src/lib/user/payload.ts +8 -0
- package/src/lib/util/telem.ts +13 -0
- package/src/setupspecs.ts +16 -0
- package/tsconfig.json +47 -0
- package/tsconfig.module.json +9 -0
- package/yarn-error.log +5756 -0
- package/yarn.lock +5936 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import {
|
|
2
|
+
decodeError,
|
|
3
|
+
EOF,
|
|
4
|
+
ErrorPayloadSchema,
|
|
5
|
+
Stream,
|
|
6
|
+
StreamClient,
|
|
7
|
+
} from '@synnaxlabs/freighter';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
|
|
10
|
+
import ChannelRegistry from '../channel/registry';
|
|
11
|
+
import { GeneralError, UnexpectedError, ValidationError } from '../errors';
|
|
12
|
+
import { Size, TimeStamp, TypedArray, UnparsedTimeStamp } from '../telem';
|
|
13
|
+
|
|
14
|
+
import { SegmentPayload, SegmentPayloadSchema } from './payload';
|
|
15
|
+
import Splitter from './splitter';
|
|
16
|
+
import TypedSegment from './typed';
|
|
17
|
+
import { ContiguityValidator, ScalarTypeValidator } from './validator';
|
|
18
|
+
|
|
19
|
+
const RequestSchema = z.object({
|
|
20
|
+
openKeys: z.string().array().optional(),
|
|
21
|
+
segments: SegmentPayloadSchema.array().optional(),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
type Request = z.infer<typeof RequestSchema>;
|
|
25
|
+
|
|
26
|
+
const ResponseSchema = z.object({
|
|
27
|
+
ack: z.boolean(),
|
|
28
|
+
error: ErrorPayloadSchema.optional(),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
type Response = z.infer<typeof ResponseSchema>;
|
|
32
|
+
|
|
33
|
+
const NOT_OPEN = new GeneralError(
|
|
34
|
+
'Writer has not been opened. Please open before calling write() or close().'
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* CoreWriter is used to write telemetry to a set of channels in time-order. It
|
|
39
|
+
* should not be instantiated directly, but rather through a {@link SegmentClient}.
|
|
40
|
+
*
|
|
41
|
+
* Using a writer is ideal when writing large volumes of data (such as recording
|
|
42
|
+
* telemetry from a sensor), but it is relatively complex and challenging to use.
|
|
43
|
+
* If you're looking to write a contiguous block of telemetry, see the {@link SegmentClient}
|
|
44
|
+
* write() method.
|
|
45
|
+
*/
|
|
46
|
+
export class CoreWriter {
|
|
47
|
+
private static ENDPOINT = '/segment/write';
|
|
48
|
+
private client: StreamClient;
|
|
49
|
+
private stream: Stream<Request, Response> | undefined;
|
|
50
|
+
private keys: string[];
|
|
51
|
+
|
|
52
|
+
constructor(client: StreamClient) {
|
|
53
|
+
this.client = client;
|
|
54
|
+
this.keys = [];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Opens the writer, acquiring an exclusive lock on the given channels for
|
|
59
|
+
* the duration of the writer's lifetime. open must be called before any other
|
|
60
|
+
* writer methods.
|
|
61
|
+
*
|
|
62
|
+
* @param keys - A list of keys representing the channels the writer will write
|
|
63
|
+
* to.
|
|
64
|
+
*/
|
|
65
|
+
async open(keys: string[]) {
|
|
66
|
+
this.keys = keys;
|
|
67
|
+
this.stream = await this.client.stream(
|
|
68
|
+
CoreWriter.ENDPOINT,
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
RequestSchema,
|
|
72
|
+
ResponseSchema
|
|
73
|
+
);
|
|
74
|
+
this.stream.send({ openKeys: keys });
|
|
75
|
+
const [res, err] = await this.stream.receive();
|
|
76
|
+
if (err) throw err;
|
|
77
|
+
if (!res?.ack)
|
|
78
|
+
throw new UnexpectedError(
|
|
79
|
+
'Writer failed to positively acknowledge open request. This is a bug. Please report it.'
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Validates and writes the given segments to the database. The provided segments
|
|
85
|
+
* must:
|
|
86
|
+
*
|
|
87
|
+
* 1. Be in time order (on a per-channel basis)
|
|
88
|
+
* 2. Have channel keys in the set of keys this writer was opened with.
|
|
89
|
+
* 3. Have non-zero length data with the correct data type.
|
|
90
|
+
*
|
|
91
|
+
* @param segments - A list of segments to write to the database.
|
|
92
|
+
* @returns false if the writer has accumulated an error. In this case,
|
|
93
|
+
* the caller should stop executing requests and close the writer.
|
|
94
|
+
*/
|
|
95
|
+
async write(segments: SegmentPayload[]): Promise<boolean> {
|
|
96
|
+
if (!this.stream) throw NOT_OPEN;
|
|
97
|
+
if (this.stream.received()) return false;
|
|
98
|
+
|
|
99
|
+
this.checkKeys(segments);
|
|
100
|
+
const err = this.stream.send({ segments });
|
|
101
|
+
if (err) throw err;
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Closes the writer, raising any accumulated error encountered during operation.
|
|
107
|
+
* A writer MUST be closed after use, and this method should probably be placed
|
|
108
|
+
* in a 'finally' block. If the writer is not closed, the database will not release
|
|
109
|
+
* the exclusive lock on the channels, preventing any other callers from
|
|
110
|
+
* writing to them. It also might leak resources and threads.
|
|
111
|
+
*/
|
|
112
|
+
async close() {
|
|
113
|
+
if (!this.stream) throw NOT_OPEN;
|
|
114
|
+
this.stream.closeSend();
|
|
115
|
+
const [res, err] = await this.stream.receive();
|
|
116
|
+
if (!err && res?.error) throw decodeError(res.error);
|
|
117
|
+
if (!(err instanceof EOF)) throw err;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private checkKeys(segments: SegmentPayload[]) {
|
|
121
|
+
// check that the channel key of each segment is in the open keys
|
|
122
|
+
segments
|
|
123
|
+
.map((segment) => segment.channelKey)
|
|
124
|
+
.forEach((key) => {
|
|
125
|
+
if (!this.keys.includes(key))
|
|
126
|
+
throw new ValidationError({
|
|
127
|
+
field: 'channelKey',
|
|
128
|
+
message: `Channel key ${key} is not in the list of keys this writer was opened with.`,
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* TypedWriter is used to write telemetry to a set of channels in time-order. It
|
|
136
|
+
* should not be instantiated directly, but rather through a {@link SegmentClient}.
|
|
137
|
+
*
|
|
138
|
+
* Using a writer is ideal when writing large volumes of data (such as recording
|
|
139
|
+
* telemetry from a sensor), but it is relatively complex and challenging to use.
|
|
140
|
+
* If you're looking to write a contiguous block of telemetry, see the {@link SegmentClient}
|
|
141
|
+
* write() method.
|
|
142
|
+
*/
|
|
143
|
+
export class TypedWriter {
|
|
144
|
+
private core: CoreWriter;
|
|
145
|
+
private splitter: Splitter;
|
|
146
|
+
private channels: ChannelRegistry;
|
|
147
|
+
private scalarTypeValidator: ScalarTypeValidator;
|
|
148
|
+
private contiguityValidator: ContiguityValidator;
|
|
149
|
+
|
|
150
|
+
constructor(client: StreamClient, channels: ChannelRegistry) {
|
|
151
|
+
this.core = new CoreWriter(client);
|
|
152
|
+
this.channels = channels;
|
|
153
|
+
this.scalarTypeValidator = new ScalarTypeValidator();
|
|
154
|
+
this.contiguityValidator = new ContiguityValidator({
|
|
155
|
+
allowNoHighWaterMark: true,
|
|
156
|
+
allowGaps: false,
|
|
157
|
+
allowOverlap: false,
|
|
158
|
+
});
|
|
159
|
+
this.splitter = new Splitter(Size.Megabytes(4));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Opens the writer, acquiring an exclusive lock on the given channels for
|
|
164
|
+
* the duration of the writer's lifetime. open must be called before any other
|
|
165
|
+
* writer methods.
|
|
166
|
+
*
|
|
167
|
+
* @param keys - A list of keys representing the channels the writer will write
|
|
168
|
+
* to.
|
|
169
|
+
*/
|
|
170
|
+
async open(keys: string[]) {
|
|
171
|
+
await this.core.open(keys);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Writes the given telemetry to the database.
|
|
176
|
+
*
|
|
177
|
+
* @param to - They key of the channel to write to. This must be in the set of
|
|
178
|
+
* keys this writer was opened with.
|
|
179
|
+
* @param start - The start time of the telemetry. This must be equal to
|
|
180
|
+
* the end of the previous segment written to the channel (unless it's the first
|
|
181
|
+
* write to that channel).
|
|
182
|
+
* @param data - The telemetry to write. This must be a valid type for the channel.
|
|
183
|
+
* @returns false if the writer has accumulated an error. In this case,
|
|
184
|
+
* the caller should stop executing requests and close the writer.
|
|
185
|
+
*/
|
|
186
|
+
async write(
|
|
187
|
+
to: string,
|
|
188
|
+
start: UnparsedTimeStamp,
|
|
189
|
+
data: TypedArray
|
|
190
|
+
): Promise<boolean> {
|
|
191
|
+
const ch = await this.channels.get(to);
|
|
192
|
+
this.scalarTypeValidator.validate(data, ch.dataType);
|
|
193
|
+
const pld: SegmentPayload = {
|
|
194
|
+
channelKey: to,
|
|
195
|
+
start: new TimeStamp(start),
|
|
196
|
+
data: new Uint8Array(data.buffer),
|
|
197
|
+
};
|
|
198
|
+
const segment = new TypedSegment(ch, pld);
|
|
199
|
+
this.contiguityValidator.validate(segment);
|
|
200
|
+
const segments = this.splitter.split(segment);
|
|
201
|
+
return this.core.write(segments.map((s) => s.payload));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Closes the writer, raising any accumulated error encountered during operation.
|
|
206
|
+
* A writer MUST be closed after use, and this method should probably be placed
|
|
207
|
+
* in a 'finally' block. If the writer is not closed, the database will not release
|
|
208
|
+
* the exclusive lock on the channels, preventing any other callers from
|
|
209
|
+
* writing to them. It also might leak resources and threads.
|
|
210
|
+
*/
|
|
211
|
+
async close() {
|
|
212
|
+
await this.core.close();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
DataType,
|
|
5
|
+
Density,
|
|
6
|
+
Rate,
|
|
7
|
+
Size,
|
|
8
|
+
TimeRange,
|
|
9
|
+
TimeSpan,
|
|
10
|
+
TimeStamp,
|
|
11
|
+
} from './telem';
|
|
12
|
+
|
|
13
|
+
// |||||| TimeStamp ||||||
|
|
14
|
+
|
|
15
|
+
test('TimeStamp - construct', (t) => {
|
|
16
|
+
const ts = new TimeStamp(1000);
|
|
17
|
+
t.true(ts.equals(TimeSpan.Microseconds()));
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('TimeStamp - span', (t) => {
|
|
21
|
+
const ts = new TimeStamp(0);
|
|
22
|
+
t.true(ts.span(new TimeStamp(1000)).equals(TimeSpan.Microseconds()));
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('TimeStamp - range', (t) => {
|
|
26
|
+
const ts = new TimeStamp(0);
|
|
27
|
+
t.true(
|
|
28
|
+
ts
|
|
29
|
+
.range(new TimeStamp(1000))
|
|
30
|
+
.equals(new TimeRange(ts, TimeSpan.Microseconds()))
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('TimeStamp - spanRange', (t) => {
|
|
35
|
+
const ts = new TimeStamp(0);
|
|
36
|
+
t.true(
|
|
37
|
+
ts
|
|
38
|
+
.spanRange(TimeSpan.Microseconds())
|
|
39
|
+
.equals(new TimeRange(ts, ts.add(TimeSpan.Microseconds())))
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('TimeStamp - isZero', (t) => {
|
|
44
|
+
const ts = new TimeStamp(0);
|
|
45
|
+
t.true(ts.isZero());
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('TimeStamp - after', (t) => {
|
|
49
|
+
const ts = new TimeStamp(0);
|
|
50
|
+
t.true(ts.after(new TimeStamp(-1)));
|
|
51
|
+
const ts2 = new TimeStamp(1);
|
|
52
|
+
t.false(ts2.after(new TimeStamp(1)));
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('TimeStamp - before', (t) => {
|
|
56
|
+
const ts = new TimeStamp(0);
|
|
57
|
+
t.true(ts.before(new TimeStamp(1)));
|
|
58
|
+
const ts2 = new TimeStamp(1);
|
|
59
|
+
t.false(ts2.before(new TimeStamp(1)));
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('TimeStamp - beforeEq', (t) => {
|
|
63
|
+
const ts = new TimeStamp(0);
|
|
64
|
+
t.true(ts.beforeEq(new TimeStamp(1)));
|
|
65
|
+
const ts2 = new TimeStamp(1);
|
|
66
|
+
t.true(ts2.beforeEq(new TimeStamp(1)));
|
|
67
|
+
const ts3 = new TimeStamp(2);
|
|
68
|
+
t.false(ts3.beforeEq(new TimeStamp(1)));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('TimeStamp - afterEq', (t) => {
|
|
72
|
+
const ts = new TimeStamp(0);
|
|
73
|
+
t.true(ts.afterEq(new TimeStamp(-1)));
|
|
74
|
+
const ts2 = new TimeStamp(1);
|
|
75
|
+
t.true(ts2.afterEq(new TimeStamp(1)));
|
|
76
|
+
const ts3 = new TimeStamp(0);
|
|
77
|
+
t.false(ts3.afterEq(new TimeStamp(1)));
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('TimeStamp - add', (t) => {
|
|
81
|
+
const ts = new TimeStamp(0);
|
|
82
|
+
t.true(
|
|
83
|
+
ts
|
|
84
|
+
.add(TimeSpan.Microseconds())
|
|
85
|
+
.equals(new TimeStamp(TimeSpan.Microseconds(1)))
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test('TimeStamp - sub', (t) => {
|
|
90
|
+
const ts = new TimeStamp(TimeSpan.Microseconds());
|
|
91
|
+
t.true(ts.sub(TimeSpan.Microseconds()).equals(new TimeStamp(0)));
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// |||||| TimeSpan ||||||
|
|
95
|
+
|
|
96
|
+
test('TimeSpan - construct from static', (t) => {
|
|
97
|
+
t.true(TimeSpan.Nanoseconds(1).equals(1));
|
|
98
|
+
t.true(TimeSpan.Microseconds(1).equals(1000));
|
|
99
|
+
t.true(TimeSpan.Milliseconds(1).equals(1000000));
|
|
100
|
+
t.true(TimeSpan.Seconds(1).equals(1e9));
|
|
101
|
+
t.true(TimeSpan.Minutes(1).equals(6e10));
|
|
102
|
+
t.true(TimeSpan.Hours(1).equals(36e11));
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test('TimeSpan - seconds', (t) => {
|
|
106
|
+
t.is(TimeSpan.Seconds(1).seconds(), 1);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('TimeSpan - isZero', (t) => {
|
|
110
|
+
t.true(TimeSpan.Zero.isZero());
|
|
111
|
+
t.false(TimeSpan.Seconds(1).isZero());
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test('TimeSpan - add', (t) => {
|
|
115
|
+
t.true(TimeSpan.Seconds(1).add(TimeSpan.Second).equals(2e9));
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test('TimeSpan - sub', (t) => {
|
|
119
|
+
t.true(TimeSpan.Seconds(1).sub(TimeSpan.Second).isZero());
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// |||||| Rate ||||||
|
|
123
|
+
|
|
124
|
+
test('Rate - construct', (t) => {
|
|
125
|
+
t.true(new Rate(1).equals(1));
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('Rate - period', (t) => {
|
|
129
|
+
t.true(new Rate(1).period().equals(TimeSpan.Second));
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test('Rate - sampleCount', (t) => {
|
|
133
|
+
t.true(new Rate(1).sampleCount(TimeSpan.Second) == 1);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('Rate - byteCount', (t) => {
|
|
137
|
+
t.true(new Rate(1).byteCount(TimeSpan.Second, Density.Bit64) == 8);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test('Rate - span', (t) => {
|
|
141
|
+
t.true(new Rate(1).span(4).equals(TimeSpan.Seconds(4)));
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('Rate - byteSpan', (t) => {
|
|
145
|
+
t.true(
|
|
146
|
+
new Rate(1)
|
|
147
|
+
.byteSpan(new Size(32), Density.Bit64)
|
|
148
|
+
.equals(TimeSpan.Seconds(4))
|
|
149
|
+
);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test('Rate - Hz', (t) => {
|
|
153
|
+
t.true(Rate.Hz(1).equals(1));
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test('Rate - KHz', (t) => {
|
|
157
|
+
t.true(Rate.KHz(1).equals(1e3));
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// |||||| TimeRange ||||||
|
|
161
|
+
|
|
162
|
+
test('TimeRange - construct', (t) => {
|
|
163
|
+
const tr = new TimeRange(new TimeStamp(0), new TimeStamp(1000));
|
|
164
|
+
t.true(tr.start.equals(new TimeStamp(0)));
|
|
165
|
+
t.true(tr.end.equals(new TimeStamp(1000)));
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
test('TimeRange - span', (t) => {
|
|
169
|
+
const tr = new TimeRange(new TimeStamp(0), new TimeStamp(1000));
|
|
170
|
+
t.true(tr.span().equals(TimeSpan.Microsecond));
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test('TimeRange - isValid', (t) => {
|
|
174
|
+
const tr = new TimeRange(new TimeStamp(0), new TimeStamp(1000));
|
|
175
|
+
t.true(tr.isValid());
|
|
176
|
+
const tr2 = new TimeRange(new TimeStamp(1000), new TimeStamp(0));
|
|
177
|
+
t.false(tr2.isValid());
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test('TimeRange - isZero', (t) => {
|
|
181
|
+
const tr = new TimeRange(new TimeStamp(0), new TimeStamp(0));
|
|
182
|
+
t.true(tr.isZero());
|
|
183
|
+
const tr2 = new TimeRange(new TimeStamp(0), new TimeStamp(1000));
|
|
184
|
+
t.false(tr2.isZero());
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
test('TimeRange - swap', (t) => {
|
|
188
|
+
const tr = new TimeRange(new TimeStamp(0), new TimeStamp(1000));
|
|
189
|
+
t.true(
|
|
190
|
+
tr.swap().equals(new TimeRange(new TimeStamp(1000), new TimeStamp(0)))
|
|
191
|
+
);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// |||||| DATA TYPE ||||||
|
|
195
|
+
|
|
196
|
+
test('DataType - json serialization', (t) => {
|
|
197
|
+
const dt = DataType.Int32;
|
|
198
|
+
const v = JSON.parse(JSON.stringify({ dt }));
|
|
199
|
+
t.true(v.dt === 'int32');
|
|
200
|
+
});
|