# Copyright 2009, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


import os
import sys

Import('env')

env['COMPONENT_TEST_SUBSYSTEM_WINDOWS'] = True

if env.Bit('windows'):
  # gmock on MSVC currently has 3 issues:
  # - it needs <tuple>, that MSVC doesn't have. We could use boost for that
  # - the 1.0.0 version triggers a bug in MSVC where function-local template
  #   types cause duplicate symbols. It may be fixed in a more recent release.
  # - on MSVC, it triggers a bug where it gets confused between chrome's and
  #   gmock's version of down_cast.
  use_gmock = False
else:
  use_gmock = True

gtest_env = env.Clone()
gtest_env.Append(
    CPPPATH = ['$GTEST_DIR/include',
               '$GTEST_DIR',
               ]
)
gtest_sources = [
    'gtest-all',
]
gtest_objs = [gtest_env.ComponentObject(name, '$GTEST_DIR/src/%s.cc' % name)
              for name in gtest_sources]

if use_gmock:
  gmock_env = gtest_env.Clone()
  gmock_env.Append(CPPPATH = ['$GMOCK_DIR/include',
                              '$GMOCK_DIR'])
  gmock_sources = ['gmock-all']
  gtest_objs += [gmock_env.ComponentObject(name, '$GMOCK_DIR/src/%s.cc' % name)
                for name in gmock_sources]
gtest_lib = gtest_env.Library('gtest', gtest_objs)

env.Append(
    CPPDEFINES = [
        '_USE_MATH_DEFINES',
    ],
    CPPPATH = [
        env.Dir('$COLLADA_DIR'),
        env.Dir('$COLLADA_DIR/LibXML/include'),
        env.Dir('$CG_DIR/include'),
        # Headers for Antlr runtime library
        env.Dir('$ANTLRLIBC_DIR/include'),
        # Headers generated by Antlr for Technique grammar
        env.Dir('$OBJ_ROOT/compiler/technique'),
        '$GTEST_DIR/include',
        '$GMOCK_DIR/include',
    ],
    LIBPATH=[
        env.Dir('.'),
        env.Dir('$NACL_LIB_DIR'),
        env.Dir('$OBJ_ROOT/compiler/technique'),  # For technique library
        env.Dir('$OBJ_ROOT/compiler/antlr'),      # For antlr3c library
    ],
)
# TODO: rearrange coverage so this can be an append.

# NOTE: Do not rearrange or sort these -- order is
# (apparently) important here on Linux.
env.Prepend(
    LIBS = [
        'testing_common',
        'o3dImportNoConditioner',
        'o3dCore',
        'o3dImport',
        'o3dArchive',
        'o3dCorePlatform',
        'o3dSerializer',
        'o3dUtils',
        'o3d_base',
        'FColladaU',
        'google_nacl_imc',
        'technique',
        'antlr3c',
        'gtest',
        'skia'
    ] + env['ICU_LIBS'],
)

# Next, append renderer specific libraries to the linker environment
env.Append(
    CPPPATH = env['RENDERER_INCLUDE_PATH'],
    LIBPATH = [
        '$CG_DIR/lib',
    ] + env['RENDERER_LIB_PATH'],
    LIBS = env['RENDERER_LIBS'],
)

run_env = env.Clone()
if env.Bit('linux'):
    run_env.Append(ENV = os.environ)
    run_env.Append(
        ENV = {'LD_LIBRARY_PATH': run_env.Dir('$ARTIFACTS_DIR').abspath}
    )

run_env.Append(
    ENV = {'MOZ_PLUGIN_PATH': run_env.Dir('$ARTIFACTS_DIR').abspath,
           'MOZ_CRASHREPORTER_DISABLE': '1'},
    PYTHONPATH = ['$GFLAGS_DIR/python',
                  '$SELENIUM_PYTHON_DIR']
)

# Install runtime files required for the build type.
gl_requirements = []
if env.Bit('windows'):
  # The install step for these lives in import/build.scons.  the
  # import library always needs the Cg DLLs and executable, even on
  # D3D.
  gl_requirements += [
      '$ARTIFACTS_DIR/cg.dll',
      '$ARTIFACTS_DIR/cgGL.dll',
      '$ARTIFACTS_DIR/glew32.dll',
  ]

# TODO: shouldn't need this.
# Adding extra line for cleaner formatting.
env.Help('\n')

swiftshader_install = []
if env.Bit('windows'):
  # Copy SwiftShader to plugin dir.
  swiftshader_path = env.subst('$SWIFTSHADER_DIR/swiftshader_d3d9.dll')
  if os.path.exists(swiftshader_path):
    swiftshader_install = env.Replicate('$ARTIFACTS_DIR/O3DExtras',
                                        swiftshader_path)

# -------------------------------------------------------------------------
# Unit tests

# The basic unit tests
tests = [
    'base/cross/bits_test.cc',
    'compiler/technique/technique_parser_test.cc',
    'core/cross/bitmap_test.cc',
    'core/cross/bounding_box_test.cc',
    'core/cross/buffer_test.cc',
    'core/cross/class_manager_test.cc',
    'core/cross/client_test.cc',
    'core/cross/counter_test.cc',
    'core/cross/curve_test.cc',
    'core/cross/draw_element_test.cc',
    'core/cross/draw_list_test.cc',
    'core/cross/draw_pass_test.cc',
    'core/cross/effect_test.cc',
    'core/cross/element_test.cc',
    'core/cross/fake_vertex_source.cc',
    'core/cross/features_test.cc',
    'core/cross/field_test.cc',
    'core/cross/float_n_test.cc',
    'core/cross/function_test.cc',
    'core/cross/material_test.cc',
    'core/cross/math_utilities_test.cc',
    'core/cross/matrix4_axis_rotation_test.cc',
    'core/cross/matrix4_composition_test.cc',
    'core/cross/matrix4_scale_test.cc',
    'core/cross/matrix4_translation_test.cc',
# Test disabled, pending investigation into NaCl API.
#   'core/cross/message_queue_test.cc',
    'core/cross/object_base_test.cc',
    'core/cross/pack_test.cc',
    'core/cross/param_array_test.cc',
    'core/cross/param_object_test.cc',
    'core/cross/param_operation_test.cc',
    'core/cross/param_test.cc',
    'core/cross/performance_timer_test.cc',
    'core/cross/primitive_test.cc',
    'core/cross/ray_intersection_info_test.cc',
    'core/cross/render_node_test.cc',
    'core/cross/renderer_test.cc',
    'core/cross/service_locator_test.cc',
    'core/cross/shape_test.cc',
    'core/cross/skin_test.cc',
    'core/cross/smart_ptr_test.cc',
    'core/cross/state_set_test.cc',
    'core/cross/state_test.cc',
    'core/cross/stream_bank_test.cc',
    'core/cross/stream_test.cc',
    'core/cross/transform_test.cc',
    'core/cross/tree_traversal_test.cc',
    'core/cross/vector_map_test.cc',
    'core/cross/vertex_source_test.cc',
    'core/cross/visitor_base_test.cc',
    'core/cross/weak_ptr_test.cc',
    'import/cross/gz_compressor_test.cc',
    'import/cross/gz_decompressor_test.cc',
    'import/cross/memory_buffer_test.cc',
    'import/cross/memory_stream_test.cc',
    'import/cross/raw_data_test.cc',
    'import/cross/tar_generator_test.cc',
    'import/cross/tar_processor_test.cc',
    'import/cross/targz_generator_test.cc',
    'import/cross/targz_processor_test.cc',
    'serializer/cross/serializer_test.cc',
    'tests/common/cross/test_utils.cc',
    'utils/cross/file_path_utils_test.cc',
    'utils/cross/file_text_reader_test.cc',
    'utils/cross/json_writer_test.cc',
    'utils/cross/string_reader_test.cc',
    'utils/cross/string_writer_test.cc',
    'utils/cross/temporary_file_test.cc',
]

if env['TARGET_PLATFORM']=='WINDOWS':
  tests += [
    # These are temporarily just being run for windows but should be
    # moved to global when logging is working for the mac.
    'plugin/cross/plugin_logging_test.cc',
    'statsreport/aggregator-win32_unittest.cc',
    'statsreport/aggregator_unittest.cc',
    'statsreport/formatter_unittest.cc',
    'statsreport/metrics_unittest.cc',
    'statsreport/persistent_iterator-win32_unittest.cc',
    'breakpad/win/bluescreen_detector_test.cc',
  ]
  env.Append(
    LINKFLAGS=['/SUBSYSTEM:WINDOWS'],
    LIBS=[
      'o3dStatsreport_Common',
      'o3dStatsreport',
      'o3dPlugin_logging',
      'o3dBreakpad',
      'shlwapi',
    ]
  )

# add command buffer renderer unit tests only on that renderer platform.
if 'RENDERER_CB' in env['CPPDEFINES']:
  tests += [
      'command_buffer/client/cross/id_allocator_test.cc',
      'command_buffer/common/cross/bitfield_helpers_test.cc',
      'command_buffer/service/cross/effect_utils_test.cc',
      'command_buffer/service/cross/resource_test.cc',
  ]
  if use_gmock:
    tests += [
        'command_buffer/client/cross/cmd_buffer_helper_test.cc',
        'command_buffer/client/cross/fenced_allocator_test.cc',
        'command_buffer/client/cross/buffer_sync_proxy_test.cc',
        'command_buffer/service/cross/buffer_rpc_test.cc',
        'command_buffer/service/cross/cmd_buffer_engine_test.cc',
        'command_buffer/service/cross/cmd_parser_test.cc',
    ]

unit_tests  = env.Program('unit_tests', tests)

# After building the test executable, force the windows executable to output
# stdout to a console window
# TODO: if WinMain/main is handled differently this isn't needed.
if env['TARGET_PLATFORM'] == 'WINDOWS':
  blessed = env.AddPostAction(unit_tests, 'editbin /SUBSYSTEM:CONSOLE $TARGET')
else:
  blessed = unit_tests

# Install to artifacts.
unit_tests_install = env.Replicate('$ARTIFACTS_DIR', blessed)

# Install any data required by the basic unit-tests
unit_tests_req = []

env['TEST_DATA_DIR'] = '$SCONSTRUCT_DIR/import/test_data'
unit_tests_req += env.Replicate(
    '$ARTIFACTS_DIR/unittest_data',
    [
     '$TEST_DATA_DIR/crate.dae',
     '$TEST_DATA_DIR/crate.jpg',
     '$TEST_DATA_DIR/rock01.tga',
     '$TEST_DATA_DIR/rock02.tga',
    ])

env['TECHNIQUE_TEST_DATA_DIR'] = '$SCONSTRUCT_DIR/compiler/technique/test_data'
unit_tests_req += env.Replicate(
    '$ARTIFACTS_DIR/unittest_data',
    [
     '$TECHNIQUE_TEST_DATA_DIR/fur.fx',
     '$TECHNIQUE_TEST_DATA_DIR/lambert.fx',
     '$TECHNIQUE_TEST_DATA_DIR/noshader.fx',
     '$TECHNIQUE_TEST_DATA_DIR/notechnique.fx',
     '$TECHNIQUE_TEST_DATA_DIR/sampler_test.fx',
     '$TECHNIQUE_TEST_DATA_DIR/shadow_map.fx',
     '$TECHNIQUE_TEST_DATA_DIR/simple.fx',
    ])

unit_tests_req += env.Replicate(
    '$ARTIFACTS_DIR/bitmap_test',
    '$SCONSTRUCT_DIR/tests/bitmap_test/*')

unit_tests_req += env.Replicate(
    '$ARTIFACTS_DIR/archive_files',
    '$SCONSTRUCT_DIR/tests/archive_files/*')

# Also require gl related libraries based on variant.
unit_tests_req += gl_requirements
unit_tests_req += swiftshader_install

# Add requirements for unit tests.
env.Requires(unit_tests_install, unit_tests_req)

# TODO: temporarily continue to use aliases to run tests.
#   This need to eventually switch to use ComponentTestProgram once
#   other sections have been adjusted.
env['PROGRAM_NAME'] = unit_tests_install[0].path
env['PROGRAM_BASENAME'] = os.path.join('$ARTIFACTS_DIR', 'unit_tests')
env.AlwaysBuild(run_env.Alias('unit_tests', unit_tests_install,
                env.subst('$COMPONENT_TEST_CMDLINE')))

# Add help.
env.Help('unit_tests: run unit tests\n')

if env.Bit('mac'):
  env['SHLINKFLAGS'] = ['-F$CG_DIR']
  env['SHLIBPREFIX'] = ['']
  env['SHLIBSUFFIX'] = ['']

  env.Append(
    FRAMEWORKS = [
      'AGL',
      'Accelerate',
      'AudioToolbox',
      'AudioUnit',
      'Carbon',
      'Cg',
      'CoreAudio',
      'Foundation',
      'GLUT',
      'OpenAL',
      'OpenGL',
     ],
     CCFLAGS = ['-F$CG_DIR'],
     LINKFLAGS = ['-F$CG_DIR'],
     SHLINKFLAGS = ['-F$CG_DIR']
  )

  env.AddPostAction(
    unit_tests_install,
    [
      # Change install name reference
      # make Cg.framework point to copy in $THIRD_PARTY
      '/usr/bin/install_name_tool '
        '-change @executable_path/../Library/Frameworks/Cg.framework/Cg '
        '"$CG_DIR/Cg.framework/Cg" '
        '"$ARTIFACTS_DIR/unit_tests"'
    ])


#----------------------------------------------------------------------------
# Install the perceptual diff tool and its requirements.

installed_pdiff = None
pdiff = None
pdiff_requirements = []
if env.Bit('windows'):
  # Install the perceptual-diff utility for lossy image comparisons
  pdiff = '$PDIFF_DIR/bin/win/perceptualdiff.exe'
  # perceptualdiff.exe also needs FreeImage.dll to run
  pdiff_requirements = env.Replicate('$ARTIFACTS_DIR',
                                     '$PDIFF_DIR/bin/win/FreeImage.dll')
elif env.Bit("linux"):
  pdiff = '$PDIFF_DIR/bin/linux/perceptualdiff'
elif env.Bit("mac"):
  pdiff = '$PDIFF_DIR/bin/mac/perceptualdiff'

if pdiff:
  installed_pdiff = env.Replicate('$ARTIFACTS_DIR', pdiff)
  run_env["PDIFF_PATH"] = installed_pdiff[0]
  env.Requires(installed_pdiff, pdiff_requirements)

# -------------------------------------------------------------------------
# System tests

# Only define and run the system tests if they are enabled.
if ARGUMENTS.get('SYSTEM_TESTS_ENABLED', False):
  # Build the system tests
  system_testprog = env.Program('system_tests',
                                'basic_system_test/basic_system_test.cc')

  # After building the test executable, force the windows executable to output
  # stdout to a console window
  if env.Bit('windows'):
    blessed = env.AddPostAction(system_testprog,
                                'editbin /SUBSYSTEM:CONSOLE $TARGET')
  else:
    blessed = system_testprog
  system_tests_install = env.Replicate('$ARTIFACTS_DIR', blessed)

  # Gather requirements for system tests.
  system_tests_req = []

  # TODO : The system tests are currently limited to Direct3D.
  if env.Bit('windows') and 'RENDERER_D3D9' in env['CPPDEFINES']:
    system_tests_req += env.Replicate(
       '$ARTIFACTS_DIR',
       ['test_driver.bat', 'test_driver.py'])

  # Install the assets required for the basic system test.
  system_tests_req += env.Replicate(
      '$ARTIFACTS_DIR/basic_system_test/reference_frames',
      'basic_system_test/reference_frames/*')
  system_tests_req += env.Replicate(
      '$ARTIFACTS_DIR/basic_system_test',
      'basic_system_test/reference_stream.csv')

  # Copy the PIX utility and experiment file to the testing build directory.
  if env.Bit('windows') and 'RENDERER_D3D9' in env['CPPDEFINES']:
    # Replicate a script which will package all of the files required,
    # for D3D9-tests.
    pix_requirements = env.Replicate(
       '$ARTIFACTS_DIR',
       [
        '$DIRECTX9_DIR/utilities/bin/x86/PIXWin.exe',
        '$DIRECTX9_DIR/utilities/bin/x86/PIXHelper.dll',
        '$DIRECTX9_DIR/utilities/bin/x86/PIXAdmin.exe',
        '$DIRECTX9_DIR/utilities/bin/x86/Detoured.dll',
        '$DIRECTX9_DIR/runtime/x86/d3dref9.dll',
        'testing_framework_reference.PIXExp',
        'testing_framework_hardware.PIXExp',
        'package_tests.bat',
       ])
    system_tests_req += pix_requirements

  if installed_pdiff:
    system_tests_req += installed_pdiff

  # Also require gl related libraries based on variant.
  system_tests_req += gl_requirements
  
  # Require SwiftShader (only if it is available).
  system_tests_req += swiftshader_install
  
  # Add requirements for system_tests.
  env.Requires(system_tests_install, system_tests_req)

  # Get command line flags for tests driver.
  if int(ARGUMENTS.get('hardware', 1)):
    env.Replace(TEST_DRIVER_FLAGS = '-hardware')

  # Create an alias for the execution of the system tests.
  env.Alias('system_tests')
  # Only add actual step if d3d mode (for now).
  if 'RENDERER_D3D9' in env['CPPDEFINES']:
    if env.get('COVERAGE_ENABLED'):
      # TODO: temporarily continue to use aliases to run tests.
      #   This need to eventually switch to use ComponentTestProgram once
      #   other sections have been adjusted.
      # When running coverage, don't run system_tests thru test_driver.py
      env['PROGRAM_NAME'] = system_tests_install[0].path
      env['PROGRAM_BASENAME'] = os.path.join('$ARTIFACTS_DIR', 'system_tests')
      env.AlwaysBuild(run_env.Alias(
          'system_tests', system_tests_install,
          env.subst('$COMPONENT_TEST_CMDLINE')))
    else:
      env.AlwaysBuild(run_env.Alias(
          'system_tests', system_tests_install,
          'cd $ARTIFACTS_DIR && ' + \
          sys.executable + ' $ARTIFACTS_DIR/test_driver.py $TEST_DRIVER_FLAGS'))
    # Add help.
    env.Help('system_tests: run system tests\n')


#----------------------------------------------------------------------------
# Selenium Tests

run_env.Replace(
    SELENIUM_VERBOSE = ARGUMENTS.get('SELENIUM_VERBOSE', '0'),
    SELENIUM_SERVER_JAR = '$SELENIUM_JAVA_DIR/server/selenium-server.jar',
    SELENIUM_TEST_PREFIX = ARGUMENTS.get('SELENIUM_TEST_PREFIX', 'Test'),
    SELENIUM_TEST_SUFFIXES = ARGUMENTS.get('SELENIUM_TEST_SUFFIXES',
                                           'small,medium,large'),
    SELENIUM_CAPTURE_SCREENSHOTS = ARGUMENTS.get(
        'SELENIUM_CAPTURE_SCREENSHOTS',
        ''),
    SELENIUM_FLAGS = ('--verbose=$SELENIUM_VERBOSE '
                      '--selenium_server="$SELENIUM_SERVER_JAR" '
                      '--testprefix=$SELENIUM_TEST_PREFIX '
                      '--testsuffixes=$SELENIUM_TEST_SUFFIXES '
                      '--screencompare=$PDIFF_PATH '
                      '$SELENIUM_CAPTURE_SCREENSHOTS '
                      '$SELENIUM_EXTRA_FLAGS'),
)

if run_env.Bit('windows'):
  from SCons.Platform.win32 import get_program_files_dir
  path_contents = '%s/Mozilla Firefox;%s' % (
      get_program_files_dir(),
      run_env.Dir('$ARTIFACTS_DIR').abspath)
  run_env.Append(
      ENV = {'PATH': '%s/Mozilla Firefox;%s' % (
          get_program_files_dir(),
          run_env.Dir('$ARTIFACTS_DIR').abspath)},
  )
  run_env.Append(
      ENV = {'USERPROFILE': os.environ['USERPROFILE']}
  )

# The Macintosh Firefox apparently does not support the MOZ_PLUGIN_PATH.
# On the Mac we can run a hermetic version of Firefox and allow it to find
# the O3D plugin by adding a symlink to it inside the plugins directory
# inside the Firefox.app bundle.  We then instruct selenium to run this
# specific version of Firefox.  All of this avoids having to install
# the plugin in a system directory which could be bad on
# auto-build machines, etc.
plugin_path = '$ARTIFACTS_DIR/${LIBPREFIX}npo3dautoplugin$SHLIBSUFFIX'
browser_path = ''
plugin_install_steps = []
cleanup_steps = []
selenium_good_to_go = True

if run_env.Bit('mac'):
  plugin_path = '$ARTIFACTS_DIR/O3D.plugin'
  
  if run_env['MAC_HERMETIC_FIREFOX_DIR']:
    # if we have a hermetic version of Firefox, then run it
    if os.path.exists(run_env.subst('$MAC_HERMETIC_FIREFOX_DIR')):
      run_env['MAC_FIREFOX_DIR'] = '$MAC_HERMETIC_FIREFOX_DIR'
      run_env['MAC_FIREFOX_APP'] = '$MAC_FIREFOX_DIR/Firefox.app'
      run_env['MAC_FIREFOX_TGZ'] = '$MAC_FIREFOX_DIR/firefox.tgz'
      browser_path = '$MAC_FIREFOX_APP/Contents/MacOS/firefox-bin'
      plugin_install_steps = [
          'rm -rf "$MAC_FIREFOX_APP"',
          'cd $MAC_FIREFOX_DIR && tar xfz "$MAC_FIREFOX_TGZ"',
          'ln -fs "' + plugin_path + '" "$MAC_FIREFOX_APP/Contents/MacOS/plugins"',
      ]
      cleanup_steps = [
          'rm -rf "$MAC_FIREFOX_APP"',
      ]
    else:
      # No hermetic version, look for Firefox.app in /Applications
      run_env['MAC_FIREFOX_ORIG_DIR'] = '/Applications'
      run_env['MAC_FIREFOX_ORIG_APP'] = '$MAC_FIREFOX_ORIG_DIR/Firefox.app'

      if not os.path.exists(run_env.subst('$MAC_FIREFOX_ORIG_APP')):
        selenium_good_to_go = False
      else:
        run_env['MAC_FIREFOX_DIR'] = '$TARGET_ROOT/firefox_selenium'
        run_env['MAC_FIREFOX_APP'] = '$MAC_FIREFOX_DIR/Firefox.app'
        browser_path = '$MAC_FIREFOX_APP/Contents/MacOS/firefox-bin'
        plugin_install_steps = [
            # copy user's version of Firefox into $MAC_FIREFOX_DIR
            'rm -rf "$MAC_FIREFOX_DIR"',
            'mkdir "$MAC_FIREFOX_DIR"',
            'ditto "$MAC_FIREFOX_ORIG_APP" "$MAC_FIREFOX_APP"',
            'ln -fs "' + plugin_path + '" "$MAC_FIREFOX_APP/Contents/MacOS/plugins"',
        ]
        cleanup_steps = [
            'rm -rf "$MAC_FIREFOX_DIR"',
        ]
      

def DeferSelenium(env):
  if not selenium_good_to_go:
    run_selenium_firefox = run_env.Alias(
        'selenium_firefox', [],
        'echo "******* Firefox.app MUST be installed in /Applications!!!"'
    )
  else:
    run_selenium_firefox = run_env.Alias(
        'selenium_firefox',
        [plugin_path, env.GetPublished('samples', 'asset_files')],
        # TODO: have a cleaner way to do this.
        [Delete('$ARTIFACTS_DIR/selenium/screenshots_firefox'),
         Mkdir('$ARTIFACTS_DIR/selenium/screenshots_firefox')] +
         plugin_install_steps +
         [run_env.Python([
            'tests/selenium/main.py',
            '$SELENIUM_FLAGS',
            '--browser=*firefox',
            '--browserpath="' + browser_path + '"',
            '--referencedir=$TEST_REFERENCE_IMAGES',
            '--screenshotsdir=$ARTIFACTS_DIR/selenium/screenshots_firefox'])] +
        cleanup_steps,
    )
  
  # Require SwiftShader (only if it is available).
  run_env.Requires(run_selenium_firefox, swiftshader_install)

  if run_env.Bit('windows'):
    run_selenium_ie = run_env.Alias(
        'selenium_ie',
        ['$ARTIFACTS_DIR/${LIBPREFIX}npo3dautoplugin$SHLIBSUFFIX',
         env.GetPublished('samples', 'asset_files')],
        # TODO: have a cleaner way to do this.
        [Delete('$ARTIFACTS_DIR/selenium/screenshots_ie'),
         Mkdir('$ARTIFACTS_DIR/selenium/screenshots_ie'),
         run_env.Python([
            'tests/selenium/main.py',
            '$SELENIUM_FLAGS',
            '--browser=*iexplore',
            '--servertimeout=80',
            '--referencedir=$TEST_REFERENCE_IMAGES',
            '--screenshotsdir=$ARTIFACTS_DIR/selenium/screenshots_ie'])],
    )
    run_env.Requires(run_selenium_ie, '$IE_PLUGIN_DIR')

    run_selenium_chrome = run_env.Alias(
        'selenium_chrome',
        ['$ARTIFACTS_DIR/${LIBPREFIX}npo3dautoplugin$SHLIBSUFFIX',
         env.GetPublished('samples', 'asset_files')],
        # TODO: have a cleaner way to do this.
        [Delete('$ARTIFACTS_DIR/selenium/screenshots_chrome'),
         Mkdir('$ARTIFACTS_DIR/selenium/screenshots_chrome'),
         run_env.Python([
            'tests/selenium/main.py',
            '$SELENIUM_FLAGS',
            '--browser=*googlechrome',
            '--referencedir=$TEST_REFERENCE_IMAGES',
            '--screenshotsdir=$ARTIFACTS_DIR/selenium/screenshots_chrome'])],
    )
    # Chrome requires that the plug-in be located in the install path.
    env.Requires(run_selenium_chrome, env.Alias('install'))

  if installed_pdiff:
    env.Requires(run_selenium_firefox, installed_pdiff)
    if run_env.Bit('windows'):
      env.Requires(run_selenium_ie, installed_pdiff)
      env.Requires(run_selenium_chrome, installed_pdiff)

  env.AlwaysBuild(run_selenium_firefox)
  if run_env.Bit('windows'):
    env.AlwaysBuild(run_selenium_ie)
    env.AlwaysBuild(run_selenium_chrome)

  run_env.Alias('selenium', run_selenium_firefox)

run_env.Defer(DeferSelenium)

# Add help.
env.Help('selenium_{firefox|ie|chrome): run selenium tests in the given browser\n')


# Add generation of lump for hive selenium tests.
if env.AnyBits('mac', 'windows'):
  selenium_env = env.Clone()
  selenium_env.AppendENVPath('PATH',
      os.environ.get('PRESCONS_PATH', '').split(';'))

  # Pull in all pulse related environment variables.
  for k in os.environ:
    if k.startswith('PULSE_'):
      selenium_env['ENV'][k] = os.environ[k]

  selenium_env['PREP_SELENIUM_ARCHIVE'] = (
      '$TARGET_ROOT/${PREP_SELENIUM_ARCHIVE_NAME}.zip')

  if int(ARGUMENTS.get('O3D_ENABLE_BREAKPAD', 0)):
    selenium_env['O3D_BRANCH'] = 'release'
  else:
    selenium_env['O3D_BRANCH'] = 'trunk'

  if env.Bit('mac'):
    selenium_env['PREP_SELENIUM_ARCHIVE_NAME'] = 'O3Dtests_mac'
    selenium_env['GNU_SETUP_EXTRAS'] = ''
    selenium_env['SETUP_SCRIPTS'] = (
        'export PYTHONPATH=' + env.Dir('$MAIN_DIR/scripts').abspath)
  else:
    selenium_env['PREP_SELENIUM_ARCHIVE_NAME'] = 'O3Dtests'
    selenium_env['GNU_SETUP_EXTRAS'] = r'..\o3d-internal\third_party\gnu\setup_env.bat && '
    selenium_env['SETUP_SCRIPTS'] = (
        'set PYTHONPATH=' + env.Dir('$MAIN_DIR/scripts').abspath)

  selenium_env['ENV']['DXSDK_DIR'] = os.environ.get('DXSDK_DIR', '')

  selenium_env.AlwaysBuild(selenium_env.Alias('prep_selenium', [],
      [Delete('$TARGET_ROOT/${PREP_SELENIUM_ARCHIVE_NAME}'),
       '$SETUP_SCRIPTS && '
       'cd .. && cd o3d-internal && cd tests && cd lab_automation && ' +
       sys.executable + ' prepare_selenium_tests.py '
       '$TARGET_ROOT/${PREP_SELENIUM_ARCHIVE_NAME}',
       Delete('$PREP_SELENIUM_ARCHIVE'),
       '${GNU_SETUP_EXTRAS}'
       'cd $TARGET_ROOT && '
       'zip -9 -r $PREP_SELENIUM_ARCHIVE ${PREP_SELENIUM_ARCHIVE_NAME}',
    ]))



#--------------------------------------------------------------------------
# General stuff

presubmit_tests = [
  env.Alias('unit_tests'),
]

if ARGUMENTS.get('SYSTEM_TESTS_ENABLED', False):
  presubmit_tests += [
    env.Alias('system_tests'),
  ]

# TODO: Make presubmit run selenium once the OpenGL build is
# completely working.
if 'RENDERER_D3D9' in env['CPPDEFINES']:
  presubmit_tests += [
      env.Alias('selenium_firefox'),
  ]

env.Alias('presubmit', presubmit_tests)
env.Help('presubmit: run unit tests and selenium integration tests.\n')

# Add an alias for what to run on Pulse.
pulse_tests = [env.Alias('presubmit')]
# OpenGL tests don't work with selenium yet.
if 'RENDERER_D3D9' in env['CPPDEFINES']:
  pulse_tests += [env.Alias('selenium_firefox'),
                  env.Alias('selenium_ie')]
# Add selenium for mac.
if env.Bit('mac'):
  pulse_tests += [env.Alias('selenium')]

env.Alias('pulse_tests', pulse_tests)
env.Help('pulse_tests: the test target that automatic builds use.\n')

# TODO: shouldn't need this.
# Adding extra line for cleaner formatting.
env.Help('\n')


#--------------------------------------------------------------------------
# Other odds and ends

# Install presubmit_tests batch file.
# TODO: is this really needed anymore?
env.Replicate('$ARTIFACTS_DIR', 'presubmit_tests.bat')