From 3fc19a35b0c8718e3d25d76c458aa5343c924b7b Mon Sep 17 00:00:00 2001
From: Jay Zoldak <zoldak@edx.org>
Date: Thu, 10 Apr 2014 14:42:26 -0400
Subject: [PATCH] Serve video HTML5 sources locally for acceptance tests

---
 cms/envs/test.py                              |  1 +
 common/djangoapps/terrain/start_stubs.py      | 31 ++++++++++--
 common/djangoapps/terrain/stubs/start.py      |  2 +
 .../djangoapps/terrain/stubs/video_source.py  | 48 +++++++++++++++++++
 .../acceptance/tests/test_video_module.py     |  9 ++--
 lms/djangoapps/courseware/features/video.py   | 10 ++--
 lms/envs/test.py                              |  1 +
 rakelib/bok_choy.rake                         |  8 ++++
 test_root/data/video/gizmo.mp99               |  2 +
 9 files changed, 100 insertions(+), 12 deletions(-)
 create mode 100644 common/djangoapps/terrain/stubs/video_source.py
 create mode 100644 test_root/data/video/gizmo.mp99

diff --git a/cms/envs/test.py b/cms/envs/test.py
index 4171dc303f9..74b0525388d 100644
--- a/cms/envs/test.py
+++ b/cms/envs/test.py
@@ -175,6 +175,7 @@ LETTUCE_SERVER_PORT = 8003
 XQUEUE_PORT = 8040
 YOUTUBE_PORT = 8031
 LTI_PORT = 8765
+VIDEO_SOURCE_PORT = 8777
 
 
 ################### Make tests faster
diff --git a/common/djangoapps/terrain/start_stubs.py b/common/djangoapps/terrain/start_stubs.py
index b859e95df44..a4dd93ad4c0 100644
--- a/common/djangoapps/terrain/start_stubs.py
+++ b/common/djangoapps/terrain/start_stubs.py
@@ -1,5 +1,5 @@
 """
-Initialize and teardown fake HTTP services for use in acceptance tests.
+Initialize and teardown stub and video HTTP services for use in acceptance tests.
 """
 import requests
 from lettuce import before, after, world
@@ -7,6 +7,8 @@ from django.conf import settings
 from terrain.stubs.youtube import StubYouTubeService
 from terrain.stubs.xqueue import StubXQueueService
 from terrain.stubs.lti import StubLtiService
+from terrain.stubs.video_source import VideoSourceHttpService
+
 
 SERVICES = {
     "youtube": {"port": settings.YOUTUBE_PORT, "class": StubYouTubeService},
@@ -17,10 +19,33 @@ SERVICES = {
 YOUTUBE_API_RESPONSE = requests.get('http://www.youtube.com/iframe_api')
 
 
+@before.all  # pylint: disable=E1101
+def start_video_server():
+    """
+    Serve the HTML5 Video Sources from a local port
+    """
+    video_source_dir = '{}/data/video'.format(settings.TEST_ROOT)
+    video_server = VideoSourceHttpService(port_num=settings.VIDEO_SOURCE_PORT)
+    video_server.config['root_dir'] = video_source_dir
+    setattr(world, 'video_source', video_server)
+
+
+@after.all  # pylint: disable=E1101
+def stop_video_server(_total):
+    """
+    Stop the HTML5 Video Source server after all tests have executed
+    """
+    video_server = getattr(world, 'video_source', None)
+    if video_server:
+        video_server.shutdown()
+
+
 @before.each_scenario
-def start_stubs(_):
+def start_stubs(_scenario):
     """
     Start each stub service running on a local port.
+    Since these services can be reconfigured on the fly,
+    stop and restart them on a scenario basis.
     """
     for name, service in SERVICES.iteritems():
         fake_server = service['class'](port_num=service['port'])
@@ -30,7 +55,7 @@ def start_stubs(_):
 
 
 @after.each_scenario
-def stop_stubs(_):
+def stop_stubs(_scenario):
     """
     Shut down each stub service.
     """
diff --git a/common/djangoapps/terrain/stubs/start.py b/common/djangoapps/terrain/stubs/start.py
index f9fdf4a388e..0a60d425395 100644
--- a/common/djangoapps/terrain/stubs/start.py
+++ b/common/djangoapps/terrain/stubs/start.py
@@ -9,6 +9,7 @@ from .xqueue import StubXQueueService
 from .youtube import StubYouTubeService
 from .ora import StubOraService
 from .lti import StubLtiService
+from .video_source import VideoSourceHttpService
 
 
 USAGE = "USAGE: python -m stubs.start SERVICE_NAME PORT_NUM [CONFIG_KEY=CONFIG_VAL, ...]"
@@ -19,6 +20,7 @@ SERVICES = {
     'ora': StubOraService,
     'comments': StubCommentsService,
     'lti': StubLtiService,
+    'video': VideoSourceHttpService,
 }
 
 # Log to stdout, including debug messages
diff --git a/common/djangoapps/terrain/stubs/video_source.py b/common/djangoapps/terrain/stubs/video_source.py
new file mode 100644
index 00000000000..460b2f7560d
--- /dev/null
+++ b/common/djangoapps/terrain/stubs/video_source.py
@@ -0,0 +1,48 @@
+"""
+Serve HTML5 video sources for acceptance tests
+"""
+from SimpleHTTPServer import SimpleHTTPRequestHandler
+from .http import StubHttpService
+from contextlib import contextmanager
+import os
+
+from logging import getLogger
+LOGGER = getLogger(__name__)
+
+class VideoSourceRequestHandler(SimpleHTTPRequestHandler):
+    """
+    Request handler for serving video sources locally.
+    """
+    def translate_path(self, path):
+        """
+        Remove any extra parameters from the path.
+        For example /gizmo.mp4?1397160769634
+        becomes /gizmo.mp4
+        """
+        root_dir = self.server.config.get('root_dir')
+        path = '{}{}'.format(root_dir, path)
+        return path.split('?')[0]
+
+
+class VideoSourceHttpService(StubHttpService):
+    """
+    Simple HTTP server for serving HTML5 Video sources locally for tests
+    """
+    HANDLER_CLASS = VideoSourceRequestHandler
+
+    def __init__(self, port_num=0):
+
+        @contextmanager
+        def _remember_cwd():
+            """
+            Files are automatically served from the current directory
+            so we need to change it, start the server, then set it back.
+            """
+            curdir = os.getcwd()
+            try:
+                yield
+            finally:
+                os.chdir(curdir)
+
+        with _remember_cwd():
+            StubHttpService.__init__(self, port_num=port_num)
diff --git a/common/test/acceptance/tests/test_video_module.py b/common/test/acceptance/tests/test_video_module.py
index 4fe9f321a6e..b2e67f550d5 100644
--- a/common/test/acceptance/tests/test_video_module.py
+++ b/common/test/acceptance/tests/test_video_module.py
@@ -11,15 +11,16 @@ from ..pages.studio.auto_auth import AutoAuthPage
 from ..pages.lms.course_info import CourseInfoPage
 from ..fixtures.course import CourseFixture, XBlockFixtureDesc
 
+VIDEO_SOURCE_PORT = 8777
 
 HTML5_SOURCES = [
-    'https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.mp4',
-    'https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.webm',
-    'https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.ogv',
+    'http://localhost:{0}/gizmo.mp4'.format(VIDEO_SOURCE_PORT),
+    'http://localhost:{0}/gizmo.webm'.format(VIDEO_SOURCE_PORT),
+    'http://localhost:{0}/gizmo.ogv'.format(VIDEO_SOURCE_PORT),
 ]
 
 HTML5_SOURCES_INCORRECT = [
-    'https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.mp99',
+    'http://localhost:{0}/gizmo.mp99'.format(VIDEO_SOURCE_PORT),
 ]
 
 HTML5_METADATA = {
diff --git a/lms/djangoapps/courseware/features/video.py b/lms/djangoapps/courseware/features/video.py
index 0cc89514ccb..fb81325099a 100644
--- a/lms/djangoapps/courseware/features/video.py
+++ b/lms/djangoapps/courseware/features/video.py
@@ -16,14 +16,14 @@ from xmodule.contentstore.django import contentstore
 
 TEST_ROOT = settings.COMMON_TEST_DATA_ROOT
 LANGUAGES = settings.ALL_LANGUAGES
-
+VIDEO_SOURCE_PORT = settings.VIDEO_SOURCE_PORT
 
 ############### ACTIONS ####################
 
 HTML5_SOURCES = [
-    'https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.mp4',
-    'https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.webm',
-    'https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.ogv',
+    'http://localhost:{0}/gizmo.mp4'.format(VIDEO_SOURCE_PORT),
+    'http://localhost:{0}/gizmo.webm'.format(VIDEO_SOURCE_PORT),
+    'http://localhost:{0}/gizmo.ogv'.format(VIDEO_SOURCE_PORT),
 ]
 
 FLASH_SOURCES = {
@@ -34,7 +34,7 @@ FLASH_SOURCES = {
 }
 
 HTML5_SOURCES_INCORRECT = [
-    'https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.mp99',
+    'http://localhost:{0}/gizmo.mp99'.format(VIDEO_SOURCE_PORT),
 ]
 
 VIDEO_BUTTONS = {
diff --git a/lms/envs/test.py b/lms/envs/test.py
index 5b9e6a5f4af..52288774712 100644
--- a/lms/envs/test.py
+++ b/lms/envs/test.py
@@ -257,6 +257,7 @@ LETTUCE_SERVER_PORT = 8003
 XQUEUE_PORT = 8040
 YOUTUBE_PORT = 8031
 LTI_PORT = 8765
+VIDEO_SOURCE_PORT = 8777
 
 ################### Make tests faster
 
diff --git a/rakelib/bok_choy.rake b/rakelib/bok_choy.rake
index 679303ff6c0..06bf342693a 100644
--- a/rakelib/bok_choy.rake
+++ b/rakelib/bok_choy.rake
@@ -23,6 +23,8 @@ BOK_CHOY_XUNIT_REPORT = File.join(BOK_CHOY_REPORT_DIR, "xunit.xml")
 BOK_CHOY_COVERAGE_RC = File.join(BOK_CHOY_DIR, ".coveragerc")
 directory BOK_CHOY_REPORT_DIR
 
+# Directory that videos are served from
+VIDEO_SOURCE_DIR = File.join(REPO_ROOT, "test_root", "data", "video")
 
 BOK_CHOY_SERVERS = {
     :lms => { :port =>  8003, :log => File.join(BOK_CHOY_LOG_DIR, "bok_choy_lms.log") },
@@ -46,6 +48,12 @@ BOK_CHOY_STUBS = {
     :comments => {
         :port => 4567,
         :log => File.join(BOK_CHOY_LOG_DIR, "bok_choy_comments.log")
+    },
+
+    :video => {
+        :port => 8777,
+        :log => File.join(BOK_CHOY_LOG_DIR, "bok_choy_video_sources.log"),
+        :config => "root_dir=#{VIDEO_SOURCE_DIR}"
     }
 }
 
diff --git a/test_root/data/video/gizmo.mp99 b/test_root/data/video/gizmo.mp99
new file mode 100644
index 00000000000..df23f62c2fc
--- /dev/null
+++ b/test_root/data/video/gizmo.mp99
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>1205EB22685DC2E7</RequestId><HostId>/a61gfYpYdzvEXubtCRZCM8u3hsEBjRxcZ+aCP0VXVcL2oQmWo2bZ1aAocxXiZ+S</HostId></Error>
-- 
GitLab