Skip to content

Commit 9093288

Browse files
committed
Added more unit tests
1 parent 284f5af commit 9093288

File tree

6 files changed

+178
-38
lines changed

6 files changed

+178
-38
lines changed

azure_functions_worker/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,4 @@
5757
CUSTOMER_PACKAGES_PATH = "/home/site/wwwroot/.python_packages/lib/site-packages"
5858

5959
# Flag to index functions in handle init request
60-
INIT_INDEXING = "INIT_INDEXING"
60+
ENABLE_INIT_INDEXING = "ENABLE_INIT_INDEXING"

azure_functions_worker/dispatcher.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
PYTHON_ENABLE_DEBUG_LOGGING,
3131
PYTHON_SCRIPT_FILE_NAME,
3232
PYTHON_SCRIPT_FILE_NAME_DEFAULT,
33-
PYTHON_LANGUAGE_RUNTIME, INIT_INDEXING)
33+
PYTHON_LANGUAGE_RUNTIME, ENABLE_INIT_INDEXING)
3434
from .extension import ExtensionManager
3535
from .logging import disable_console_logging, enable_console_logging
3636
from .logging import (logger, error_logger, is_system_log_category,
@@ -301,7 +301,7 @@ async def _handle__worker_init_request(self, request):
301301
# dictionary which will be later used in the invocation request
302302
bindings.load_binding_registry()
303303

304-
if is_envvar_true(INIT_INDEXING):
304+
if is_envvar_true(ENABLE_INIT_INDEXING):
305305
self.get_function_metadata(directory,
306306
caller_info=sys._getframe().f_code.co_name)
307307

@@ -322,6 +322,11 @@ async def _handle__worker_status_request(self, request):
322322
worker_status_response=protos.WorkerStatusResponse())
323323

324324
def get_function_metadata(self, directory, caller_info):
325+
"""
326+
This method is called to index the functions in the function app directory
327+
and save the results in function_metadata_result or
328+
function_metadata_exception in case of an exception.
329+
"""
325330
script_file_name = get_app_setting(
326331
setting=PYTHON_SCRIPT_FILE_NAME,
327332
default_value=f'{PYTHON_SCRIPT_FILE_NAME_DEFAULT}')
@@ -345,7 +350,7 @@ async def _handle__functions_metadata_request(self, request):
345350
metadata_request = request.functions_metadata_request
346351
directory = metadata_request.function_app_directory
347352

348-
if not is_envvar_true(INIT_INDEXING):
353+
if not is_envvar_true(ENABLE_INIT_INDEXING):
349354
self.get_function_metadata(directory,
350355
caller_info=sys._getframe().f_code.co_name)
351356

@@ -383,7 +388,7 @@ async def _handle__function_load_request(self, request):
383388
if not self._functions.get_function(function_id):
384389

385390
if function_metadata.properties.get("worker_indexed", False)\
386-
and not is_envvar_true(INIT_INDEXING):
391+
and not is_envvar_true(ENABLE_INIT_INDEXING):
387392
# This is for the second worker and above where the worker
388393
# indexing is enabled and load request is called without
389394
# calling the metadata request. In this case we index the

azure_functions_worker/loader.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ def load_function(name: str, directory: str, script_file: str,
218218
f'{os.path.exists(CUSTOMER_PACKAGES_PATH)}')
219219
def index_function_app(function_path: str):
220220
module_name = pathlib.Path(function_path).stem
221+
logger.info(f'Loading module {module_name}')
221222
imported_module = importlib.import_module(module_name)
222223

223224
from azure.functions import FunctionRegister

tests/endtoend/test_http_functions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ def tearDown(self):
3434

3535
@classmethod
3636
def get_script_dir(cls):
37-
return testutils.E2E_TESTS_FOLDER / 'http_functions'
37+
return testutils.E2E_TESTS_FOLDER / 'http_functions' / \
38+
'http_functions_stein'
3839

3940
@testutils.retryable_test(3, 5)
4041
def test_function_index_page_should_return_ok(self):
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import azure.functions as func
22

3-
app = func.FunctionApp()
3+
app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)
44

55

6-
@app.route()
7-
def main(req: func.HttpRequest):
8-
pass
6+
@app.route(route="http_trigger")
7+
def http_trigger(req: func.HttpRequest) -> func.HttpResponse:
8+
9+
return func.HttpResponse("Hello.")

tests/unittests/test_dispatcher.py

Lines changed: 160 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from azure_functions_worker import protos
1212
from azure_functions_worker.constants import PYTHON_THREADPOOL_THREAD_COUNT, \
1313
PYTHON_THREADPOOL_THREAD_COUNT_DEFAULT, \
14-
PYTHON_THREADPOOL_THREAD_COUNT_MAX_37, PYTHON_THREADPOOL_THREAD_COUNT_MIN
14+
PYTHON_THREADPOOL_THREAD_COUNT_MAX_37, PYTHON_THREADPOOL_THREAD_COUNT_MIN, ENABLE_INIT_INDEXING
1515
from azure_functions_worker.version import VERSION
1616
from tests.utils import testutils
1717
from tests.utils.testutils import UNIT_TESTS_ROOT
@@ -22,8 +22,8 @@
2222
DISPATCHER_STEIN_FUNCTIONS_DIR = testutils.UNIT_TESTS_FOLDER / \
2323
'dispatcher_functions' / \
2424
'dispatcher_functions_stein'
25-
FUNCTION_APP_DIRECTORY = UNIT_TESTS_ROOT / 'dispatcher_functions' / \
26-
'dispatcher_functions_stein'
25+
FUNCTION_APP_DIRECTORY = UNIT_TESTS_ROOT / 'dispatcher_functions' / \
26+
'dispatcher_functions_stein'
2727

2828

2929
class TestThreadPoolSettingsPython37(testutils.AsyncTestCase):
@@ -680,10 +680,10 @@ async def test_dispatcher_load_azfunc_in_init(self):
680680
)
681681
self.assertIn("azure.functions", sys.modules)
682682

683-
async def test_dispatcher_indexing_in_init(self):
683+
async def test_dispatcher_indexing_in_init_request(self):
684684
"""Test if azure functions is loaded during init
685685
"""
686-
env = {"INIT_INDEXING": "1"}
686+
env = {ENABLE_INIT_INDEXING: "1"}
687687
with patch.dict(os.environ, env):
688688
async with self._ctrl as host:
689689
r = await host.init_worker()
@@ -696,7 +696,8 @@ async def test_dispatcher_indexing_in_init(self):
696696

697697
self.assertEqual(
698698
len([log for log in r.logs if log.message.startswith(
699-
"Received WorkerMetadataRequest from _handle__worker_init_request"
699+
"Received WorkerMetadataRequest from "
700+
"_handle__worker_init_request"
700701
)]),
701702
1
702703
)
@@ -752,46 +753,177 @@ async def test_dispatcher_load_modules_con_app_placeholder_disabled(self):
752753
" Placeholder: False", logs)
753754

754755

755-
class DispatcherTests(unittest.TestCase):
756+
class TestDispatcherIndexinginInit(unittest.TestCase):
756757

757758
def setUp(self):
758759
self.loop = asyncio.new_event_loop()
759760
asyncio.set_event_loop(self.loop)
760761
self.dispatcher = testutils.create_dummy_dispatcher()
762+
sys.path.append(str(FUNCTION_APP_DIRECTORY))
761763

762764
def tearDown(self):
763765
self.loop.close()
764766

765-
@patch.dict(os.environ, {'INIT_INDEXING': 'true'})
766-
# @patch('azure_functions_worker.dispatcher.Dispatcher.get_function_metadata')
767+
@patch.dict(os.environ, {ENABLE_INIT_INDEXING: 'true'})
767768
def test_worker_init_request_with_indexing_enabled(self):
768-
# Set up any additional mocks needed for your test
769-
# mock_get_function_metadata.return_value = None
770-
import azure.functions
771769

772770
request = protos.StreamingMessage(
773-
worker_init_request=protos.WorkerInitRequest(
774-
host_version="2.3.4",
775-
function_app_directory=str(FUNCTION_APP_DIRECTORY)
776-
)
771+
worker_init_request=protos.WorkerInitRequest(
772+
host_version="2.3.4",
773+
function_app_directory=str(FUNCTION_APP_DIRECTORY)
777774
)
775+
)
778776

779-
# Execute the method under test
780-
result = self.loop.run_until_complete(
777+
self.loop.run_until_complete(
781778
self.dispatcher._handle__worker_init_request(request))
782779

783-
# Assert conditions based on INIT_INDEXING being true
784780
self.assertIsNotNone(self.dispatcher.function_metadata_result)
781+
self.assertIsNone(self.dispatcher.function_metadata_exception)
782+
783+
@patch.dict(os.environ, {ENABLE_INIT_INDEXING: 'false'})
784+
def test_worker_init_request_with_indexing_disabled(self):
785+
request = protos.StreamingMessage(
786+
worker_init_request=protos.WorkerInitRequest(
787+
host_version="2.3.4",
788+
function_app_directory=str(FUNCTION_APP_DIRECTORY)
789+
)
790+
)
791+
792+
self.loop.run_until_complete(
793+
self.dispatcher._handle__worker_init_request(request))
794+
795+
self.assertIsNone(self.dispatcher.function_metadata_result)
796+
self.assertIsNone(self.dispatcher.function_metadata_exception)
797+
798+
@patch.dict(os.environ, {ENABLE_INIT_INDEXING: 'true'})
799+
def test_worker_init_request_with_indexing_exception(self):
800+
sys.path.remove(str(FUNCTION_APP_DIRECTORY))
801+
802+
request = protos.StreamingMessage(
803+
worker_init_request=protos.WorkerInitRequest(
804+
host_version="2.3.4",
805+
function_app_directory=str(FUNCTION_APP_DIRECTORY)
806+
)
807+
)
808+
809+
self.loop.run_until_complete(
810+
self.dispatcher._handle__worker_init_request(request))
811+
812+
self.assertIsNone(self.dispatcher.function_metadata_result)
813+
self.assertIsNotNone(self.dispatcher.function_metadata_exception)
814+
815+
@patch.dict(os.environ, {ENABLE_INIT_INDEXING: 'true'})
816+
def test_functions_metadata_request_with_init_indexing_enabled(self):
817+
init_request = protos.StreamingMessage(
818+
worker_init_request=protos.WorkerInitRequest(
819+
host_version="2.3.4",
820+
function_app_directory=str(FUNCTION_APP_DIRECTORY)
821+
)
822+
)
823+
824+
metadata_request = protos.StreamingMessage(
825+
functions_metadata_request=protos.FunctionsMetadataRequest(
826+
function_app_directory=str(FUNCTION_APP_DIRECTORY)
827+
)
828+
)
829+
830+
init_response = self.loop.run_until_complete(
831+
self.dispatcher._handle__worker_init_request(init_request))
832+
self.assertEqual(init_response.worker_init_response.result.status,
833+
protos.StatusResult.Success)
834+
835+
metadata_response = self.loop.run_until_complete(
836+
self.dispatcher._handle__functions_metadata_request(metadata_request))
837+
838+
self.assertEqual(metadata_response.function_metadata_response.result.status,
839+
protos.StatusResult.Success)
840+
self.assertIsNotNone(self.dispatcher.function_metadata_result)
841+
self.assertIsNone(self.dispatcher.function_metadata_exception)
842+
843+
@patch.dict(os.environ, {ENABLE_INIT_INDEXING: 'false'})
844+
def test_functions_metadata_request_with_init_indexing_enabled(self):
845+
init_request = protos.StreamingMessage(
846+
worker_init_request=protos.WorkerInitRequest(
847+
host_version="2.3.4",
848+
function_app_directory=str(FUNCTION_APP_DIRECTORY)
849+
)
850+
)
851+
852+
metadata_request = protos.StreamingMessage(
853+
functions_metadata_request=protos.FunctionsMetadataRequest(
854+
function_app_directory=str(str(FUNCTION_APP_DIRECTORY))
855+
)
856+
)
857+
858+
init_response = self.loop.run_until_complete(
859+
self.dispatcher._handle__worker_init_request(init_request))
860+
self.assertEqual(init_response.worker_init_response.result.status,
861+
protos.StatusResult.Success)
862+
self.assertIsNone(self.dispatcher.function_metadata_result)
863+
self.assertIsNone(self.dispatcher.function_metadata_exception)
864+
865+
866+
metadata_response = self.loop.run_until_complete(
867+
self.dispatcher._handle__functions_metadata_request(metadata_request))
868+
869+
self.assertEqual(metadata_response.function_metadata_response.result.status,
870+
protos.StatusResult.Success)
871+
self.assertIsNotNone(self.dispatcher.function_metadata_result)
872+
self.assertIsNone(self.dispatcher.function_metadata_exception)
785873

786-
@patch.dict(os.environ, {'INIT_INDEXING': 'false'})
787-
@patch('yourmodule.dispatcher.Dispatcher.get_function_metadata')
788-
def test_worker_init_request_with_indexing_disabled(self, mock_get_function_metadata):
789-
# Execute the method under test
790-
# result = self.loop.run_until_complete(self.dispatcher._handle__worker_init_request(request))
874+
@patch.dict(os.environ, {ENABLE_INIT_INDEXING: 'true'})
875+
def test_functions_metadata_request_with_indexing_exception(self):
876+
sys.path.remove(str(FUNCTION_APP_DIRECTORY))
791877

792-
# Assert conditions based on INIT_INDEXING being false
793-
# For example, you might expect function_metadata_result or function_metadata_exception to be set differently
794-
# Adjust your assertions accordingly
795-
pass
878+
request = protos.StreamingMessage(
879+
worker_init_request=protos.WorkerInitRequest(
880+
host_version="2.3.4",
881+
function_app_directory=str(FUNCTION_APP_DIRECTORY)
882+
)
883+
)
796884

885+
metadata_request = protos.StreamingMessage(
886+
functions_metadata_request=protos.FunctionsMetadataRequest(
887+
function_app_directory=str(FUNCTION_APP_DIRECTORY)
888+
)
889+
)
797890

891+
self.loop.run_until_complete(
892+
self.dispatcher._handle__worker_init_request(request))
893+
894+
self.assertIsNone(self.dispatcher.function_metadata_result)
895+
self.assertIsNotNone(self.dispatcher.function_metadata_exception)
896+
897+
metadata_response = self.loop.run_until_complete(
898+
self.dispatcher._handle__functions_metadata_request(metadata_request))
899+
900+
self.assertEqual(metadata_response.function_metadata_response.result.status,
901+
protos.StatusResult.Failure)
902+
903+
@patch.dict(os.environ, {ENABLE_INIT_INDEXING: 'false'})
904+
def test_dispatcher_indexing_in_load_request(self):
905+
init_request = protos.StreamingMessage(
906+
worker_init_request=protos.WorkerInitRequest(
907+
host_version="2.3.4",
908+
function_app_directory=str(FUNCTION_APP_DIRECTORY)
909+
)
910+
)
911+
912+
self.loop.run_until_complete(
913+
self.dispatcher._handle__worker_init_request(init_request))
914+
915+
self.assertIsNone(self.dispatcher.function_metadata_result)
916+
917+
load_request = protos.StreamingMessage(
918+
function_load_request=protos.FunctionLoadRequest(
919+
function_id="http_trigger",
920+
metadata=protos.RpcFunctionMetadata(
921+
directory=str(FUNCTION_APP_DIRECTORY),
922+
properties={"worker_indexed": "True"}
923+
)))
924+
925+
self.loop.run_until_complete(
926+
self.dispatcher._handle__function_load_request(load_request))
927+
928+
self.assertIsNotNone(self.dispatcher.function_metadata_result)
929+
self.assertIsNone(self.dispatcher.function_metadata_exception)

0 commit comments

Comments
 (0)