| 
5 | 5 | 
 
  | 
6 | 6 | from __future__ import annotations  | 
7 | 7 | 
 
  | 
 | 8 | +import logging  | 
 | 9 | +import unittest.mock  | 
8 | 10 | from logging import getLogger  | 
9 | 11 | 
 
  | 
 | 12 | +import pytest  | 
 | 13 | + | 
 | 14 | +import snowflake.connector  | 
10 | 15 | from snowflake.connector import errorcode, errors  | 
11 |  | -from snowflake.connector.network import SnowflakeRestful  | 
 | 16 | +from snowflake.connector.network import (  | 
 | 17 | +    QUERY_IN_PROGRESS_ASYNC_CODE,  | 
 | 18 | +    QUERY_IN_PROGRESS_CODE,  | 
 | 19 | +    SnowflakeRestful,  | 
 | 20 | +)  | 
12 | 21 | 
 
  | 
13 | 22 | logger = getLogger(__name__)  | 
14 | 23 | 
 
  | 
@@ -36,3 +45,56 @@ def test_no_auth(db_parameters):  | 
36 | 45 |         assert e.errno == errorcode.ER_CONNECTION_IS_CLOSED  | 
37 | 46 |     finally:  | 
38 | 47 |         rest.close()  | 
 | 48 | + | 
 | 49 | + | 
 | 50 | +@pytest.mark.skipolddriver  | 
 | 51 | +@pytest.mark.parametrize(  | 
 | 52 | +    "query_return_code", [QUERY_IN_PROGRESS_CODE, QUERY_IN_PROGRESS_ASYNC_CODE]  | 
 | 53 | +)  | 
 | 54 | +def test_none_object_when_querying_result(db_parameters, caplog, query_return_code):  | 
 | 55 | +    # this test simulate the case where the response from the server is None  | 
 | 56 | +    # the following events happen in sequence:  | 
 | 57 | +    # 1. we send a simple query to the server which is a post request  | 
 | 58 | +    # 2. we record the query result in a global variable  | 
 | 59 | +    # 3. we mock return a query in progress code and an url to fetch the query result  | 
 | 60 | +    # 4. we return None for the fetching query result request for the first time  | 
 | 61 | +    # 5. for the second time, we return the code for the query result  | 
 | 62 | +    # 6. in the end, we assert the result, and retry has taken place when result is None by checking logging  | 
 | 63 | + | 
 | 64 | +    original_request_exec = SnowflakeRestful._request_exec  | 
 | 65 | +    expected_ret = None  | 
 | 66 | +    get_executed_time = 0  | 
 | 67 | + | 
 | 68 | +    def side_effect_request_exec(self, *args, **kwargs):  | 
 | 69 | +        nonlocal expected_ret, get_executed_time  | 
 | 70 | +        # 1. we send a simple query to the server which is a post request  | 
 | 71 | +        if "queries/v1/query-request" in kwargs["full_url"]:  | 
 | 72 | +            ret = original_request_exec(self, *args, **kwargs)  | 
 | 73 | +            expected_ret = ret  # 2. we record the query result in a global variable  | 
 | 74 | +            # 3. we mock return a query in progress code and an url to fetch the query result  | 
 | 75 | +            return {  | 
 | 76 | +                "code": query_return_code,  | 
 | 77 | +                "data": {"getResultUrl": "/queries/123/result"},  | 
 | 78 | +            }  | 
 | 79 | + | 
 | 80 | +        if "/queries/123/result" in kwargs["full_url"]:  | 
 | 81 | +            if get_executed_time == 0:  | 
 | 82 | +                # 4. we return None for the 1st time fetching query result request, this should trigger retry  | 
 | 83 | +                get_executed_time += 1  | 
 | 84 | +                return None  | 
 | 85 | +            else:  | 
 | 86 | +                # 5. for the second time, we return the code for the query result, this indicates retry success  | 
 | 87 | +                return expected_ret  | 
 | 88 | + | 
 | 89 | +    with snowflake.connector.connect(  | 
 | 90 | +        **db_parameters  | 
 | 91 | +    ) as conn, conn.cursor() as cursor, caplog.at_level(logging.INFO):  | 
 | 92 | +        with unittest.mock.patch.object(  | 
 | 93 | +            SnowflakeRestful, "_request_exec", new=side_effect_request_exec  | 
 | 94 | +        ):  | 
 | 95 | +            # 6. in the end, we assert the result, and retry has taken place when result is None by checking logging  | 
 | 96 | +            assert cursor.execute("select 1").fetchone() == (1,)  | 
 | 97 | +            assert (  | 
 | 98 | +                "fetch query status failed and http request returned None, this is usually caused by transient network failures, retrying"  | 
 | 99 | +                in caplog.text  | 
 | 100 | +            )  | 
0 commit comments