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
OpenEdx
edx-platform
Commits
71805ed8
Commit
71805ed8
authored
Nov 17, 2016
by
Ben Patterson
Committed by
GitHub
Nov 17, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #13974 from edx/benp/cb-never-called-workaround
Workaround for TE-1767 aka cb() never called
parents
41f8d762
705c8b91
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
129 additions
and
39 deletions
+129
-39
pavelib/paver_tests/test_paver_quality.py
+9
-36
pavelib/paver_tests/test_prereqs.py
+57
-1
pavelib/paver_tests/utils.py
+49
-0
pavelib/prereqs.py
+14
-2
No files found.
pavelib/paver_tests/test_paver_quality.py
View file @
71805ed8
"""
"""
Tests for paver quality tasks
Tests for paver quality tasks
"""
"""
import
os
from
path
import
Path
as
path
import
tempfile
import
tempfile
import
textwrap
import
textwrap
import
unittest
import
unittest
from
mock
import
patch
,
MagicMock
,
mock_open
from
ddt
import
ddt
,
file_data
import
pavelib.quality
import
os
import
paver.easy
import
paver.easy
import
paver.tasks
import
paver.tasks
from
ddt
import
ddt
,
file_data
from
mock
import
patch
,
MagicMock
,
mock_open
from
path
import
Path
as
path
from
paver.easy
import
BuildFailure
from
paver.easy
import
BuildFailure
import
pavelib.quality
from
pavelib.paver_tests.utils
import
fail_on_pylint
,
fail_on_eslint
@ddt
@ddt
class
TestPaverQualityViolations
(
unittest
.
TestCase
):
class
TestPaverQualityViolations
(
unittest
.
TestCase
):
...
@@ -296,7 +298,7 @@ class TestPaverRunQuality(unittest.TestCase):
...
@@ -296,7 +298,7 @@ class TestPaverRunQuality(unittest.TestCase):
"""
"""
# Underlying sh call must fail when it is running the pylint diff-quality task
# Underlying sh call must fail when it is running the pylint diff-quality task
self
.
_mock_paver_sh
.
side_effect
=
CustomShMock
()
.
fail_on_pylint
self
.
_mock_paver_sh
.
side_effect
=
fail_on_pylint
_mock_pep8_violations
=
MagicMock
(
return_value
=
(
0
,
[]))
_mock_pep8_violations
=
MagicMock
(
return_value
=
(
0
,
[]))
with
patch
(
'pavelib.quality._get_pep8_violations'
,
_mock_pep8_violations
):
with
patch
(
'pavelib.quality._get_pep8_violations'
,
_mock_pep8_violations
):
with
self
.
assertRaises
(
SystemExit
):
with
self
.
assertRaises
(
SystemExit
):
...
@@ -316,7 +318,7 @@ class TestPaverRunQuality(unittest.TestCase):
...
@@ -316,7 +318,7 @@ class TestPaverRunQuality(unittest.TestCase):
"""
"""
# Underlying sh call must fail when it is running the eslint diff-quality task
# Underlying sh call must fail when it is running the eslint diff-quality task
self
.
_mock_paver_sh
.
side_effect
=
CustomShMock
()
.
fail_on_eslint
self
.
_mock_paver_sh
.
side_effect
=
fail_on_eslint
_mock_pep8_violations
=
MagicMock
(
return_value
=
(
0
,
[]))
_mock_pep8_violations
=
MagicMock
(
return_value
=
(
0
,
[]))
with
patch
(
'pavelib.quality._get_pep8_violations'
,
_mock_pep8_violations
):
with
patch
(
'pavelib.quality._get_pep8_violations'
,
_mock_pep8_violations
):
with
self
.
assertRaises
(
SystemExit
):
with
self
.
assertRaises
(
SystemExit
):
...
@@ -351,32 +353,3 @@ class TestPaverRunQuality(unittest.TestCase):
...
@@ -351,32 +353,3 @@ class TestPaverRunQuality(unittest.TestCase):
self
.
assertEqual
(
_mock_pep8_violations
.
call_count
,
1
)
self
.
assertEqual
(
_mock_pep8_violations
.
call_count
,
1
)
# And assert that sh was called twice (for the call to "pylint" & "eslint")
# And assert that sh was called twice (for the call to "pylint" & "eslint")
self
.
assertEqual
(
self
.
_mock_paver_sh
.
call_count
,
2
)
self
.
assertEqual
(
self
.
_mock_paver_sh
.
call_count
,
2
)
class
CustomShMock
(
object
):
"""
Diff-quality makes a number of sh calls. None of those calls should be made during tests; however, some
of them need to have certain responses.
"""
def
fail_on_pylint
(
self
,
arg
):
"""
For our tests, we need the call for diff-quality running pep8 reports to fail, since that is what
is going to fail when we pass in a percentage ("p") requirement.
"""
if
"pylint"
in
arg
:
# Essentially mock diff-quality exiting with 1
paver
.
easy
.
sh
(
"exit 1"
)
else
:
return
def
fail_on_eslint
(
self
,
arg
):
"""
For our tests, we need the call for diff-quality running pep8 reports to fail, since that is what
is going to fail when we pass in a percentage ("p") requirement.
"""
if
"eslint"
in
arg
:
# Essentially mock diff-quality exiting with 1
paver
.
easy
.
sh
(
"exit 1"
)
else
:
return
pavelib/paver_tests/test_prereqs.py
View file @
71805ed8
...
@@ -4,7 +4,12 @@ Tests covering the Open edX Paver prequisites installation workflow
...
@@ -4,7 +4,12 @@ Tests covering the Open edX Paver prequisites installation workflow
import
os
import
os
import
unittest
import
unittest
from
pavelib.prereqs
import
no_prereq_install
from
mock
import
call
,
patch
from
paver.easy
import
BuildFailure
from
pavelib.prereqs
import
no_prereq_install
,
node_prereqs_installation
from
pavelib.paver_tests.utils
import
(
PaverTestCase
,
unexpected_fail_on_npm_install
,
fail_on_npm_install
)
class
TestPaverPrereqInstall
(
unittest
.
TestCase
):
class
TestPaverPrereqInstall
(
unittest
.
TestCase
):
...
@@ -68,3 +73,54 @@ class TestPaverPrereqInstall(unittest.TestCase):
...
@@ -68,3 +73,54 @@ class TestPaverPrereqInstall(unittest.TestCase):
Ensure that '1' will be True.
Ensure that '1' will be True.
"""
"""
self
.
check_val
(
'1'
,
True
)
self
.
check_val
(
'1'
,
True
)
class
TestPaverNodeInstall
(
PaverTestCase
):
"""
Test node install logic
"""
def
setUp
(
self
):
super
(
TestPaverNodeInstall
,
self
)
.
setUp
()
# Ensure prereqs will be run
os
.
environ
[
'NO_PREREQ_INSTALL'
]
=
'false'
patcher
=
patch
(
'pavelib.prereqs.sh'
,
return_value
=
True
)
self
.
_mock_paver_sh
=
patcher
.
start
()
self
.
addCleanup
(
patcher
.
stop
)
def
test_npm_install_with_subprocess_error
(
self
):
"""
An exit with subprocess exit 1 is what paver receives when there is
an npm install error ("cb() never called!"). Test that we can handle
this kind of failure. For more info see TE-1767.
"""
self
.
_mock_paver_sh
.
side_effect
=
fail_on_npm_install
with
self
.
assertRaises
(
BuildFailure
):
node_prereqs_installation
()
actual_calls
=
self
.
_mock_paver_sh
.
mock_calls
# npm install will be called twice
self
.
assertEqual
(
actual_calls
.
count
(
call
(
'npm install'
)),
2
)
def
test_npm_install_called_once_when_successful
(
self
):
"""
Vanilla npm install should only be calling npm install one time
"""
node_prereqs_installation
()
actual_calls
=
self
.
_mock_paver_sh
.
mock_calls
# when there's no failure, npm install is only called once
self
.
assertEqual
(
actual_calls
.
count
(
call
(
'npm install'
)),
1
)
def
test_npm_install_with_unexpected_subprocess_error
(
self
):
"""
If there's some other error, only call npm install once, and raise a failure
"""
self
.
_mock_paver_sh
.
side_effect
=
unexpected_fail_on_npm_install
with
self
.
assertRaises
(
BuildFailure
):
node_prereqs_installation
()
actual_calls
=
self
.
_mock_paver_sh
.
mock_calls
self
.
assertEqual
(
actual_calls
.
count
(
call
(
'npm install'
)),
1
)
pavelib/paver_tests/utils.py
View file @
71805ed8
"""Unit tests for the Paver server tasks."""
"""Unit tests for the Paver server tasks."""
import
os
import
os
import
paver.easy
from
paver
import
tasks
from
paver
import
tasks
from
unittest
import
TestCase
from
unittest
import
TestCase
from
paver.easy
import
BuildFailure
class
PaverTestCase
(
TestCase
):
class
PaverTestCase
(
TestCase
):
"""
"""
...
@@ -58,3 +61,49 @@ class MockEnvironment(tasks.Environment):
...
@@ -58,3 +61,49 @@ class MockEnvironment(tasks.Environment):
output
=
message
output
=
message
if
not
output
.
startswith
(
"--->"
):
if
not
output
.
startswith
(
"--->"
):
self
.
messages
.
append
(
unicode
(
output
))
self
.
messages
.
append
(
unicode
(
output
))
def
fail_on_eslint
(
arg
):
"""
For our tests, we need the call for diff-quality running pep8 reports to fail, since that is what
is going to fail when we pass in a percentage ("p") requirement.
"""
if
"eslint"
in
arg
:
# Essentially mock diff-quality exiting with 1
paver
.
easy
.
sh
(
"exit 1"
)
else
:
return
def
fail_on_pylint
(
arg
):
"""
For our tests, we need the call for diff-quality running pep8 reports to fail, since that is what
is going to fail when we pass in a percentage ("p") requirement.
"""
if
"pylint"
in
arg
:
# Essentially mock diff-quality exiting with 1
paver
.
easy
.
sh
(
"exit 1"
)
else
:
return
def
fail_on_npm_install
(
arg
):
"""
For our tests, we need the call for diff-quality running pep8 reports to fail, since that is what
is going to fail when we pass in a percentage ("p") requirement.
"""
if
"npm install"
in
arg
:
raise
BuildFailure
(
'Subprocess return code: 1'
)
else
:
return
def
unexpected_fail_on_npm_install
(
arg
):
"""
For our tests, we need the call for diff-quality running pep8 reports to fail, since that is what
is going to fail when we pass in a percentage ("p") requirement.
"""
if
"npm install"
in
arg
:
raise
BuildFailure
(
'Subprocess return code: 50'
)
else
:
return
pavelib/prereqs.py
View file @
71805ed8
...
@@ -8,7 +8,7 @@ import os
...
@@ -8,7 +8,7 @@ import os
import
re
import
re
import
sys
import
sys
from
paver.easy
import
sh
,
task
from
paver.easy
import
sh
,
task
,
BuildFailure
from
.utils.envs
import
Env
from
.utils.envs
import
Env
from
.utils.timer
import
timed
from
.utils.timer
import
timed
...
@@ -132,10 +132,22 @@ def node_prereqs_installation():
...
@@ -132,10 +132,22 @@ def node_prereqs_installation():
"""
"""
Configures npm and installs Node prerequisites
Configures npm and installs Node prerequisites
"""
"""
cb_error_text
=
"Subprocess return code: 1"
sh
(
"test `npm config get registry` =
\"
{reg}
\"
|| "
sh
(
"test `npm config get registry` =
\"
{reg}
\"
|| "
"(echo setting registry; npm config set registry"
"(echo setting registry; npm config set registry"
" {reg})"
.
format
(
reg
=
NPM_REGISTRY
))
" {reg})"
.
format
(
reg
=
NPM_REGISTRY
))
sh
(
'npm install'
)
# Error handling around a race condition that produces "cb() never called" error. This
# evinces itself as `cb_error_text` and it ought to disappear when we upgrade
# npm to 3 or higher. TODO: clean this up when we do that.
try
:
sh
(
'npm install'
)
except
BuildFailure
,
error_text
:
if
cb_error_text
in
error_text
:
print
"npm install error detected. Retrying..."
sh
(
'npm install'
)
else
:
raise
BuildFailure
(
error_text
)
def
python_prereqs_installation
():
def
python_prereqs_installation
():
...
...
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