Skip to content

Commit 2fead12

Browse files
author
Nacho Bonafonte
committed
Add some more tests
1 parent 13d54d9 commit 2fead12

File tree

3 files changed

+208
-0
lines changed

3 files changed

+208
-0
lines changed

Sources/OpenTelemetrySdk/Metrics/Stable/Exemplar/ReservoirCell.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public class ReservoirCell {
4545

4646
func getAndResetDouble(pointAttributes: [String: AttributeValue]) -> DoubleExemplarData {
4747
let result = DoubleExemplarData(value: doubleValue, epochNanos: recordTime, filteredAttributes: filtered(attributes, pointAttributes), spanContext: spanContext)
48+
reset()
4849
return result
4950
}
5051

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//
2+
// Copyright The OpenTelemetry Authors
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
6+
import Foundation
7+
import OpenTelemetryApi
8+
9+
import OpenTelemetryApi
10+
@testable import OpenTelemetrySdk
11+
import XCTest
12+
13+
class ReservoirCellSelectorMock: ReservoirCellSelector {
14+
func reservoirCellIndex(for cells: [ReservoirCell], value: Int, attributes: [String: AttributeValue]) -> Int {
15+
return cells.firstIndex { $0.longValue == 0 } ?? 0
16+
}
17+
18+
func reservoirCellIndex(for cells: [ReservoirCell], value: Double, attributes: [String: AttributeValue]) -> Int {
19+
return cells.firstIndex { $0.doubleValue == 0.0 } ?? 0
20+
}
21+
22+
func reset() {
23+
// do nothing for testing purposes
24+
}
25+
}
26+
27+
class FixedSizedExemplarReservoirTests: XCTestCase {
28+
var reservoir: FixedSizedExemplarReservoir!
29+
let clock = TestClock()
30+
let attributes: [String: AttributeValue] = ["key1": AttributeValue("value1"), "key2": AttributeValue("value2")]
31+
let selector = ReservoirCellSelectorMock()
32+
33+
override func setUp() {
34+
super.setUp()
35+
reservoir = FixedSizedExemplarReservoir(clock: clock, size: 3, reservoirCellSelector: selector, mapAndResetCell: { _, _ in nil })
36+
}
37+
38+
func testOfferLongMeasurement() {
39+
reservoir.offerLongMeasurement(value: 1, attributes: attributes)
40+
reservoir.offerLongMeasurement(value: 2, attributes: attributes)
41+
reservoir.offerLongMeasurement(value: 3, attributes: attributes)
42+
reservoir.offerLongMeasurement(value: 4, attributes: attributes)
43+
44+
XCTAssertTrue(reservoir.storage.contains { $0.longValue == 1 })
45+
XCTAssertTrue(reservoir.storage.contains { $0.longValue == 2 })
46+
XCTAssertTrue(reservoir.storage.contains { $0.longValue == 3 })
47+
XCTAssertTrue(reservoir.storage.contains { $0.longValue == 4 })
48+
}
49+
50+
func testOfferDoubleMeasurement() {
51+
reservoir.offerDoubleMeasurement(value: 1.1, attributes: attributes)
52+
reservoir.offerDoubleMeasurement(value: 2.2, attributes: attributes)
53+
reservoir.offerDoubleMeasurement(value: 3.3, attributes: attributes)
54+
reservoir.offerDoubleMeasurement(value: 4.4, attributes: attributes)
55+
56+
XCTAssertTrue(reservoir.storage.contains { $0.doubleValue == 1.1 })
57+
XCTAssertTrue(reservoir.storage.contains { $0.doubleValue == 2.2 })
58+
XCTAssertTrue(reservoir.storage.contains { $0.doubleValue == 3.3 })
59+
XCTAssertTrue(reservoir.storage.contains { $0.doubleValue == 4.4 })
60+
}
61+
62+
func testCollectAndReset() {
63+
let clock = TestClock()
64+
let reservoirSize = 5
65+
let reservoirCellSelector = ReservoirCellSelectorMock()
66+
67+
// Create the reservoir
68+
let reservoir = FixedSizedExemplarReservoir(clock: clock, size: reservoirSize, reservoirCellSelector: reservoirCellSelector, mapAndResetCell: { cell, attributes in
69+
let exemplar = cell.getAndResetLong(pointAttributes: attributes)
70+
return exemplar.value > 0 ? exemplar : nil
71+
})
72+
73+
// Offer measurements
74+
reservoir.offerLongMeasurement(value: 100, attributes: ["service": AttributeValue.string("foo")])
75+
reservoir.offerLongMeasurement(value: 200, attributes: ["service": AttributeValue.string("foo")])
76+
reservoir.offerLongMeasurement(value: 300, attributes: ["service": AttributeValue.string("bar")])
77+
reservoir.offerLongMeasurement(value: 400, attributes: ["service": AttributeValue.string("bar")])
78+
reservoir.offerLongMeasurement(value: 500, attributes: ["service": AttributeValue.string("baz")])
79+
reservoir.offerLongMeasurement(value: 0, attributes: [:])
80+
81+
// Collect and reset with empty attributes
82+
var exemplars = reservoir.collectAndReset(attribute: [:])
83+
XCTAssertEqual(exemplars.count, 5)
84+
85+
// Collect and reset with non-empty attributes
86+
exemplars = reservoir.collectAndReset(attribute: ["service": AttributeValue.string("bar")])
87+
XCTAssertEqual(exemplars.count, 0)
88+
89+
// Collect and reset with attributes that don't match any measurements
90+
exemplars = reservoir.collectAndReset(attribute: ["service": AttributeValue.string("qux")])
91+
XCTAssertEqual(exemplars.count, 0)
92+
93+
// Offer new measurements
94+
reservoir.offerLongMeasurement(value: 600, attributes: ["service": AttributeValue.string("foo")])
95+
reservoir.offerLongMeasurement(value: 700, attributes: ["service": AttributeValue.string("foo")])
96+
reservoir.offerLongMeasurement(value: 800, attributes: ["service": AttributeValue.string("foo")])
97+
reservoir.offerLongMeasurement(value: 900, attributes: ["service": AttributeValue.string("foo")])
98+
99+
// Collect and reset again with empty attributes
100+
exemplars = reservoir.collectAndReset(attribute: [:])
101+
XCTAssertEqual(exemplars.count, 4)
102+
}
103+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//
2+
// Copyright The OpenTelemetry Authors
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
6+
import OpenTelemetryApi
7+
@testable import OpenTelemetrySdk
8+
import XCTest
9+
10+
class ReservoirCellTests: XCTestCase {
11+
let idGen = RandomIdGenerator()
12+
var reservoirCell: ReservoirCell!
13+
let mockClock = TestClock()
14+
15+
override func setUp() {
16+
super.setUp()
17+
reservoirCell = ReservoirCell(clock: mockClock)
18+
}
19+
20+
func testRecordLongValue() {
21+
let attributes = ["attribute1": AttributeValue.string("value1")]
22+
reservoirCell.recordLongValue(value: 10, attributes: attributes)
23+
24+
XCTAssertEqual(reservoirCell.longValue, 10)
25+
XCTAssertEqual(reservoirCell.attributes, attributes)
26+
XCTAssertEqual(reservoirCell.spanContext, nil)
27+
}
28+
29+
func testRecordDoubleValue() {
30+
let attributes = ["attribute1": AttributeValue.string("value1")]
31+
reservoirCell.recordDoubleValue(value: 3.14, attributes: attributes)
32+
33+
XCTAssertEqual(reservoirCell.doubleValue, 3.14)
34+
XCTAssertEqual(reservoirCell.attributes, attributes)
35+
XCTAssertEqual(reservoirCell.spanContext, nil)
36+
}
37+
38+
func testGetAndResetLong() {
39+
let attributes = ["attribute1": AttributeValue.string("value1")]
40+
let pointAttributes = ["attribute2": AttributeValue.string("value2")]
41+
reservoirCell.recordLongValue(value: 10, attributes: attributes)
42+
43+
let result = reservoirCell.getAndResetLong(pointAttributes: pointAttributes)
44+
XCTAssertEqual(result.value, 10)
45+
XCTAssertEqual(result.epochNanos, mockClock.nanoTime)
46+
XCTAssertEqual(result.filteredAttributes, attributes)
47+
XCTAssertEqual(result.spanContext, nil)
48+
49+
XCTAssertEqual(reservoirCell.attributes, [:])
50+
XCTAssertEqual(reservoirCell.longValue, 0)
51+
XCTAssertEqual(reservoirCell.spanContext, nil)
52+
XCTAssertEqual(reservoirCell.recordTime, 0)
53+
}
54+
55+
func testGetAndResetDouble() {
56+
let attributes = ["attribute1": AttributeValue.string("value1")]
57+
let pointAttributes = ["attribute2": AttributeValue.string("value2")]
58+
reservoirCell.recordDoubleValue(value: 3.14, attributes: attributes)
59+
60+
let result = reservoirCell.getAndResetDouble(pointAttributes: pointAttributes)
61+
XCTAssertEqual(result.value, 3.14)
62+
XCTAssertEqual(result.epochNanos, mockClock.nanoTime)
63+
XCTAssertEqual(result.filteredAttributes, attributes)
64+
XCTAssertEqual(result.spanContext, nil)
65+
66+
XCTAssertEqual(reservoirCell.attributes, [:])
67+
XCTAssertEqual(reservoirCell.doubleValue, 0)
68+
XCTAssertEqual(reservoirCell.spanContext, nil)
69+
XCTAssertEqual(reservoirCell.recordTime, 0)
70+
}
71+
72+
func testReset() {
73+
let attributes = ["attribute1": AttributeValue.string("value1")]
74+
reservoirCell.recordLongValue(value: 10, attributes: attributes)
75+
76+
reservoirCell.reset()
77+
78+
XCTAssertEqual(reservoirCell.attributes, [:])
79+
XCTAssertEqual(reservoirCell.longValue, 0)
80+
XCTAssertEqual(reservoirCell.doubleValue, 0)
81+
XCTAssertEqual(reservoirCell.spanContext, nil)
82+
XCTAssertEqual(reservoirCell.recordTime, 0)
83+
}
84+
85+
func testFiltered() {
86+
let originalAttributes: [String: AttributeValue] = [
87+
"key1": .string("value1"),
88+
"key2": .int(123),
89+
"key3": .bool(true)
90+
]
91+
let metricPointAttributes: [String: AttributeValue] = [
92+
"key2": .int(123),
93+
"key4": .string("value4")
94+
]
95+
let expectedFilteredAttributes: [String: AttributeValue] = [
96+
"key1": .string("value1"),
97+
"key3": .bool(true)
98+
]
99+
100+
let filteredAttributes = reservoirCell.filtered(originalAttributes, metricPointAttributes)
101+
102+
XCTAssertEqual(filteredAttributes, expectedFilteredAttributes)
103+
}
104+
}

0 commit comments

Comments
 (0)