def instrument_course_progress_render( self, course_width, enable_ccx, view_as_ccx, sql_queries, mongo_reads, ): """ Renders the progress page, instrumenting Mongo reads and SQL queries. """ course_key = self.setup_course(course_width, enable_ccx, view_as_ccx) # Switch to published-only mode to simulate the LMS with self.settings(MODULESTORE_BRANCH='published-only'): # Clear all caches before measuring for cache in settings.CACHES: caches[cache].clear() # Refill the metadata inheritance cache get_course_in_cache(course_key) # We clear the request cache to simulate a new request in the LMS. RequestCache.clear_all_namespaces() # Reset the list of provider classes, so that our django settings changes # can actually take affect. OverrideFieldData.provider_classes = None with self.assertNumQueries(sql_queries, using='default', table_blacklist=QUERY_COUNT_TABLE_BLACKLIST): with self.assertNumQueries(0, using='student_module_history'): with self.assertMongoCallCount(mongo_reads): with self.assertXBlockInstantiations(1): self.grade_course(course_key)
def test_request_context_caching(self): """ Test that the RequestContext is cached in the RequestCache. """ with patch( 'common.djangoapps.edxmako.request_context.get_current_request', return_value=None): # requestcontext should be None, because the cache isn't filled assert get_template_request_context() is None with patch( 'common.djangoapps.edxmako.request_context.get_current_request', return_value=self.request): # requestcontext should not be None, and should fill the cache assert get_template_request_context() is not None mock_get_current_request = Mock() with patch( 'common.djangoapps.edxmako.request_context.get_current_request' ): with patch( 'common.djangoapps.edxmako.request_context.RequestContext.__init__' ) as mock_context_init: # requestcontext should not be None, because the cache is filled assert get_template_request_context() is not None mock_context_init.assert_not_called() mock_get_current_request.assert_not_called() RequestCache.clear_all_namespaces() with patch( 'common.djangoapps.edxmako.request_context.get_current_request', return_value=None): # requestcontext should be None, because the cache isn't filled assert get_template_request_context() is None
def test_setting_override(self, is_enabled, override_choice, expected_result): RequestCache.clear_all_namespaces() self.set_waffle_course_override(override_choice, is_enabled) override_value = WaffleFlagCourseOverrideModel.override_value( self.WAFFLE_TEST_NAME, self.TEST_COURSE_KEY ) self.assertEqual(override_value, expected_result)
def test_request_context_caching(self): """ Test that the RequestContext is cached in the RequestCache. """ with patch('edxmako.request_context.get_current_request', return_value=None): # requestcontext should be None, because the cache isn't filled self.assertIsNone(get_template_request_context()) with patch('edxmako.request_context.get_current_request', return_value=self.request): # requestcontext should not be None, and should fill the cache self.assertIsNotNone(get_template_request_context()) mock_get_current_request = Mock() with patch('edxmako.request_context.get_current_request', mock_get_current_request): # requestcontext should not be None, because the cache is filled self.assertIsNotNone(get_template_request_context()) mock_get_current_request.assert_not_called() RequestCache.clear_all_namespaces() with patch('edxmako.request_context.get_current_request', return_value=None): # requestcontext should be None, because the cache isn't filled self.assertIsNone(get_template_request_context())
def test_setting_override_multiple_times(self): RequestCache.clear_all_namespaces() self.set_waffle_course_override(self.OVERRIDE_CHOICES.on) self.set_waffle_course_override(self.OVERRIDE_CHOICES.off) override_value = WaffleFlagCourseOverrideModel.override_value( self.WAFFLE_TEST_NAME, self.TEST_COURSE_KEY) self.assertEqual(override_value, self.OVERRIDE_CHOICES.off)
def test_get_template_path(self): """ Tests to make sure the get_template_path function works as expected. """ # if the current site has associated SiteTheme then get_template_path should return the argument as is. with patch( "openedx.core.djangoapps.theming.helpers.current_request_has_associated_site_theme", Mock(return_value=True), ): with patch( "openedx.core.djangoapps.theming.helpers.microsite.is_request_in_microsite", Mock(return_value=True), ): with patch("microsite_configuration.microsite.TEMPLATES_BACKEND") as mock_microsite_backend: mock_microsite_backend.get_template = Mock(return_value="/microsite/about.html") self.assertEqual(theming_helpers.get_template_path("about.html"), "about.html") RequestCache.clear_all_namespaces() # if the current site does not have associated SiteTheme then get_template_path should return microsite override with patch( "openedx.core.djangoapps.theming.helpers.current_request_has_associated_site_theme", Mock(return_value=False), ): with patch( "openedx.core.djangoapps.theming.helpers.microsite.is_request_in_microsite", Mock(return_value=True), ): with patch("microsite_configuration.microsite.TEMPLATES_BACKEND") as mock_microsite_backend: mock_microsite_backend.get_template_path = Mock(return_value="/microsite/about.html") self.assertEqual(theming_helpers.get_template_path("about.html"), "/microsite/about.html")
def test_setting_override(self, is_enabled, override_choice, expected_result): RequestCache.clear_all_namespaces() self.set_waffle_course_override(override_choice, is_enabled) override_value = WaffleFlagCourseOverrideModel.override_value( self.WAFFLE_TEST_NAME, self.TEST_COURSE_KEY) self.assertEqual(override_value, expected_result)
def test_request_cached_with_caches_despite_changing_wrapped_result(self): """ Ensure that after caching a result, we always send it back, even if the underlying result changes. """ RequestCache.clear_all_namespaces() to_be_wrapped = Mock() to_be_wrapped.side_effect = [1, 2, 3] self.assertEqual(to_be_wrapped.call_count, 0) def mock_wrapper(*args, **kwargs): """Simple wrapper to let us decorate our mock.""" return to_be_wrapped(*args, **kwargs) wrapped = request_cached(mock_wrapper) result = wrapped() self.assertEqual(result, 1) self.assertEqual(to_be_wrapped.call_count, 1) result = wrapped() self.assertEqual(result, 1) self.assertEqual(to_be_wrapped.call_count, 1) direct_result = mock_wrapper() self.assertEqual(direct_result, 2) self.assertEqual(to_be_wrapped.call_count, 2) result = wrapped() self.assertEqual(result, 1) self.assertEqual(to_be_wrapped.call_count, 2) direct_result = mock_wrapper() self.assertEqual(direct_result, 3) self.assertEqual(to_be_wrapped.call_count, 3)
def _clear_request_cache(**kwargs): """ Once a celery task completes, clear the request cache to prevent memory leaks. """ if getattr(settings, 'CLEAR_REQUEST_CACHE_ON_TASK_COMPLETION', True): RequestCache.clear_all_namespaces()
def test_caching_org(self): course = CourseOverviewFactory.create(org='test-org') site_cfg = SiteConfigurationFactory.create( site_values={'course_org_filter': course.org}, values={'course_org_filter': course.org}) org_config = CourseDurationLimitConfig(org=course.org, enabled=True, enabled_as_of=datetime( 2018, 1, 1)) org_config.save() RequestCache.clear_all_namespaces() # Check that the org value is not retrieved from cache after save with self.assertNumQueries(2): self.assertTrue( CourseDurationLimitConfig.current(org=course.org).enabled) RequestCache.clear_all_namespaces() # Check that the org value can be retrieved from cache after read with self.assertNumQueries(0): self.assertTrue( CourseDurationLimitConfig.current(org=course.org).enabled) org_config.enabled = False org_config.save() RequestCache.clear_all_namespaces() # Check that the org value in cache was deleted on save with self.assertNumQueries(2): self.assertFalse( CourseDurationLimitConfig.current(org=course.org).enabled) global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime( 2018, 1, 1)) global_config.save() RequestCache.clear_all_namespaces() # Check that the org value is not updated in cache by changing the global value with self.assertNumQueries(0): self.assertFalse( CourseDurationLimitConfig.current(org=course.org).enabled) site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime( 2018, 1, 1)) site_config.save() RequestCache.clear_all_namespaces() # Check that the org value is not updated in cache by changing the site value with self.assertNumQueries(0): self.assertFalse( CourseDurationLimitConfig.current(org=course.org).enabled)
def test_setting_override_multiple_times(self): RequestCache.clear_all_namespaces() self.set_waffle_course_override(self.OVERRIDE_CHOICES.on) self.set_waffle_course_override(self.OVERRIDE_CHOICES.off) override_value = WaffleFlagCourseOverrideModel.override_value( self.WAFFLE_TEST_NAME, self.TEST_COURSE_KEY ) self.assertEqual(override_value, self.OVERRIDE_CHOICES.off)
def test_too_many_courses(self): """ Test that search results are limited to 100 courses, and that they don't blow up the database. """ ContentTypeGatingConfig.objects.create( enabled=True, enabled_as_of=datetime(2018, 1, 1), ) CourseDurationLimitConfig.objects.create( enabled=True, enabled_as_of=datetime(2018, 1, 1), ) course_ids = [] # Create 300 courses across 30 organizations for org_num in range(10): org_id = f'org{org_num}' for course_num in range(30): course_name = f'course{org_num}.{course_num}' course_run_name = f'run{org_num}.{course_num}' course = CourseFactory.create(org=org_id, number=course_name, run=course_run_name, emit_signals=True) CourseModeFactory.create(course_id=course.id, mode_slug=CourseMode.AUDIT) CourseModeFactory.create(course_id=course.id, mode_slug=CourseMode.VERIFIED) course_ids.append(course.id) self.setup_user(self.audit_user) # These query counts were found empirically query_counts = [50, 46, 46, 46, 46, 46, 46, 46, 46, 46, 16] ordered_course_ids = sorted( [str(cid) for cid in (course_ids + [c.id for c in self.courses])]) self.clear_caches() for page in range(1, 12): RequestCache.clear_all_namespaces() with self.assertNumQueries(query_counts[page - 1], table_ignorelist=WAFFLE_TABLES): response = self.verify_response(params={ 'page': page, 'page_size': 30 }) assert 'results' in response.data assert response.data['pagination']['count'] == 303 assert len(response.data['results']) == (30 if (page < 11) else 3) assert [c['id'] for c in response.data['results'] ] == ordered_course_ids[((page - 1) * 30):(page * 30)]
def test_too_many_courses(self): """ Test that search results are limited to 100 courses, and that they don't blow up the database. """ ContentTypeGatingConfig.objects.create( enabled=True, enabled_as_of=datetime(2018, 1, 1), ) CourseDurationLimitConfig.objects.create( enabled=True, enabled_as_of=datetime(2018, 1, 1), ) course_ids = [] # Create 300 courses across 30 organizations for org_num in range(10): org_id = 'org{}'.format(org_num) for course_num in range(30): course_name = 'course{}.{}'.format(org_num, course_num) course_run_name = 'run{}.{}'.format(org_num, course_num) course = CourseFactory.create(org=org_id, number=course_name, run=course_run_name, emit_signals=True) CourseModeFactory.create(course_id=course.id, mode_slug=CourseMode.AUDIT) CourseModeFactory.create(course_id=course.id, mode_slug=CourseMode.VERIFIED) course_ids.append(course.id) self.setup_user(self.audit_user) # These query counts were found empirically query_counts = [63, 50, 50, 50, 50, 50, 50, 50, 50, 50, 20] ordered_course_ids = sorted( [str(cid) for cid in (course_ids + [c.id for c in self.courses])]) self.clear_caches() for page in range(1, 12): RequestCache.clear_all_namespaces() with self.assertNumQueries(query_counts[page - 1]): response = self.verify_response(params={ 'page': page, 'page_size': 30 }) self.assertIn('results', response.data) self.assertEqual(response.data['pagination']['count'], 303) self.assertEqual(len(response.data['results']), 30 if page < 11 else 3) self.assertEqual([c['id'] for c in response.data['results']], ordered_course_ids[(page - 1) * 30:page * 30])
def lti_consumer_fields_editing_flag(course_id, enabled_for_course=False): """ Yields CourseEditLTIFieldsEnabledFlag record for unit tests Arguments: course_id (CourseLocator): course locator to control this feature for. enabled_for_course (bool): whether feature is enabled for 'course_id' """ RequestCache.clear_all_namespaces() CourseEditLTIFieldsEnabledFlag.objects.create(course_id=course_id, enabled=enabled_for_course) yield
def setUp(self): super().setUp() flag_name = "test_namespace.test_flag" self.waffle_flag = WaffleFlag(flag_name, __name__) request = RequestFactory().request() crum.set_current_request(request) RequestCache.clear_all_namespaces() self.addCleanup(crum.set_current_request, None) self.addCleanup(RequestCache.clear_all_namespaces)
def assert_access_to_gated_content(self, user): """ Verifies access to gated content for the given user is as expected. """ # clear the request cache to flush any cached access results RequestCache.clear_all_namespaces() # access to gating content (seq1) remains constant assert bool(has_access(user, 'load', self.seq1, self.course.id)) # access to gated content (seq2) remains constant, access is prevented in SeqModule loading assert bool(has_access(user, 'load', self.seq2, self.course.id))
def assert_access_to_gated_content(self, user): """ Verifies access to gated content for the given user is as expected. """ # clear the request cache to flush any cached access results RequestCache.clear_all_namespaces() # access to gating content (seq1) remains constant self.assertTrue(bool(has_access(user, 'load', self.seq1, self.course.id))) # access to gated content (seq2) remains constant, access is prevented in SeqModule loading self.assertTrue(bool(has_access(user, 'load', self.seq2, self.course.id)))
def dump_courses_to_neo4j(self, connection_overrides=None, override_cache=False): """ Method that iterates through a list of courses in a modulestore, serializes them, then submits tasks to write them to neo4j. Arguments: connection_overrides (dict): overrides to Neo4j connection parameters specified in `settings.COURSEGRAPH_CONNECTION`. override_cache: serialize the courses even if they'be been recently serialized Returns: two lists--one of the courses that were successfully written to neo4j and one of courses that were not. """ total_number_of_courses = len(self.course_keys) submitted_courses = [] skipped_courses = [] graph = authenticate_and_create_graph(connection_overrides) for index, course_key in enumerate(self.course_keys): # first, clear the request cache to prevent memory leaks RequestCache.clear_all_namespaces() (needs_dump, reason) = should_dump_course(course_key, graph) if not (override_cache or needs_dump): log.info("skipping submitting %s, since it hasn't changed", course_key) skipped_courses.append(str(course_key)) continue if override_cache: reason = "override_cache is True" log.info( "Now submitting %s for export to neo4j, because %s: course %d of %d total courses", course_key, reason, index + 1, total_number_of_courses, ) dump_course_to_neo4j.apply_async(kwargs=dict( course_key_string=str(course_key), connection_overrides=connection_overrides, )) submitted_courses.append(str(course_key)) return submitted_courses, skipped_courses
def setUp(self): super().setUp() flag_name = "test_namespace.test_flag" self.waffle_flag = WaffleFlag( # lint-amnesty, pylint: disable=toggle-missing-annotation flag_name, __name__ ) request = RequestFactory().request() crum.set_current_request(request) RequestCache.clear_all_namespaces() self.addCleanup(crum.set_current_request, None) self.addCleanup(RequestCache.clear_all_namespaces)
def test_caching_site(self): site_cfg = SiteConfigurationFactory() site_config = ContentTypeGatingConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1)) site_config.save() RequestCache.clear_all_namespaces() # Check that the site value is not retrieved from cache after save with self.assertNumQueries(1): self.assertTrue(ContentTypeGatingConfig.current(site=site_cfg.site).enabled) RequestCache.clear_all_namespaces() # Check that the site value can be retrieved from cache after read with self.assertNumQueries(0): self.assertTrue(ContentTypeGatingConfig.current(site=site_cfg.site).enabled) site_config.enabled = False site_config.save() RequestCache.clear_all_namespaces() # Check that the site value in cache was deleted on save with self.assertNumQueries(1): self.assertFalse(ContentTypeGatingConfig.current(site=site_cfg.site).enabled) global_config = ContentTypeGatingConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1)) global_config.save() RequestCache.clear_all_namespaces() # Check that the site value is not updated in cache by changing the global value with self.assertNumQueries(0): self.assertFalse(ContentTypeGatingConfig.current(site=site_cfg.site).enabled)
def test_caching_site(self): site_cfg = SiteConfigurationFactory() site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1)) site_config.save() RequestCache.clear_all_namespaces() # Check that the site value is not retrieved from cache after save with self.assertNumQueries(1): self.assertTrue(CourseDurationLimitConfig.current(site=site_cfg.site).enabled) RequestCache.clear_all_namespaces() # Check that the site value can be retrieved from cache after read with self.assertNumQueries(0): self.assertTrue(CourseDurationLimitConfig.current(site=site_cfg.site).enabled) site_config.enabled = False site_config.save() RequestCache.clear_all_namespaces() # Check that the site value in cache was deleted on save with self.assertNumQueries(1): self.assertFalse(CourseDurationLimitConfig.current(site=site_cfg.site).enabled) global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1)) global_config.save() RequestCache.clear_all_namespaces() # Check that the site value is not updated in cache by changing the global value with self.assertNumQueries(0): self.assertFalse(CourseDurationLimitConfig.current(site=site_cfg.site).enabled)
def test_too_many_courses(self): """ Test that search results are limited to 100 courses, and that they don't blow up the database. """ ContentTypeGatingConfig.objects.create( enabled=True, enabled_as_of=datetime(2018, 1, 1), ) CourseDurationLimitConfig.objects.create( enabled=True, enabled_as_of=datetime(2018, 1, 1), ) course_ids = [] # Create 300 courses across 30 organizations for org_num in range(10): org_id = 'org{}'.format(org_num) for course_num in range(30): course_name = 'course{}.{}'.format(org_num, course_num) course_run_name = 'run{}.{}'.format(org_num, course_num) course = CourseFactory.create(org=org_id, number=course_name, run=course_run_name, emit_signals=True) CourseModeFactory.create(course_id=course.id, mode_slug=CourseMode.AUDIT) CourseModeFactory.create(course_id=course.id, mode_slug=CourseMode.VERIFIED) course_ids.append(course.id) self.setup_user(self.audit_user) # These query counts were found empirically query_counts = [63, 50, 50, 50, 50, 50, 50, 50, 50, 50, 20] ordered_course_ids = sorted([str(cid) for cid in (course_ids + [c.id for c in self.courses])]) self.clear_caches() for page in range(1, 12): RequestCache.clear_all_namespaces() with self.assertNumQueries(query_counts[page - 1]): response = self.verify_response(params={'page': page, 'page_size': 30}) self.assertIn('results', response.data) self.assertEqual(response.data['pagination']['count'], 303) self.assertEqual(len(response.data['results']), 30 if page < 11 else 3) self.assertEqual( [c['id'] for c in response.data['results']], ordered_course_ids[(page - 1) * 30:page * 30] )
def persistent_grades_feature_flags(global_flag, enabled_for_all_courses=False, course_id=None, enabled_for_course=False): """ Most test cases will use a single call to this manager, as they need to set the global setting and the course-specific setting for a single course. """ RequestCache.clear_all_namespaces() PersistentGradesEnabledFlag.objects.create( enabled=global_flag, enabled_for_all_courses=enabled_for_all_courses) if course_id: CoursePersistentGradesFlag.objects.create(course_id=course_id, enabled=enabled_for_course) yield
def test_gradebook(self): self.course.enable_ccx = True RequestCache.clear_all_namespaces() url = reverse( 'ccx_gradebook', kwargs={'course_id': self.ccx_key} ) response = self.client.get(url) assert response.status_code == 200 # Max number of student per page is one. Patched setting MAX_STUDENTS_PER_PAGE_GRADE_BOOK = 1 assert len(response.mako_context['students']) == 1 student_info = response.mako_context['students'][0] assert student_info['grade_summary']['percent'] == 0.5 assert list(student_info['grade_summary']['grade_breakdown'].values())[0]['percent'] == 0.5 assert len(student_info['grade_summary']['section_breakdown']) == 4
def clear_caches(cls): """ Clear all of the caches defined in settings.CACHES. """ # N.B. As of 2016-04-20, Django won't return any caches # from django.core.cache.caches.all() that haven't been # accessed using caches[name] previously, so we loop # over our list of overridden caches, instead. for cache in settings.CACHES: caches[cache].clear() # The sites framework caches in a module-level dictionary. # Clear that. sites.models.SITE_CACHE.clear() RequestCache.clear_all_namespaces()
def persistent_grades_feature_flags( global_flag, enabled_for_all_courses=False, course_id=None, enabled_for_course=False ): """ Most test cases will use a single call to this manager, as they need to set the global setting and the course-specific setting for a single course. """ RequestCache.clear_all_namespaces() PersistentGradesEnabledFlag.objects.create(enabled=global_flag, enabled_for_all_courses=enabled_for_all_courses) if course_id: CoursePersistentGradesFlag.objects.create(course_id=course_id, enabled=enabled_for_course) yield
def setUp(self): """ Set up test data """ super(ProgramCourseEnrollmentModelTests, self).setUp() RequestCache.clear_all_namespaces() self.user = UserFactory.create() self.program_uuid = uuid4() self.program_enrollment = ProgramEnrollment.objects.create( user=self.user, external_user_key='abc', program_uuid=self.program_uuid, curriculum_uuid=uuid4(), status='enrolled') self.course_key = CourseKey.from_string(generate_course_run_key()) CourseOverviewFactory(id=self.course_key)
def setUp(self): """ Set up test data """ super(ProgramCourseEnrollmentModelTests, self).setUp() RequestCache.clear_all_namespaces() self.user = UserFactory(username="******") self.program_uuid = UUID("88888888-4444-2222-1111-000000000000") self.curriculum_uuid = UUID("77777777-4444-2222-1111-000000000000") self.program_enrollment = ProgramEnrollmentFactory( user=self.user, external_user_key='abc', program_uuid=self.program_uuid, curriculum_uuid=self.curriculum_uuid, status='enrolled') self.course_key = CourseKey.from_string("course-v1:blah+blah+blah") CourseOverviewFactory(id=self.course_key)
def setUp(self): """ Set up test data """ super(ProgramCourseEnrollmentModelTests, self).setUp() RequestCache.clear_all_namespaces() self.user = UserFactory.create() self.program_uuid = uuid4() self.program_enrollment = ProgramEnrollment.objects.create( user=self.user, external_user_key='abc', program_uuid=self.program_uuid, curriculum_uuid=uuid4(), status='enrolled' ) self.course_key = CourseKey.from_string(generate_course_run_key()) CourseOverviewFactory(id=self.course_key)
def test_request_cached_with_changing_kwargs(self): """ Ensure that calling a decorated function with different keyword arguments will not use a cached value invoked by a previous call with different arguments. """ RequestCache.clear_all_namespaces() to_be_wrapped = Mock() to_be_wrapped.side_effect = [1, 2, 3, 4, 5, 6] self.assertEqual(to_be_wrapped.call_count, 0) def mock_wrapper(*args, **kwargs): """Simple wrapper to let us decorate our mock.""" return to_be_wrapped(*args, **kwargs) wrapped = request_cached(mock_wrapper) # This will be a miss, and make an underlying call. result = wrapped(1, foo=1) self.assertEqual(result, 1) self.assertEqual(to_be_wrapped.call_count, 1) # This will be a miss, and make an underlying call. result = wrapped(2, foo=2) self.assertEqual(result, 2) self.assertEqual(to_be_wrapped.call_count, 2) # This is bypass of the decorator. direct_result = mock_wrapper(3, foo=3) self.assertEqual(direct_result, 3) self.assertEqual(to_be_wrapped.call_count, 3) # These will be hits, and not make an underlying call. result = wrapped(1, foo=1) self.assertEqual(result, 1) self.assertEqual(to_be_wrapped.call_count, 3) result = wrapped(2, foo=2) self.assertEqual(result, 2) self.assertEqual(to_be_wrapped.call_count, 3) # Since we're changing foo, this will be a miss. result = wrapped(2, foo=5) self.assertEqual(result, 4) self.assertEqual(to_be_wrapped.call_count, 4)
def test_caching_org(self): course = CourseOverviewFactory.create(org='test-org') site_cfg = SiteConfigurationFactory.create(values={'course_org_filter': course.org}) org_config = ContentTypeGatingConfig(org=course.org, enabled=True, enabled_as_of=datetime(2018, 1, 1)) org_config.save() RequestCache.clear_all_namespaces() # Check that the org value is not retrieved from cache after save with self.assertNumQueries(2): self.assertTrue(ContentTypeGatingConfig.current(org=course.org).enabled) RequestCache.clear_all_namespaces() # Check that the org value can be retrieved from cache after read with self.assertNumQueries(0): self.assertTrue(ContentTypeGatingConfig.current(org=course.org).enabled) org_config.enabled = False org_config.save() RequestCache.clear_all_namespaces() # Check that the org value in cache was deleted on save with self.assertNumQueries(2): self.assertFalse(ContentTypeGatingConfig.current(org=course.org).enabled) global_config = ContentTypeGatingConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1)) global_config.save() RequestCache.clear_all_namespaces() # Check that the org value is not updated in cache by changing the global value with self.assertNumQueries(0): self.assertFalse(ContentTypeGatingConfig.current(org=course.org).enabled) site_config = ContentTypeGatingConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1)) site_config.save() RequestCache.clear_all_namespaces() # Check that the org value is not updated in cache by changing the site value with self.assertNumQueries(0): self.assertFalse(ContentTypeGatingConfig.current(org=course.org).enabled)
def dump_courses_to_neo4j(self, credentials, override_cache=False): """ Method that iterates through a list of courses in a modulestore, serializes them, then submits tasks to write them to neo4j. Arguments: credentials (dict): the necessary credentials to connect to neo4j and create a py2neo `Graph` object override_cache: serialize the courses even if they'be been recently serialized Returns: two lists--one of the courses that were successfully written to neo4j and one of courses that were not. """ total_number_of_courses = len(self.course_keys) submitted_courses = [] skipped_courses = [] graph = authenticate_and_create_graph(credentials) for index, course_key in enumerate(self.course_keys): # first, clear the request cache to prevent memory leaks RequestCache.clear_all_namespaces() log.info( "Now submitting %s for export to neo4j: course %d of %d total courses", course_key, index + 1, total_number_of_courses, ) if not (override_cache or should_dump_course(course_key, graph)): log.info("skipping submitting %s, since it hasn't changed", course_key) skipped_courses.append(six.text_type(course_key)) continue dump_course_to_neo4j.apply_async( args=[six.text_type(course_key), credentials], ) submitted_courses.append(six.text_type(course_key)) return submitted_courses, skipped_courses
def test_request_cached_with_none_result(self): """ Ensure that calling a decorated function that returns None properly caches the result and doesn't recall the underlying function. """ RequestCache.clear_all_namespaces() to_be_wrapped = Mock() to_be_wrapped.side_effect = [None, None, None, 1, 1] self.assertEqual(to_be_wrapped.call_count, 0) def mock_wrapper(*args, **kwargs): """Simple wrapper to let us decorate our mock.""" return to_be_wrapped(*args, **kwargs) wrapped = request_cached(mock_wrapper) # This will be a miss, and make an underlying call. result = wrapped(1) self.assertEqual(result, None) self.assertEqual(to_be_wrapped.call_count, 1) # This will be a miss, and make an underlying call. result = wrapped(2) self.assertEqual(result, None) self.assertEqual(to_be_wrapped.call_count, 2) # This is bypass of the decorator. direct_result = mock_wrapper(3) self.assertEqual(direct_result, None) self.assertEqual(to_be_wrapped.call_count, 3) # These will be hits, and not make an underlying call. result = wrapped(1) self.assertEqual(result, None) self.assertEqual(to_be_wrapped.call_count, 3) result = wrapped(2) self.assertEqual(result, None) self.assertEqual(to_be_wrapped.call_count, 3)
def test_authenticated_user_found_is_properly_reset( self, mock_set_custom_attribute): # set user before process_request self.request.user = UserFactory() self.middleware.process_request(self.request) self.middleware.process_response(self.request, None) mock_set_custom_attribute.assert_any_call( 'request_authenticated_user_found_in_middleware', 'process_request') # set up new request and set user before process_response mock_set_custom_attribute.reset_mock() RequestCache.clear_all_namespaces() self.request = RequestFactory().get('/') self.request.user = UserFactory() self.middleware.process_response(self.request, None) mock_set_custom_attribute.assert_any_call( 'request_authenticated_user_found_in_middleware', 'process_response')
def test_request_cached_mixed_unicode_str_args(self): """ Ensure that request_cached can work with mixed str and Unicode parameters. """ RequestCache.clear_all_namespaces() def dummy_function(arg1, arg2): """ A dummy function that expects an str and unicode arguments. """ assert isinstance(arg1, str), 'First parameter has to be of type `str`' assert isinstance(arg2, unicode), 'Second parameter has to be of type `unicode`' return True self.assertTrue(dummy_function('Hello', u'World'), 'Should be callable with ASCII chars') self.assertTrue(dummy_function('H∂llå', u'Wørld'), 'Should be callable with non-ASCII chars') wrapped = request_cached(dummy_function) self.assertTrue(wrapped('Hello', u'World'), 'Wrapper should handle ASCII only chars') self.assertTrue(wrapped('H∂llå', u'Wørld'), 'Wrapper should handle non-ASCII chars')
def test_grades_csv(self): self.course.enable_ccx = True RequestCache.clear_all_namespaces() url = reverse( 'ccx_grades_csv', kwargs={'course_id': self.ccx_key} ) response = self.client.get(url) assert response.status_code == 200 # Are the grades downloaded as an attachment? assert response['content-disposition'] == 'attachment' rows = response.content.decode('utf-8').strip().split('\r') headers = rows[0] # picking first student records data = dict(list(zip(headers.strip().split(','), rows[1].strip().split(',')))) assert 'HW 04' not in data assert data['HW 01'] == '0.75' assert data['HW 02'] == '0.5' assert data['HW 03'] == '0.25' assert data['HW Avg'] == '0.5'
def test_caching_global(self): global_config = ContentTypeGatingConfig(enabled=True, enabled_as_of=datetime( 2018, 1, 1)) global_config.save() RequestCache.clear_all_namespaces() # Check that the global value is not retrieved from cache after save with self.assertNumQueries(1): assert ContentTypeGatingConfig.current().enabled RequestCache.clear_all_namespaces() # Check that the global value can be retrieved from cache after read with self.assertNumQueries(0): assert ContentTypeGatingConfig.current().enabled global_config.enabled = False global_config.save() RequestCache.clear_all_namespaces() # Check that the global value in cache was deleted on save with self.assertNumQueries(1): assert not ContentTypeGatingConfig.current().enabled
def test_caching_global(self): global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime( 2018, 1, 1, tzinfo=pytz.UTC)) global_config.save() RequestCache.clear_all_namespaces() # Check that the global value is not retrieved from cache after save with self.assertNumQueries(1): self.assertTrue(CourseDurationLimitConfig.current().enabled) RequestCache.clear_all_namespaces() # Check that the global value can be retrieved from cache after read with self.assertNumQueries(0): self.assertTrue(CourseDurationLimitConfig.current().enabled) global_config.enabled = False global_config.save() RequestCache.clear_all_namespaces() # Check that the global value in cache was deleted on save with self.assertNumQueries(1): self.assertFalse(CourseDurationLimitConfig.current().enabled)
def test_caching_global(self): global_config = ContentTypeGatingConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1)) global_config.save() RequestCache.clear_all_namespaces() # Check that the global value is not retrieved from cache after save with self.assertNumQueries(1): self.assertTrue(ContentTypeGatingConfig.current().enabled) RequestCache.clear_all_namespaces() # Check that the global value can be retrieved from cache after read with self.assertNumQueries(0): self.assertTrue(ContentTypeGatingConfig.current().enabled) global_config.enabled = False global_config.save() RequestCache.clear_all_namespaces() # Check that the global value in cache was deleted on save with self.assertNumQueries(1): self.assertFalse(ContentTypeGatingConfig.current().enabled)
def setUp(self): super(SocialAuthEnrollmentCompletionSignalTest, self).setUp() RequestCache.clear_all_namespaces() catalog_org = CatalogOrganizationFactory.create(key=self.organization.short_name) self.program_uuid = self._create_catalog_program(catalog_org)['uuid']
def setUp(self): super(TestCourseWaffleFlag, self).setUp() request = RequestFactory().request() self.addCleanup(crum.set_current_request, None) crum.set_current_request(request) RequestCache.clear_all_namespaces()
def setUp(self): RequestCache.clear_all_namespaces()