Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
e7ce4106
Commit
e7ce4106
authored
Aug 11, 2014
by
Calen Pennington
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve debuggability when call-count numbers don't match up
parent
337b0b48
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
145 additions
and
130 deletions
+145
-130
cms/djangoapps/contentstore/tests/test_contentstore.py
+2
-2
cms/djangoapps/contentstore/tests/test_course_listing.py
+3
-2
common/lib/xmodule/xmodule/modulestore/tests/factories.py
+42
-69
common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
+74
-46
common/lib/xmodule/xmodule/modulestore/tests/test_publish.py
+21
-8
common/lib/xmodule/xmodule/modulestore/xml_importer.py
+1
-1
lms/djangoapps/courseware/tests/test_module_render.py
+2
-2
No files found.
cms/djangoapps/contentstore/tests/test_contentstore.py
View file @
e7ce4106
...
...
@@ -867,7 +867,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
# so we don't need to make an extra query to compute it.
# set the branch to 'publish' in order to prevent extra lookups of draft versions
with
mongo_store
.
branch_setting
(
ModuleStoreEnum
.
Branch
.
published_only
):
with
check_mongo_calls
(
mongo_store
,
4
,
0
):
with
check_mongo_calls
(
4
,
0
):
course
=
mongo_store
.
get_course
(
course_id
,
depth
=
2
)
# make sure we pre-fetched a known sequential which should be at depth=2
...
...
@@ -879,7 +879,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
# Now, test with the branch set to draft. No extra round trips b/c it doesn't go deep enough to get
# beyond direct only categories
with
mongo_store
.
branch_setting
(
ModuleStoreEnum
.
Branch
.
draft_preferred
):
with
check_mongo_calls
(
mongo_store
,
4
,
0
):
with
check_mongo_calls
(
4
,
0
):
mongo_store
.
get_course
(
course_id
,
depth
=
2
)
def
test_export_course_without_content_store
(
self
):
...
...
cms/djangoapps/contentstore/tests/test_course_listing.py
View file @
e7ce4106
...
...
@@ -201,10 +201,11 @@ class TestCourseListing(ModuleStoreTestCase):
# Now count the db queries
store
=
modulestore
()
.
_get_modulestore_by_type
(
ModuleStoreEnum
.
Type
.
mongo
)
with
check_mongo_calls
(
store
,
USER_COURSES_COUNT
):
with
check_mongo_calls
(
USER_COURSES_COUNT
):
_accessible_courses_list_from_groups
(
self
.
request
)
with
check_mongo_calls
(
store
,
1
):
# TODO: LMS-11220: Document why this takes 6 calls
with
check_mongo_calls
(
6
):
_accessible_courses_list
(
self
.
request
)
def
test_get_course_list_with_same_course_id
(
self
):
...
...
common/lib/xmodule/xmodule/modulestore/tests/factories.py
View file @
e7ce4106
import
pprint
import
pymongo.message
from
factory
import
Factory
,
lazy_attribute_sequence
,
lazy_attribute
from
factory.containers
import
CyclicDefinitionError
from
uuid
import
uuid4
...
...
@@ -223,104 +226,74 @@ def check_exact_number_of_calls(object_with_method, method_name, num_calls):
yield
@contextmanager
def
check_number_of_calls
(
object_with_method
,
method_name
,
maximum_calls
,
minimum_calls
=
1
):
"""
Instruments the given method on the given object to verify the number of calls to the method is
less than or equal to the expected maximum_calls and greater than or equal to the expected minimum_calls.
"""
method
=
getattr
(
object_with_method
,
method_name
)
method_wrap
=
Mock
(
wraps
=
method
)
wrap_patch
=
patch
.
object
(
object_with_method
,
method_name
,
method_wrap
)
return
check_sum_of_calls
(
object_with_method
,
[
method_name
],
maximum_calls
,
minimum_calls
)
try
:
wrap_patch
.
start
()
@contextmanager
def
check_sum_of_calls
(
object_
,
methods
,
maximum_calls
,
minimum_calls
=
1
):
"""
Instruments the given methods on the given object to verify that the total sum of calls made to the
methods falls between minumum_calls and maximum_calls.
"""
mocks
=
{
method
:
Mock
(
wraps
=
getattr
(
object_
,
method
))
for
method
in
methods
}
with
patch
.
multiple
(
object_
,
**
mocks
):
yield
finally
:
wrap_patch
.
stop
()
call_count
=
sum
(
mock
.
call_count
for
mock
in
mocks
.
values
())
calls
=
pprint
.
pformat
({
method_name
:
mock
.
call_args_list
for
method_name
,
mock
in
mocks
.
items
()
})
# verify the counter actually worked by ensuring we have counted greater than (or equal to) the minimum calls
assert_greater_equal
(
method_wrap
.
call_count
,
minimum_calls
,
"Expected at least {} calls, {} were made. Calls: {}"
.
format
(
# Assertion errors don't handle multi-line values, so pretty-print to std-out instead
if
not
minimum_calls
<=
call_count
<=
maximum_calls
:
print
"Expected between {} and {} calls, {} were made. Calls: {}"
.
format
(
minimum_calls
,
method_wrap
.
call_count
,
method_wrap
.
call_args_list
)
maximum_calls
,
call_count
,
calls
,
)
# verify the counter actually worked by ensuring we have counted greater than (or equal to) the minimum calls
assert_greater_equal
(
call_count
,
minimum_calls
)
# now verify the number of actual calls is less than (or equal to) the expected maximum
assert_less_equal
(
method_wrap
.
call_count
,
maximum_calls
,
"Expected at most {} calls, {} were made. Calls: {}"
.
format
(
maximum_calls
,
method_wrap
.
call_count
,
method_wrap
.
call_args_list
)
)
assert_less_equal
(
call_count
,
maximum_calls
)
@contextmanager
def
check_mongo_calls
(
mongo_store
,
num_finds
=
0
,
num_sends
=
None
):
def
check_mongo_calls
(
num_finds
=
0
,
num_sends
=
None
):
"""
Instruments the given store to count the number of calls to find (incl find_one) and the number
of calls to send_message which is for insert, update, and remove (if you provide num_sends). At the
end of the with statement, it compares the counts to the num_finds and num_sends.
:param mongo_store: the MongoModulestore or subclass to watch or a SplitMongoModuleStore
:param num_finds: the exact number of find calls expected
:param num_sends: If none, don't instrument the send calls. If non-none, count and compare to
the given int value.
"""
if
mongo_store
.
get_modulestore_type
()
==
ModuleStoreEnum
.
Type
.
mongo
:
with
check_exact_number_of_calls
(
mongo_store
.
collection
,
'find'
,
num_finds
):
if
num_sends
is
not
None
:
with
check_exact_number_of_calls
(
mongo_store
.
database
.
connection
,
'_send_message'
,
num_sends
,
with
check_sum_of_calls
(
pymongo
.
message
,
[
'query'
,
'get_more'
],
num_finds
,
num_finds
):
yield
else
:
yield
elif
mongo_store
.
get_modulestore_type
()
==
ModuleStoreEnum
.
Type
.
split
:
collections
=
[
mongo_store
.
db_connection
.
course_index
,
mongo_store
.
db_connection
.
structures
,
mongo_store
.
db_connection
.
definitions
,
]
# could add else clause which raises exception or just rely on the below to suss that out
try
:
find_wraps
=
[]
wrap_patches
=
[]
for
collection
in
collections
:
find_wrap
=
Mock
(
wraps
=
collection
.
find
)
find_wraps
.
append
(
find_wrap
)
wrap_patch
=
patch
.
object
(
collection
,
'find'
,
find_wrap
)
wrap_patches
.
append
(
wrap_patch
)
wrap_patch
.
start
()
if
num_sends
is
not
None
:
connection
=
mongo_store
.
db_connection
.
database
.
connection
with
check_exact_number_of_calls
(
connection
,
'_send_message'
,
# pylint: disable=protected-access
with
check_sum_of_calls
(
pymongo
.
message
,
[
'insert'
,
'update'
,
'delete'
],
num_sends
,
num_sends
):
yield
else
:
yield
finally
:
map
(
lambda
wrap_patch
:
wrap_patch
.
stop
(),
wrap_patches
)
call_count
=
sum
([
find_wrap
.
call_count
for
find_wrap
in
find_wraps
])
assert_equal
(
call_count
,
num_finds
,
"Expected {} calls, {} were made. Calls: {}"
.
format
(
num_finds
,
call_count
,
[
find_wrap
.
call_args_list
for
find_wrap
in
find_wraps
]
)
)
common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
View file @
e7ce4106
...
...
@@ -272,8 +272,13 @@ class TestMixedModuleStore(unittest.TestCase):
with
self
.
assertRaises
(
DuplicateCourseError
):
self
.
store
.
create_course
(
'org_x'
,
'course_y'
,
'run_z'
,
self
.
user_id
)
# Draft:
# - One lookup to locate an item that exists
# - Two lookups to determine an item doesn't exist (one to check mongo, one to check split)
# split has one lookup for the course and then one for the course items
@ddt.data
((
'draft'
,
1
,
0
),
(
'split'
,
2
,
0
))
# TODO: LMS-11220: Document why draft find count is [1, 1]
# TODO: LMS-11220: Document why split find count is [2, 2]
@ddt.data
((
'draft'
,
[
1
,
1
],
0
),
(
'split'
,
[
2
,
2
],
0
))
@ddt.unpack
def
test_has_item
(
self
,
default_ms
,
max_find
,
max_send
):
self
.
initdb
(
default_ms
)
...
...
@@ -281,15 +286,14 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
assertTrue
(
self
.
store
.
has_item
(
self
.
course_locations
[
self
.
XML_COURSEID1
]))
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
with
check_mongo_calls
(
mongo_store
,
max_find
,
max_send
):
with
check_mongo_calls
(
max_find
.
pop
(
0
),
max_send
):
self
.
assertTrue
(
self
.
store
.
has_item
(
self
.
problem_x1a_1
))
# try negative cases
self
.
assertFalse
(
self
.
store
.
has_item
(
self
.
course_locations
[
self
.
XML_COURSEID1
]
.
replace
(
name
=
'not_findable'
,
category
=
'problem'
)
))
with
check_mongo_calls
(
m
ongo_store
,
max_find
,
max_send
):
with
check_mongo_calls
(
m
ax_find
.
pop
(
0
)
,
max_send
):
self
.
assertFalse
(
self
.
store
.
has_item
(
self
.
fake_location
))
# verify that an error is raised when the revision is not valid
...
...
@@ -298,7 +302,9 @@ class TestMixedModuleStore(unittest.TestCase):
# draft is 2 to compute inheritance
# split is 2 (would be 3 on course b/c it looks up the wiki_slug in definitions)
@ddt.data
((
'draft'
,
2
,
0
),
(
'split'
,
2
,
0
))
# TODO: LMS-11220: Document why draft find count is [2, 2]
# TODO: LMS-11220: Document why split find count is [3, 3]
@ddt.data
((
'draft'
,
[
2
,
2
],
0
),
(
'split'
,
[
3
,
3
],
0
))
@ddt.unpack
def
test_get_item
(
self
,
default_ms
,
max_find
,
max_send
):
self
.
initdb
(
default_ms
)
...
...
@@ -306,8 +312,7 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
assertIsNotNone
(
self
.
store
.
get_item
(
self
.
course_locations
[
self
.
XML_COURSEID1
]))
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
with
check_mongo_calls
(
mongo_store
,
max_find
,
max_send
):
with
check_mongo_calls
(
max_find
.
pop
(
0
),
max_send
):
self
.
assertIsNotNone
(
self
.
store
.
get_item
(
self
.
problem_x1a_1
))
# try negative cases
...
...
@@ -315,7 +320,7 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
store
.
get_item
(
self
.
course_locations
[
self
.
XML_COURSEID1
]
.
replace
(
name
=
'not_findable'
,
category
=
'problem'
)
)
with
check_mongo_calls
(
m
ongo_store
,
max_find
,
max_send
):
with
check_mongo_calls
(
m
ax_find
.
pop
(
0
)
,
max_send
):
with
self
.
assertRaises
(
ItemNotFoundError
):
self
.
store
.
get_item
(
self
.
fake_location
)
...
...
@@ -324,7 +329,8 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
store
.
get_item
(
self
.
fake_location
,
revision
=
ModuleStoreEnum
.
RevisionOption
.
draft_preferred
)
# compared to get_item for the course, draft asks for both draft and published
@ddt.data
((
'draft'
,
8
,
0
),
(
'split'
,
2
,
0
))
# TODO: LMS-11220: Document why split find count is 3
@ddt.data
((
'draft'
,
8
,
0
),
(
'split'
,
3
,
0
))
@ddt.unpack
def
test_get_items
(
self
,
default_ms
,
max_find
,
max_send
):
self
.
initdb
(
default_ms
)
...
...
@@ -336,9 +342,8 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
assertEqual
(
len
(
modules
),
1
)
self
.
assertEqual
(
modules
[
0
]
.
location
,
course_locn
)
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
course_locn
=
self
.
course_locations
[
self
.
MONGO_COURSEID
]
with
check_mongo_calls
(
m
ongo_store
,
m
ax_find
,
max_send
):
with
check_mongo_calls
(
max_find
,
max_send
):
# NOTE: use get_course if you just want the course. get_items is expensive
modules
=
self
.
store
.
get_items
(
course_locn
.
course_key
,
qualifiers
=
{
'category'
:
'problem'
})
self
.
assertEqual
(
len
(
modules
),
6
)
...
...
@@ -352,8 +357,8 @@ class TestMixedModuleStore(unittest.TestCase):
# draft: 2 to look in draft and then published and then 5 for updating ancestors.
# split: 1 for the course index, 1 for the course structure before the change, 1 for the structure after the change
# 2 sends
to update index & structure (calculator is a setting field)
@ddt.data
((
'draft'
,
7
,
5
),
(
'split'
,
3
,
2
))
# 2 sends
: insert structure, update index_entry
@ddt.data
((
'draft'
,
11
,
5
),
(
'split'
,
3
,
2
))
@ddt.unpack
def
test_update_item
(
self
,
default_ms
,
max_find
,
max_send
):
"""
...
...
@@ -369,12 +374,11 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
store
.
update_item
(
course
,
self
.
user_id
)
# now do it for a r/w db
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
problem
=
self
.
store
.
get_item
(
self
.
problem_x1a_1
)
# if following raised, then the test is really a noop, change it
self
.
assertNotEqual
(
problem
.
max_attempts
,
2
,
"Default changed making test meaningless"
)
problem
.
max_attempts
=
2
with
check_mongo_calls
(
m
ongo_store
,
m
ax_find
,
max_send
):
with
check_mongo_calls
(
max_find
,
max_send
):
problem
=
self
.
store
.
update_item
(
problem
,
self
.
user_id
)
self
.
assertEqual
(
problem
.
max_attempts
,
2
,
"Update didn't persist"
)
...
...
@@ -435,7 +439,10 @@ class TestMixedModuleStore(unittest.TestCase):
component
=
self
.
store
.
publish
(
component
.
location
,
self
.
user_id
)
self
.
assertFalse
(
self
.
store
.
has_changes
(
component
))
@ddt.data
((
'draft'
,
7
,
2
),
(
'split'
,
2
,
4
))
# TODO: LMS-11220: Document why split find count is 4
# TODO: LMS-11220: Document why draft find count is 8
# TODO: LMS-11220: Document why split send count is 3
@ddt.data
((
'draft'
,
8
,
2
),
(
'split'
,
4
,
3
))
@ddt.unpack
def
test_delete_item
(
self
,
default_ms
,
max_find
,
max_send
):
"""
...
...
@@ -447,14 +454,16 @@ class TestMixedModuleStore(unittest.TestCase):
with
self
.
assertRaises
(
NotImplementedError
):
self
.
store
.
delete_item
(
self
.
xml_chapter_location
,
self
.
user_id
)
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
with
check_mongo_calls
(
mongo_store
,
max_find
,
max_send
):
with
check_mongo_calls
(
max_find
,
max_send
):
self
.
store
.
delete_item
(
self
.
writable_chapter_location
,
self
.
user_id
)
# verify it's gone
with
self
.
assertRaises
(
ItemNotFoundError
):
self
.
store
.
get_item
(
self
.
writable_chapter_location
)
@ddt.data
((
'draft'
,
8
,
2
),
(
'split'
,
2
,
4
))
# TODO: LMS-11220: Document why draft find count is 9
# TODO: LMS-11220: Document why split send count is 3
@ddt.data
((
'draft'
,
9
,
2
),
(
'split'
,
4
,
3
))
@ddt.unpack
def
test_delete_private_vertical
(
self
,
default_ms
,
max_find
,
max_send
):
"""
...
...
@@ -485,8 +494,7 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
assertIn
(
vert_loc
,
course
.
children
)
# delete the vertical and ensure the course no longer points to it
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
with
check_mongo_calls
(
mongo_store
,
max_find
,
max_send
):
with
check_mongo_calls
(
max_find
,
max_send
):
self
.
store
.
delete_item
(
vert_loc
,
self
.
user_id
)
course
=
self
.
store
.
get_course
(
self
.
course_locations
[
self
.
MONGO_COURSEID
]
.
course_key
,
0
)
if
hasattr
(
private_vert
.
location
,
'version_guid'
):
...
...
@@ -500,7 +508,9 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
assertFalse
(
self
.
store
.
has_item
(
leaf_loc
))
self
.
assertNotIn
(
vert_loc
,
course
.
children
)
@ddt.data
((
'draft'
,
4
,
1
),
(
'split'
,
1
,
2
))
# TODO: LMS-11220: Document why split send count is 2
# TODO: LMS-11220: Document why draft find count is 5
@ddt.data
((
'draft'
,
5
,
1
),
(
'split'
,
2
,
2
))
@ddt.unpack
def
test_delete_draft_vertical
(
self
,
default_ms
,
max_find
,
max_send
):
"""
...
...
@@ -529,18 +539,18 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
store
.
publish
(
private_vert
.
location
,
self
.
user_id
)
private_leaf
.
display_name
=
'change me'
private_leaf
=
self
.
store
.
update_item
(
private_leaf
,
self
.
user_id
)
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
# test succeeds if delete succeeds w/o error
with
check_mongo_calls
(
m
ongo_store
,
m
ax_find
,
max_send
):
with
check_mongo_calls
(
max_find
,
max_send
):
self
.
store
.
delete_item
(
private_leaf
.
location
,
self
.
user_id
)
@ddt.data
((
'draft'
,
2
,
0
),
(
'split'
,
3
,
0
))
# TODO: LMS-11220: Document why split find count is 5
# TODO: LMS-11220: Document why draft find count is 4
@ddt.data
((
'draft'
,
4
,
0
),
(
'split'
,
5
,
0
))
@ddt.unpack
def
test_get_courses
(
self
,
default_ms
,
max_find
,
max_send
):
self
.
initdb
(
default_ms
)
# we should have 3 total courses across all stores
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
with
check_mongo_calls
(
mongo_store
,
max_find
,
max_send
):
with
check_mongo_calls
(
max_find
,
max_send
):
courses
=
self
.
store
.
get_courses
()
course_ids
=
[
course
.
location
for
course
in
courses
]
self
.
assertEqual
(
len
(
courses
),
3
,
"Not 3 courses: {}"
.
format
(
course_ids
))
...
...
@@ -581,7 +591,8 @@ class TestMixedModuleStore(unittest.TestCase):
# draft is 2 to compute inheritance
# split is 3 (one for the index, one for the definition to check if the wiki is set, and one for the course structure
@ddt.data
((
'draft'
,
2
,
0
),
(
'split'
,
3
,
0
))
# TODO: LMS-11220: Document why split find count is 4
@ddt.data
((
'draft'
,
2
,
0
),
(
'split'
,
4
,
0
))
@ddt.unpack
def
test_get_course
(
self
,
default_ms
,
max_find
,
max_send
):
"""
...
...
@@ -589,8 +600,7 @@ class TestMixedModuleStore(unittest.TestCase):
of getting an item whose scope.content fields are looked at.
"""
self
.
initdb
(
default_ms
)
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
with
check_mongo_calls
(
mongo_store
,
max_find
,
max_send
):
with
check_mongo_calls
(
max_find
,
max_send
):
course
=
self
.
store
.
get_item
(
self
.
course_locations
[
self
.
MONGO_COURSEID
])
self
.
assertEqual
(
course
.
id
,
self
.
course_locations
[
self
.
MONGO_COURSEID
]
.
course_key
)
...
...
@@ -599,7 +609,8 @@ class TestMixedModuleStore(unittest.TestCase):
# notice this doesn't test getting a public item via draft_preferred which draft would have 2 hits (split
# still only 2)
@ddt.data
((
'draft'
,
1
,
0
),
(
'split'
,
2
,
0
))
# TODO: LMS-11220: Document why draft find count is 2
@ddt.data
((
'draft'
,
2
,
0
),
(
'split'
,
2
,
0
))
@ddt.unpack
def
test_get_parent_locations
(
self
,
default_ms
,
max_find
,
max_send
):
"""
...
...
@@ -608,8 +619,7 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
initdb
(
default_ms
)
self
.
_create_block_hierarchy
()
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
with
check_mongo_calls
(
mongo_store
,
max_find
,
max_send
):
with
check_mongo_calls
(
max_find
,
max_send
):
parent
=
self
.
store
.
get_parent_location
(
self
.
problem_x1a_1
)
self
.
assertEqual
(
parent
,
self
.
vertical_x1a
)
...
...
@@ -693,7 +703,21 @@ class TestMixedModuleStore(unittest.TestCase):
(
child_to_delete_location
,
None
,
ModuleStoreEnum
.
RevisionOption
.
published_only
),
])
@ddt.data
((
'draft'
,
[
10
,
3
],
0
),
(
'split'
,
[
14
,
6
],
0
))
# Mongo reads:
# First location:
# - count problem (1)
# - For each level of ancestors: (5)
# - Count ancestor
# - retrieve ancestor
# - compute inheritable data
# Second location:
# - load vertical
# - load inheritance data
# TODO: LMS-11220: Document why draft send count is 5
# TODO: LMS-11220: Document why draft find count is 18
# TODO: LMS-11220: Document why split find count is 16
@ddt.data
((
'draft'
,
[
18
,
5
],
0
),
(
'split'
,
[
16
,
6
],
0
))
@ddt.unpack
def
test_path_to_location
(
self
,
default_ms
,
num_finds
,
num_sends
):
"""
...
...
@@ -714,7 +738,7 @@ class TestMixedModuleStore(unittest.TestCase):
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
for
location
,
expected
in
should_work
:
with
check_mongo_calls
(
mongo_store
,
num_finds
.
pop
(
0
),
num_sends
):
with
check_mongo_calls
(
num_finds
.
pop
(
0
),
num_sends
):
self
.
assertEqual
(
path_to_location
(
self
.
store
,
location
),
expected
)
not_found
=
(
...
...
@@ -882,8 +906,7 @@ class TestMixedModuleStore(unittest.TestCase):
block_id
=
location
.
block_id
)
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
with
check_mongo_calls
(
mongo_store
,
max_find
,
max_send
):
with
check_mongo_calls
(
max_find
,
max_send
):
found_orphans
=
self
.
store
.
get_orphans
(
self
.
course_locations
[
self
.
MONGO_COURSEID
]
.
course_key
)
self
.
assertItemsEqual
(
found_orphans
,
orphan_locations
)
...
...
@@ -925,7 +948,9 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
assertEqual
(
self
.
user_id
,
block
.
subtree_edited_by
)
self
.
assertGreater
(
datetime
.
datetime
.
now
(
UTC
),
block
.
subtree_edited_on
)
@ddt.data
((
'draft'
,
1
,
0
),
(
'split'
,
1
,
0
))
# TODO: LMS-11220: Document why split find count is 2
# TODO: LMS-11220: Document why draft find count is 2
@ddt.data
((
'draft'
,
2
,
0
),
(
'split'
,
2
,
0
))
@ddt.unpack
def
test_get_courses_for_wiki
(
self
,
default_ms
,
max_find
,
max_send
):
"""
...
...
@@ -942,8 +967,7 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
assertIn
(
self
.
course_locations
[
self
.
XML_COURSEID2
]
.
course_key
,
wiki_courses
)
# Test Mongo wiki
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
with
check_mongo_calls
(
mongo_store
,
max_find
,
max_send
):
with
check_mongo_calls
(
max_find
,
max_send
):
wiki_courses
=
self
.
store
.
get_courses_for_wiki
(
'999'
)
self
.
assertEqual
(
len
(
wiki_courses
),
1
)
self
.
assertIn
(
...
...
@@ -954,9 +978,15 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
assertEqual
(
len
(
self
.
store
.
get_courses_for_wiki
(
'edX.simple.2012_Fall'
)),
0
)
self
.
assertEqual
(
len
(
self
.
store
.
get_courses_for_wiki
(
'no_such_wiki'
)),
0
)
# Mongo reads:
# - load vertical
# - load vertical children
# - get last error
# Split takes 1 query to read the course structure, deletes all of the entries in memory, and loads the module from an in-memory cache
# Only writes the course structure back to the database once
@ddt.data
((
'draft'
,
2
,
6
),
(
'split'
,
1
,
1
))
# Sends:
# - insert structure
# - write index entry
@ddt.data
((
'draft'
,
3
,
6
),
(
'split'
,
3
,
2
))
@ddt.unpack
def
test_unpublish
(
self
,
default_ms
,
max_find
,
max_send
):
"""
...
...
@@ -974,8 +1004,7 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
assertIsNotNone
(
published_xblock
)
# unpublish
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
with
check_mongo_calls
(
mongo_store
,
max_find
,
max_send
):
with
check_mongo_calls
(
max_find
,
max_send
):
self
.
store
.
unpublish
(
self
.
vertical_x1a
,
self
.
user_id
)
with
self
.
assertRaises
(
ItemNotFoundError
):
...
...
@@ -1003,8 +1032,7 @@ class TestMixedModuleStore(unittest.TestCase):
# start off as Private
item
=
self
.
store
.
create_child
(
self
.
user_id
,
self
.
writable_chapter_location
,
'problem'
,
'test_compute_publish_state'
)
item_location
=
item
.
location
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
with
check_mongo_calls
(
mongo_store
,
max_find
,
max_send
):
with
check_mongo_calls
(
max_find
,
max_send
):
self
.
assertFalse
(
self
.
store
.
has_published_version
(
item
))
# Private -> Public
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_publish.py
View file @
e7ce4106
...
...
@@ -19,23 +19,35 @@ class TestPublish(SplitWMongoCourseBoostrapper):
# There are 12 created items and 7 parent updates
# create course: finds: 1 to verify uniqueness, 1 to find parents
# sends: 1 to create course, 1 to create overview
with
check_mongo_calls
(
self
.
draft_mongo
,
5
,
2
):
with
check_mongo_calls
(
5
,
2
):
super
(
TestPublish
,
self
)
.
_create_course
(
split
=
False
)
# 2 inserts (course and overview)
# with bulk will delay all inheritance computations which won't be added into the mongo_calls
with
self
.
draft_mongo
.
bulk_write_operations
(
self
.
old_course_key
):
# finds: 1 for parent to add child
# sends: 1 for insert, 1 for parent (add child)
with
check_mongo_calls
(
self
.
draft_mongo
,
1
,
2
):
with
check_mongo_calls
(
1
,
2
):
self
.
_create_item
(
'chapter'
,
'Chapter1'
,
{},
{
'display_name'
:
'Chapter 1'
},
'course'
,
'runid'
,
split
=
False
)
with
check_mongo_calls
(
self
.
draft_mongo
,
2
,
2
):
with
check_mongo_calls
(
2
,
2
):
self
.
_create_item
(
'chapter'
,
'Chapter2'
,
{},
{
'display_name'
:
'Chapter 2'
},
'course'
,
'runid'
,
split
=
False
)
# update info propagation is 2 levels. create looks for draft and then published and then creates
with
check_mongo_calls
(
self
.
draft_mongo
,
8
,
6
):
# For each vertical (2) created:
# - load draft
# - load non-draft
# - get last error
# - load parent
# - load inheritable data
with
check_mongo_calls
(
10
,
6
):
self
.
_create_item
(
'vertical'
,
'Vert1'
,
{},
{
'display_name'
:
'Vertical 1'
},
'chapter'
,
'Chapter1'
,
split
=
False
)
self
.
_create_item
(
'vertical'
,
'Vert2'
,
{},
{
'display_name'
:
'Vertical 2'
},
'chapter'
,
'Chapter1'
,
split
=
False
)
with
check_mongo_calls
(
self
.
draft_mongo
,
20
,
12
):
# For each (4) item created
# - load draft
# - load non-draft
# - get last error
# - load parent
# - load inheritable data
# - load parent
with
check_mongo_calls
(
24
,
12
):
self
.
_create_item
(
'html'
,
'Html1'
,
"<p>Goodbye</p>"
,
{
'display_name'
:
'Parented Html'
},
'vertical'
,
'Vert1'
,
split
=
False
)
self
.
_create_item
(
'discussion'
,
'Discussion1'
,
...
...
@@ -63,7 +75,7 @@ class TestPublish(SplitWMongoCourseBoostrapper):
split
=
False
)
with
check_mongo_calls
(
self
.
draft_mongo
,
0
,
2
):
with
check_mongo_calls
(
0
,
2
):
# 2 finds b/c looking for non-existent parents
self
.
_create_item
(
'static_tab'
,
'staticuno'
,
"<p>tab</p>"
,
{
'display_name'
:
'Tab uno'
},
None
,
None
,
split
=
False
)
self
.
_create_item
(
'course_info'
,
'updates'
,
"<ol><li><h2>Sep 22</h2><p>test</p></li></ol>"
,
{},
None
,
None
,
split
=
False
)
...
...
@@ -76,10 +88,11 @@ class TestPublish(SplitWMongoCourseBoostrapper):
vert_location
=
self
.
old_course_key
.
make_usage_key
(
'vertical'
,
block_id
=
'Vert1'
)
item
=
self
.
draft_mongo
.
get_item
(
vert_location
,
2
)
# Vert1 has 3 children; so, publishes 4 nodes which may mean 4 inserts & 1 bulk remove
# TODO: LMS-11220: Document why find count is 25
# 25-June-2014 find calls are 19. Probably due to inheritance recomputation?
# 02-July-2014 send calls are 7. 5 from above, plus 2 for updating subtree edit info for Chapter1 and course
# find calls are 22. 19 from above, plus 3 for finding the parent of Vert1, Chapter1, and course
with
check_mongo_calls
(
self
.
draft_mongo
,
22
,
7
):
with
check_mongo_calls
(
25
,
7
):
self
.
draft_mongo
.
publish
(
item
.
location
,
self
.
user_id
)
# verify status
...
...
common/lib/xmodule/xmodule/modulestore/xml_importer.py
View file @
e7ce4106
...
...
@@ -607,7 +607,7 @@ def _import_course_draft(
_import_module
(
descriptor
)
except
Exception
:
logging
.
exception
(
'
There
while importing draft descriptor
%
s'
,
descriptor
)
logging
.
exception
(
'while importing draft descriptor
%
s'
,
descriptor
)
def
allowed_metadata_by_category
(
category
):
...
...
lms/djangoapps/courseware/tests/test_module_render.py
View file @
e7ce4106
...
...
@@ -326,7 +326,7 @@ class TestTOC(ModuleStoreTestCase):
self
.
request
=
factory
.
get
(
chapter_url
)
self
.
request
.
user
=
UserFactory
()
self
.
modulestore
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
course_key
)
with
check_mongo_calls
(
self
.
modulestore
,
num_finds
,
num_sends
):
with
check_mongo_calls
(
num_finds
,
num_sends
):
self
.
toy_course
=
self
.
store
.
get_course
(
self
.
toy_loc
,
depth
=
2
)
self
.
field_data_cache
=
FieldDataCache
.
cache_for_descriptor_descendents
(
self
.
toy_loc
,
self
.
request
.
user
,
self
.
toy_course
,
depth
=
2
)
...
...
@@ -352,7 +352,7 @@ class TestTOC(ModuleStoreTestCase):
'format'
:
''
,
'due'
:
None
,
'active'
:
False
}],
'url_name'
:
'secret:magic'
,
'display_name'
:
'secret:magic'
}])
with
check_mongo_calls
(
self
.
modulestore
,
0
,
0
):
with
check_mongo_calls
(
0
,
0
):
actual
=
render
.
toc_for_course
(
self
.
request
.
user
,
self
.
request
,
self
.
toy_course
,
self
.
chapter
,
None
,
self
.
field_data_cache
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment