|  | 
| 15 | 15 | from frequenz.sdk.timeseries import Sample | 
| 16 | 16 | from frequenz.sdk.timeseries._quantities import Quantity | 
| 17 | 17 | from frequenz.sdk.timeseries._ringbuffer import Gap, OrderedRingBuffer | 
|  | 18 | +from frequenz.sdk.timeseries._ringbuffer.buffer import FloatArray | 
| 18 | 19 | 
 | 
| 19 | 20 | FIVE_MINUTES = timedelta(minutes=5) | 
| 20 | 21 | ONE_MINUTE = timedelta(minutes=1) | 
| @@ -494,3 +495,98 @@ def test_delete_oudated_gap() -> None: | 
| 494 | 495 |     buffer.update(Sample(datetime.fromtimestamp(202, tz=timezone.utc), Quantity(2))) | 
| 495 | 496 | 
 | 
| 496 | 497 |     assert len(buffer.gaps) == 0 | 
|  | 498 | + | 
|  | 499 | + | 
|  | 500 | +def get_orb(data: FloatArray) -> OrderedRingBuffer[FloatArray]: | 
|  | 501 | +    """Get OrderedRingBuffer with data. | 
|  | 502 | +
 | 
|  | 503 | +    Args: | 
|  | 504 | +        data: Data to fill the buffer with. | 
|  | 505 | +
 | 
|  | 506 | +    Returns: | 
|  | 507 | +        OrderedRingBuffer with data. | 
|  | 508 | +    """ | 
|  | 509 | +    buffer = OrderedRingBuffer(data, ONE_SECOND) | 
|  | 510 | +    for i, d in enumerate(data):  # pylint: disable=invalid-name | 
|  | 511 | +        buffer.update(Sample(dt(i), Quantity(d) if d is not None else None)) | 
|  | 512 | +    return buffer | 
|  | 513 | + | 
|  | 514 | + | 
|  | 515 | +def test_window() -> None: | 
|  | 516 | +    """Test the window function.""" | 
|  | 517 | +    buffer = get_orb(np.array([0, None, 2, 3, 4])) | 
|  | 518 | +    win = buffer.window(dt(0), dt(3), force_copy=False) | 
|  | 519 | +    assert [0, np.nan, 2] == list(win) | 
|  | 520 | +    buffer._buffer[1] = 1  # pylint: disable=protected-access | 
|  | 521 | +    # Test whether the window is a view or a copy | 
|  | 522 | +    assert [0, 1, 2] == list(win) | 
|  | 523 | +    win = buffer.window(dt(0), dt(3), force_copy=False) | 
|  | 524 | +    assert [0, 1, 2] == list(win) | 
|  | 525 | +    # Empty array | 
|  | 526 | +    assert 0 == buffer.window(dt(1), dt(1)).size | 
|  | 527 | + | 
|  | 528 | +    buffer = get_orb([0.0, 1.0, 2.0, 3.0, 4.0])  # type: ignore | 
|  | 529 | +    assert [0, 1, 2] == buffer.window(dt(0), dt(3)) | 
|  | 530 | +    assert [] == buffer.window(dt(0), dt(0)) | 
|  | 531 | +    assert [] == buffer.window(dt(1), dt(1)) | 
|  | 532 | + | 
|  | 533 | + | 
|  | 534 | +def test_wrapped_buffer_window() -> None: | 
|  | 535 | +    """Test the wrapped buffer window function.""" | 
|  | 536 | +    wbw = OrderedRingBuffer._wrapped_buffer_window  # pylint: disable=protected-access | 
|  | 537 | + | 
|  | 538 | +    # | 
|  | 539 | +    # Tests for list buffer | 
|  | 540 | +    # | 
|  | 541 | +    buffer = [0.0, 1.0, 2.0, 3.0, 4.0] | 
|  | 542 | +    # start = end | 
|  | 543 | +    assert [0, 1, 2, 3, 4] == wbw(buffer, 0, 0, force_copy=False) | 
|  | 544 | +    assert [4, 0, 1, 2, 3] == wbw(buffer, 4, 4, force_copy=False) | 
|  | 545 | +    # start < end | 
|  | 546 | +    assert [0] == wbw(buffer, 0, 1, force_copy=False) | 
|  | 547 | +    assert [0, 1, 2, 3, 4] == wbw(buffer, 0, 5, force_copy=False) | 
|  | 548 | +    # start > end, end = 0 | 
|  | 549 | +    assert [4] == wbw(buffer, 4, 0, force_copy=False) | 
|  | 550 | +    # start > end, end > 0 | 
|  | 551 | +    assert [4, 0, 1] == wbw(buffer, 4, 2, force_copy=False) | 
|  | 552 | + | 
|  | 553 | +    # Lists are always shallow copies | 
|  | 554 | +    res_copy = wbw(buffer, 0, 5, force_copy=False) | 
|  | 555 | +    assert [0, 1, 2, 3, 4] == res_copy | 
|  | 556 | +    buffer[0] = 9 | 
|  | 557 | +    assert [0, 1, 2, 3, 4] == res_copy | 
|  | 558 | + | 
|  | 559 | +    # | 
|  | 560 | +    # Tests for array buffer | 
|  | 561 | +    # | 
|  | 562 | +    buffer = np.array([0, 1, 2, 3, 4])  # type: ignore | 
|  | 563 | +    # start = end | 
|  | 564 | +    assert [0, 1, 2, 3, 4] == list(wbw(buffer, 0, 0, force_copy=False)) | 
|  | 565 | +    assert [4, 0, 1, 2, 3] == list(wbw(buffer, 4, 4, force_copy=False)) | 
|  | 566 | +    # start < end | 
|  | 567 | +    assert [0] == list(wbw(buffer, 0, 1, force_copy=False)) | 
|  | 568 | +    assert [0, 1, 2, 3, 4] == list(wbw(buffer, 0, 5, force_copy=False)) | 
|  | 569 | +    # start > end, end = 0 | 
|  | 570 | +    assert [4] == list(wbw(buffer, 4, 0, force_copy=False)) | 
|  | 571 | +    # start > end, end > 0 | 
|  | 572 | +    assert [4, 0, 1] == list(wbw(buffer, 4, 2, force_copy=False)) | 
|  | 573 | + | 
|  | 574 | +    # Get a view and a copy before modifying the buffer | 
|  | 575 | +    res1_view = wbw(buffer, 3, 5, force_copy=False) | 
|  | 576 | +    res1_copy = wbw(buffer, 3, 5, force_copy=True) | 
|  | 577 | +    res2_view = wbw(buffer, 3, 0, force_copy=False) | 
|  | 578 | +    res2_copy = wbw(buffer, 3, 0, force_copy=True) | 
|  | 579 | +    res3_copy = wbw(buffer, 4, 1, force_copy=False) | 
|  | 580 | +    assert [3, 4] == list(res1_view) | 
|  | 581 | +    assert [3, 4] == list(res1_copy) | 
|  | 582 | +    assert [3, 4] == list(res2_view) | 
|  | 583 | +    assert [3, 4] == list(res2_copy) | 
|  | 584 | +    assert [4, 0] == list(res3_copy) | 
|  | 585 | + | 
|  | 586 | +    # Modify the buffer and check that only the view is updated | 
|  | 587 | +    buffer[4] = 9 | 
|  | 588 | +    assert [3, 9] == list(res1_view) | 
|  | 589 | +    assert [3, 4] == list(res1_copy) | 
|  | 590 | +    assert [3, 9] == list(res2_view) | 
|  | 591 | +    assert [3, 4] == list(res2_copy) | 
|  | 592 | +    assert [4, 0] == list(res3_copy) | 
0 commit comments