99import pandas as pd
1010import pytest
1111import pytz
12+ import requests
1213
1314from feast import FeatureService , ValueType
1415from feast .embedded_go .lib .embedded import LoggingOptions
@@ -61,8 +62,7 @@ def initialized_registry(environment, universal_data_sources):
6162 fs .materialize (environment .start_date , environment .end_date )
6263
6364
64- @pytest .fixture
65- def grpc_server_port (environment , initialized_registry ):
65+ def server_port (environment , server_type : str ):
6666 if not environment .test_repo_config .go_feature_retrieval :
6767 pytest .skip ("Only for Go path" )
6868
@@ -72,9 +72,15 @@ def grpc_server_port(environment, initialized_registry):
7272 repo_path = str (fs .repo_path .absolute ()), repo_config = fs .config , feature_store = fs ,
7373 )
7474 port = free_port ()
75+ if server_type == "grpc" :
76+ target = embedded .start_grpc_server
77+ elif server_type == "http" :
78+ target = embedded .start_http_server
79+ else :
80+ raise ValueError ("Server Type must be either 'http' or 'grpc'" )
7581
7682 t = threading .Thread (
77- target = embedded . start_grpc_server ,
83+ target = target ,
7884 args = ("127.0.0.1" , port ),
7985 kwargs = dict (
8086 enable_logging = True ,
@@ -98,6 +104,16 @@ def grpc_server_port(environment, initialized_registry):
98104 time .sleep (2 )
99105
100106
107+ @pytest .fixture
108+ def grpc_server_port (environment , initialized_registry ):
109+ yield from server_port (environment , "grpc" )
110+
111+
112+ @pytest .fixture
113+ def http_server_port (environment , initialized_registry ):
114+ yield from server_port (environment , "http" )
115+
116+
101117@pytest .fixture
102118def grpc_client (grpc_server_port ):
103119 ch = grpc .insecure_channel (f"localhost:{ grpc_server_port } " )
@@ -130,6 +146,44 @@ def test_go_grpc_server(grpc_client):
130146 assert all ([s == FieldStatus .PRESENT for s in vector .statuses ])
131147
132148
149+ @pytest .mark .integration
150+ @pytest .mark .goserver
151+ def test_go_http_server (http_server_port ):
152+ response = requests .post (
153+ f"http://localhost:{ http_server_port } /get-online-features" ,
154+ json = {
155+ "feature_service" : "driver_features" ,
156+ "entities" : {"driver_id" : [5001 , 5002 ]},
157+ "full_feature_names" : True ,
158+ },
159+ )
160+ assert response .status_code == 200 , response .text
161+ response = response .json ()
162+ assert set (response .keys ()) == {"metadata" , "results" }
163+ metadata = response ["metadata" ]
164+ results = response ["results" ]
165+ assert response ["metadata" ] == {
166+ "feature_names" : [
167+ "driver_id" ,
168+ "driver_stats__conv_rate" ,
169+ "driver_stats__acc_rate" ,
170+ "driver_stats__avg_daily_trips" ,
171+ ]
172+ }, metadata
173+ assert len (results ) == 4 , results
174+ assert all (
175+ set (result .keys ()) == {"event_timestamps" , "statuses" , "values" }
176+ for result in results
177+ ), results
178+ assert all (
179+ result ["statuses" ] == ["PRESENT" , "PRESENT" ] for result in results
180+ ), results
181+ assert results [0 ]["values" ] == [5001 , 5002 ], results
182+ for result in results [1 :]:
183+ assert len (result ["values" ]) == 2 , result
184+ assert all (value is not None for value in result ["values" ]), result
185+
186+
133187@pytest .mark .integration
134188@pytest .mark .goserver
135189@pytest .mark .universal_offline_stores
0 commit comments