77from typing import List
88
99import numpy as np
10+ import pytest
1011from frequenz .channels import Broadcast
1112
1213from frequenz .sdk .timeseries import (
@@ -102,7 +103,7 @@ async def test_interval_shifting() -> None:
102103 assert index_shifted == 1
103104
104105
105- async def test_feature_extractor () -> None :
106+ async def test_feature_extractor () -> None : # pylint: disable=too-many-statements
106107 """Test the feature extractor with a moving window that contains data."""
107108 start = UNIX_EPOCH + timedelta (seconds = 1 )
108109 end = start + timedelta (seconds = 2 )
@@ -120,6 +121,113 @@ async def test_feature_extractor() -> None:
120121 feature_extractor = await init_feature_extractor (data , timedelta (seconds = 5 ))
121122 assert np .allclose (feature_extractor .avg (start , end ), [1.5 , 1.5 ])
122123
124+ async def _test_fun ( # pylint: disable=too-many-arguments
125+ data : List [float ],
126+ period : int ,
127+ start : int ,
128+ end : int ,
129+ expected : List [float ],
130+ weights : List [float ] | None = None ,
131+ ) -> None :
132+ feature_extractor = await init_feature_extractor (
133+ data , timedelta (seconds = period )
134+ )
135+ ret = feature_extractor .avg (
136+ UNIX_EPOCH + timedelta (seconds = start ),
137+ UNIX_EPOCH + timedelta (seconds = end ),
138+ weights = weights ,
139+ )
140+ assert np .allclose (ret , expected )
141+
142+ async def test_09 (
143+ period : int ,
144+ start : int ,
145+ end : int ,
146+ expected : List [float ],
147+ weights : List [float ] | None = None ,
148+ ) -> None :
149+ data : List [float ] = [0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
150+ await _test_fun (data , period , start , end , expected , weights )
151+
152+ async def test_011 (
153+ period : int ,
154+ start : int ,
155+ end : int ,
156+ expected : List [float ],
157+ weights : List [float ] | None = None ,
158+ ) -> None :
159+ data : List [float ] = [0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ]
160+ await _test_fun (data , period , start , end , expected , weights )
161+
162+ # empty time period
163+ with pytest .raises (ValueError ):
164+ await test_09 (period = 5 , start = 1 , end = 1 , expected = [4711 ])
165+
166+ # moving window not multiple of period
167+ with pytest .raises (ValueError ):
168+ await test_09 (period = 3 , start = 1 , end = 1 , expected = [4711 ])
169+
170+ # time period in moving window
171+ await test_09 (period = 2 , start = 0 , end = 1 , expected = [5 ])
172+ await test_09 (period = 2 , start = 0 , end = 2 , expected = [5 , 6 ])
173+ await test_09 (period = 2 , start = 5 , end = 7 , expected = [4 , 5 ])
174+ await test_09 (period = 2 , start = 8 , end = 10 , expected = [5 , 6 ])
175+ await test_09 (period = 5 , start = 0 , end = 1 , expected = [5 ])
176+ await test_09 (period = 5 , start = 5 , end = 6 , expected = [5 ])
177+
178+ # time period outside of moving window in future
179+ await test_09 (period = 5 , start = 10 , end = 11 , expected = [5 ])
180+ # time period outside of moving window in past
181+ await test_09 (period = 5 , start = - 5 , end = - 4 , expected = [5 ])
182+
183+ await test_09 (period = 5 , start = 0 , end = 2 , expected = [5 , 6 ])
184+ await test_09 (period = 5 , start = 0 , end = 3 , expected = [5 , 6 , 7 ])
185+ await test_09 (period = 5 , start = 0 , end = 4 , expected = [5 , 6 , 7 , 8 ])
186+ await test_09 (period = 5 , start = 1 , end = 5 , expected = [6 , 7 , 8 , 9 ])
187+
188+ # No full time period in moving window, expect to throw
189+ await test_09 (period = 5 , start = 0 , end = 5 , expected = [5 , 6 , 7 , 8 , 9 ])
190+ with pytest .raises (Exception ):
191+ await test_09 (period = 5 , start = 0 , end = 6 , expected = [5 ])
192+ with pytest .raises (Exception ):
193+ await test_09 (period = 5 , start = 0 , end = 7 , expected = [5 , 6 ])
194+ with pytest .raises (Exception ):
195+ await test_09 (period = 5 , start = 0 , end = 8 , expected = [5 , 6 , 7 ])
196+ with pytest .raises (Exception ):
197+ await test_09 (period = 5 , start = 0 , end = 9 , expected = [5 , 6 , 7 , 8 ])
198+ with pytest .raises (Exception ):
199+ await test_09 (period = 5 , start = 0 , end = 10 , expected = [4711 ])
200+ with pytest .raises (Exception ):
201+ await test_09 (period = 5 , start = 0 , end = 11 , expected = [5 ])
202+ with pytest .raises (Exception ):
203+ await test_09 (period = 5 , start = 0 , end = 12 , expected = [5 , 6 ])
204+
205+ # time period outside window but more matches
206+ await test_09 (
207+ period = 5 , start = 8 , end = 11 , expected = [3 , 4 , 5 ]
208+ ) # First occurence [-2, -1, 0] partly inside window
209+
210+ # time period larger than period
211+ with pytest .raises (Exception ):
212+ await test_09 (period = 2 , start = 8 , end = 11 , expected = [5 ])
213+ with pytest .raises (Exception ):
214+ await test_09 (period = 2 , start = 0 , end = 3 , expected = [5 ])
215+
216+ # Weights
217+ await test_011 (period = 4 , start = 0 , end = 2 , expected = [6 , 7 ])
218+ await test_011 (period = 4 , start = 0 , end = 2 , expected = [6 , 7 ], weights = None )
219+ await test_011 (period = 4 , start = 0 , end = 2 , expected = [6 , 7 ], weights = [1 , 1 ])
220+ await test_011 (
221+ period = 4 , start = 0 , end = 2 , expected = [4 , 5 ], weights = [1 , 0 ]
222+ ) # oldest weight first
223+ await test_011 (period = 4 , start = 0 , end = 2 , expected = [6 , 7 ], weights = [1 , 1 ])
224+ with pytest .raises (ValueError ):
225+ await test_011 (
226+ period = 4 , start = 0 , end = 2 , expected = [4711 , 4711 ], weights = [1 , 1 , 1 ]
227+ )
228+ with pytest .raises (ValueError ):
229+ await test_011 (period = 4 , start = 0 , end = 2 , expected = [4711 , 4711 ], weights = [1 ])
230+
123231
124232async def test_profiler_calculate_np () -> None :
125233 """
0 commit comments