|
13 | 13 | import json
|
14 | 14 |
|
15 | 15 | import mock
|
| 16 | +import threading |
16 | 17 |
|
17 | 18 | from optimizely import optimizely, decision_service
|
18 | 19 | from optimizely.decision.optimizely_decide_option import OptimizelyDecideOption as DecideOption
|
@@ -1793,3 +1794,113 @@ def test_forced_decision_return_status(self):
|
1793 | 1794 | self.assertTrue(status)
|
1794 | 1795 | status = user_context.remove_all_forced_decisions()
|
1795 | 1796 | self.assertTrue(status)
|
| 1797 | + |
| 1798 | + def test_forced_decision_clone_return_valid_forced_decision(self): |
| 1799 | + """ |
| 1800 | + Should return valid forced decision on cloning. |
| 1801 | + """ |
| 1802 | + opt_obj = optimizely.Optimizely(json.dumps(self.config_dict_with_features)) |
| 1803 | + user_context = OptimizelyUserContext(opt_obj, "test_user", {}) |
| 1804 | + |
| 1805 | + context_with_flag = OptimizelyUserContext.OptimizelyDecisionContext('f1', None) |
| 1806 | + decision_for_flag = OptimizelyUserContext.OptimizelyForcedDecision('v1') |
| 1807 | + context_with_rule = OptimizelyUserContext.OptimizelyDecisionContext('f1', 'r1') |
| 1808 | + decision_for_rule = OptimizelyUserContext.OptimizelyForcedDecision('v2') |
| 1809 | + context_with_empty_rule = OptimizelyUserContext.OptimizelyDecisionContext('f1', '') |
| 1810 | + decision_for_empty_rule = OptimizelyUserContext.OptimizelyForcedDecision('v3') |
| 1811 | + |
| 1812 | + user_context.set_forced_decision(context_with_flag, decision_for_flag) |
| 1813 | + user_context.set_forced_decision(context_with_rule, decision_for_rule) |
| 1814 | + user_context.set_forced_decision(context_with_empty_rule, decision_for_empty_rule) |
| 1815 | + |
| 1816 | + user_context_2 = user_context._clone() |
| 1817 | + self.assertEqual(user_context_2.user_id, 'test_user') |
| 1818 | + self.assertEqual(user_context_2.get_user_attributes(), {}) |
| 1819 | + self.assertIsNotNone(user_context_2.forced_decisions) |
| 1820 | + |
| 1821 | + self.assertEqual(user_context_2.get_forced_decision(context_with_flag).variation_key, 'v1') |
| 1822 | + self.assertEqual(user_context_2.get_forced_decision(context_with_rule).variation_key, 'v2') |
| 1823 | + self.assertEqual(user_context_2.get_forced_decision(context_with_empty_rule).variation_key, 'v3') |
| 1824 | + |
| 1825 | + context_with_rule = OptimizelyUserContext.OptimizelyDecisionContext('x', 'y') |
| 1826 | + decision_for_rule = OptimizelyUserContext.OptimizelyForcedDecision('z') |
| 1827 | + user_context.set_forced_decision(context_with_rule, decision_for_rule) |
| 1828 | + self.assertEqual(user_context.get_forced_decision(context_with_rule).variation_key, 'z') |
| 1829 | + self.assertIsNone(user_context_2.get_forced_decision(context_with_rule)) |
| 1830 | + |
| 1831 | + def test_forced_decision_sync_return_correct_number_of_calls(self): |
| 1832 | + """ |
| 1833 | + Should return valid number of call on running forced decision calls in thread. |
| 1834 | + """ |
| 1835 | + opt_obj = optimizely.Optimizely(json.dumps(self.config_dict_with_features)) |
| 1836 | + user_context = OptimizelyUserContext(opt_obj, "test_user", {}) |
| 1837 | + context_1 = OptimizelyUserContext.OptimizelyDecisionContext('f1', None) |
| 1838 | + decision_1 = OptimizelyUserContext.OptimizelyForcedDecision('v1') |
| 1839 | + context_2 = OptimizelyUserContext.OptimizelyDecisionContext('f2', None) |
| 1840 | + decision_2 = OptimizelyUserContext.OptimizelyForcedDecision('v1') |
| 1841 | + |
| 1842 | + with mock.patch( |
| 1843 | + 'optimizely.optimizely_user_context.OptimizelyUserContext.set_forced_decision' |
| 1844 | + ) as set_forced_decision_mock, mock.patch( |
| 1845 | + 'optimizely.optimizely_user_context.OptimizelyUserContext.get_forced_decision' |
| 1846 | + ) as get_forced_decision_mock, mock.patch( |
| 1847 | + 'optimizely.optimizely_user_context.OptimizelyUserContext.remove_forced_decision' |
| 1848 | + ) as remove_forced_decision_mock, mock.patch( |
| 1849 | + 'optimizely.optimizely_user_context.OptimizelyUserContext.remove_all_forced_decisions' |
| 1850 | + ) as remove_all_forced_decisions_mock, mock.patch( |
| 1851 | + 'optimizely.optimizely_user_context.OptimizelyUserContext._clone' |
| 1852 | + ) as clone_mock: |
| 1853 | + def set_forced_decision_loop(user_context, context, decision): |
| 1854 | + for x in range(100): |
| 1855 | + user_context.set_forced_decision(context, decision) |
| 1856 | + |
| 1857 | + def get_forced_decision_loop(user_context, context): |
| 1858 | + for x in range(100): |
| 1859 | + user_context.get_forced_decision(context) |
| 1860 | + |
| 1861 | + def remove_forced_decision_loop(user_context, context): |
| 1862 | + for x in range(100): |
| 1863 | + user_context.remove_forced_decision(context) |
| 1864 | + |
| 1865 | + def remove_all_forced_decisions_loop(user_context): |
| 1866 | + for x in range(100): |
| 1867 | + user_context.remove_all_forced_decisions() |
| 1868 | + |
| 1869 | + def clone_loop(user_context): |
| 1870 | + for x in range(100): |
| 1871 | + user_context._clone() |
| 1872 | + |
| 1873 | + set_thread_1 = threading.Thread(target=set_forced_decision_loop, args=(user_context, context_1, decision_1)) |
| 1874 | + set_thread_2 = threading.Thread(target=set_forced_decision_loop, args=(user_context, context_2, decision_2)) |
| 1875 | + set_thread_3 = threading.Thread(target=get_forced_decision_loop, args=(user_context, context_1)) |
| 1876 | + set_thread_4 = threading.Thread(target=get_forced_decision_loop, args=(user_context, context_2)) |
| 1877 | + set_thread_5 = threading.Thread(target=remove_forced_decision_loop, args=(user_context, context_1)) |
| 1878 | + set_thread_6 = threading.Thread(target=remove_forced_decision_loop, args=(user_context, context_2)) |
| 1879 | + set_thread_7 = threading.Thread(target=remove_all_forced_decisions_loop, args=(user_context,)) |
| 1880 | + set_thread_8 = threading.Thread(target=clone_loop, args=(user_context,)) |
| 1881 | + |
| 1882 | + # Starting the threads |
| 1883 | + set_thread_1.start() |
| 1884 | + set_thread_2.start() |
| 1885 | + set_thread_3.start() |
| 1886 | + set_thread_4.start() |
| 1887 | + set_thread_5.start() |
| 1888 | + set_thread_6.start() |
| 1889 | + set_thread_7.start() |
| 1890 | + set_thread_8.start() |
| 1891 | + |
| 1892 | + # Waiting for all the threads to finish executing |
| 1893 | + set_thread_1.join() |
| 1894 | + set_thread_2.join() |
| 1895 | + set_thread_3.join() |
| 1896 | + set_thread_4.join() |
| 1897 | + set_thread_5.join() |
| 1898 | + set_thread_6.join() |
| 1899 | + set_thread_7.join() |
| 1900 | + set_thread_8.join() |
| 1901 | + |
| 1902 | + self.assertEqual(200, set_forced_decision_mock.call_count) |
| 1903 | + self.assertEqual(200, get_forced_decision_mock.call_count) |
| 1904 | + self.assertEqual(200, remove_forced_decision_mock.call_count) |
| 1905 | + self.assertEqual(100, remove_all_forced_decisions_mock.call_count) |
| 1906 | + self.assertEqual(100, clone_mock.call_count) |
0 commit comments