text: # Copyright 2018-present MongoDB, Inc.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #   http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  
  from collections import OrderedDict as OD
  from itertools import chain
  
  try:
      # Python 3 abstract base classes.
      import collections.abc as abc
  except ImportError:
      import collections as abc
  
  from evergreen_config_generator.functions import (
      bootstrap, func, run_tests, s3_put)
  from evergreen_config_generator.tasks import (
      both_or_neither, FuncTask, MatrixTask, NamedTask, prohibit, require, Task)
  from evergreen_config_lib import shell_mongoc
  
  
  class CompileTask(NamedTask):
      def __init__(self, task_name, tags=None, config='debug',
                   compression='default', continue_on_err=False,
                   extra_commands=None, depends_on=None, **kwargs):
          super(CompileTask, self).__init__(task_name=task_name,
                                            depends_on=depends_on,
                                            tags=tags,
                                            **kwargs)
  
          self.extra_commands = extra_commands or []
  
          # Environment variables for .evergreen/compile.sh.
          self.compile_sh_opt = kwargs
          if config == 'debug':
              self.compile_sh_opt['DEBUG'] = 'ON'
          else:
              assert config == 'release'
              self.compile_sh_opt['RELEASE'] = 'ON'
  
          if compression != 'default':
              self.compile_sh_opt['SNAPPY'] = (
                  'ON' if compression in ('all', 'snappy') else 'OFF')
              self.compile_sh_opt['ZLIB'] = (
                  'BUNDLED' if compression in ('all', 'zlib') else 'OFF')
              self.compile_sh_opt['ZSTD'] = (
                  'ON' if compression in ('all', 'zstd') else 'OFF')
  
          self.continue_on_err = continue_on_err
  
      def to_dict(self):
          task = super(CompileTask, self).to_dict()
  
          script = ''
          for opt, value in sorted(self.compile_sh_opt.items()):
              script += 'export %s="%s"\n' % (opt, value)
  
          script += "CC='${CC}' MARCH='${MARCH}' sh .evergreen/compile.sh"
          task['commands'].append(shell_mongoc(script))
          task['commands'].append(func('upload build'))
          task['commands'].extend(self.extra_commands)
          return task
  
  
  class SpecialTask(CompileTask):
      def __init__(self, *args, **kwargs):
          super(SpecialTask, self).__init__(*args, **kwargs)
          self.add_tags('special')
  
  
  class LinkTask(NamedTask):
      def __init__(self, task_name, extra_commands, orchestration=True, **kwargs):
          if orchestration == 'ssl':
              bootstrap_commands = [bootstrap(SSL=1)]
          elif orchestration:
              bootstrap_commands = [bootstrap()]
          else:
              bootstrap_commands = []
  
          super(LinkTask, self).__init__(
              task_name=task_name,
              depends_on=OD([('name', 'make-release-archive'),
                             ('variant', 'releng')]),
              commands=bootstrap_commands + extra_commands,
              **kwargs)
  
  
  all_tasks = [
      NamedTask('check-headers',
                commands=[shell_mongoc('sh ./.evergreen/check-public-decls.sh'), shell_mongoc('python ./.evergreen/check-preludes.py .')]),
      FuncTask('make-release-archive',
               'release archive', 'upload docs', 'upload man pages',
               'upload release', 'upload build'),
      CompileTask('hardened-compile',
                  tags=['hardened'],
                  compression=None,
                  CFLAGS='-fno-strict-overflow -D_FORTIFY_SOURCE=2 -fstack-protector-all -fPIE -O',
                  LDFLAGS='-pie -Wl,-z,relro -Wl,-z,now'),
      FuncTask('abi-compliance-check', 'abi report'),
      CompileTask('debug-compile-compression-zlib',
                  tags=['zlib', 'compression'],
                  compression='zlib'),
      CompileTask('debug-compile-compression-snappy',
                  tags=['snappy', 'compression'],
                  compression='snappy'),
      CompileTask('debug-compile-compression-zstd',
                  tags=['zstd', 'compression'],
                  compression='zstd'),
      CompileTask('debug-compile-compression',
                  tags=['zlib', 'snappy', 'zstd', 'compression'],
                  compression='all'),
      CompileTask('debug-compile-no-align',
                  tags=['debug-compile'],
                  compression='zlib',
                  EXTRA_CONFIGURE_FLAGS="-DENABLE_EXTRA_ALIGNMENT=OFF"),
      CompileTask('debug-compile-nosasl-nossl',
                  tags=['debug-compile', 'nosasl', 'nossl']),
      CompileTask('debug-compile-lto', CFLAGS='-flto'),
      CompileTask('debug-compile-lto-thin', CFLAGS='-flto=thin'),
      SpecialTask('debug-compile-c11',
                  tags=['debug-compile', 'c11', 'stdflags'],
                  CFLAGS='-std=c11 -D_XOPEN_SOURCE=600'),
      SpecialTask('debug-compile-c99',
                  tags=['debug-compile', 'c99', 'stdflags'],
                  CFLAGS='-std=c99 -D_XOPEN_SOURCE=600'),
      SpecialTask('debug-compile-c89',
                  tags=['debug-compile', 'c89', 'stdflags'],
                  CFLAGS='-std=c89 -D_POSIX_C_SOURCE=200112L -pedantic'),
      SpecialTask('debug-compile-valgrind',
                  tags=['debug-compile', 'valgrind'],
                  SASL='OFF',
                  SSL='OPENSSL',
                  VALGRIND='ON',
                  CFLAGS='-DBSON_MEMCHECK'),
      SpecialTask('debug-compile-coverage',
                  tags=['debug-compile', 'coverage'],
                  COVERAGE='ON',
                  extra_commands=[func('upload coverage')]),
      CompileTask('debug-compile-no-counters',
                  tags=['debug-compile', 'no-counters'],
                  ENABLE_SHM_COUNTERS='OFF'),
      SpecialTask('debug-compile-asan-clang',
                  tags=['debug-compile', 'asan-clang'],
                  compression='zlib',
                  CC='clang-3.8',
                  CFLAGS='-fsanitize=address -fno-omit-frame-pointer'
                         ' -DBSON_MEMCHECK',
                  CHECK_LOG='ON',
                  EXTRA_CONFIGURE_FLAGS='-DENABLE_EXTRA_ALIGNMENT=OFF',
                  PATH='/usr/lib/llvm-3.8/bin:$PATH'),
      # include -pthread in CFLAGS on gcc to address the issue explained here:
      # https://groups.google.com/forum/#!topic/address-sanitizer/JxnwgrWOLuc
      SpecialTask('debug-compile-asan-gcc',
                  compression='zlib',
                  CFLAGS='-fsanitize=address -pthread',
                  CHECK_LOG='ON',
                  EXTRA_CONFIGURE_FLAGS="-DENABLE_EXTRA_ALIGNMENT=OFF"),
      SpecialTask('debug-compile-asan-clang-openssl',
                  tags=['debug-compile', 'asan-clang'],
                  compression='zlib',
                  CC='clang-3.8',
                  CFLAGS='-fsanitize=address -fno-omit-frame-pointer'
                         ' -DBSON_MEMCHECK',
                  CHECK_LOG='ON',
                  EXTRA_CONFIGURE_FLAGS="-DENABLE_EXTRA_ALIGNMENT=OFF",
                  PATH='/usr/lib/llvm-3.8/bin:$PATH',
                  SSL='OPENSSL'),
      SpecialTask('debug-compile-ubsan',
                  compression='zlib',
                  CC='clang-3.8',
                  CFLAGS='-fsanitize=undefined -fno-omit-frame-pointer'
                         ' -DBSON_MEMCHECK',
                  CHECK_LOG='ON',
                  EXTRA_CONFIGURE_FLAGS="-DENABLE_EXTRA_ALIGNMENT=OFF",
                  PATH='/usr/lib/llvm-3.8/bin:$PATH'),
      SpecialTask('debug-compile-scan-build',
                  tags=['clang', 'debug-compile', 'scan-build'],
                  continue_on_err=True,
                  ANALYZE='ON',
                  CC='clang',
                  extra_commands=[
                      func('upload scan artifacts'),
                      shell_mongoc('''
                          if find scan -name \*.html | grep -q html; then
                            exit 123
                          fi''')]),
      CompileTask('compile-tracing',
                  TRACING='ON'),
      CompileTask('release-compile',
                  config='release',
                  depends_on=OD([('name', 'make-release-archive'),
                                 ('variant', 'releng')])),
      CompileTask('debug-compile-nosasl-openssl',
                  tags=['debug-compile', 'nosasl', 'openssl'],
                  SSL='OPENSSL'),
      CompileTask('debug-compile-nosasl-darwinssl',
                  tags=['debug-compile', 'nosasl', 'darwinssl'],
                  SSL='DARWIN'),
      CompileTask('debug-compile-nosasl-winssl',
                  tags=['debug-compile', 'nosasl', 'winssl'],
                  SSL='WINDOWS'),
      CompileTask('debug-compile-sasl-nossl',
                  tags=['debug-compile', 'sasl', 'nossl'],
                  SASL='AUTO',
                  SSL='OFF'),
      CompileTask('debug-compile-sasl-openssl',
                  tags=['debug-compile', 'sasl', 'openssl'],
                  SASL='AUTO',
                  SSL='OPENSSL'),
      CompileTask('debug-compile-sasl-darwinssl',
                  tags=['debug-compile', 'sasl', 'darwinssl'],
                  SASL='AUTO',
                  SSL='DARWIN'),
      CompileTask('debug-compile-sasl-winssl',
                  tags=['debug-compile', 'sasl', 'winssl'],
                  SASL='AUTO',
                  SSL='WINDOWS'),
      CompileTask('debug-compile-sspi-nossl',
                  tags=['debug-compile', 'sspi', 'nossl'],
                  SASL='SSPI',
                  SSL='OFF'),
      CompileTask('debug-compile-sspi-openssl',
                  tags=['debug-compile', 'sspi', 'openssl'],
                  SASL='SSPI',
                  SSL='OPENSSL'),
      CompileTask('debug-compile-rdtscp',
                  ENABLE_RDTSCP='ON'),
      CompileTask('debug-compile-sspi-winssl',
                  tags=['debug-compile', 'sspi', 'winssl'],
                  SASL='SSPI',
                  SSL='WINDOWS'),
      CompileTask('debug-compile-nosrv',
                  tags=['debug-compile'],
                  SRV='OFF'),
      LinkTask('link-with-cmake',
               extra_commands=[
                   func('link sample program', BUILD_SAMPLE_WITH_CMAKE=1)]),
      LinkTask('link-with-cmake-ssl',
               extra_commands=[
                   func('link sample program',
                        BUILD_SAMPLE_WITH_CMAKE=1,
                        ENABLE_SSL=1)]),
      LinkTask('link-with-cmake-snappy',
               extra_commands=[
                   func('link sample program',
                        BUILD_SAMPLE_WITH_CMAKE=1,
                        ENABLE_SNAPPY=1)]),
      LinkTask('link-with-cmake-mac',
               extra_commands=[
                   func('link sample program', BUILD_SAMPLE_WITH_CMAKE=1)]),
      LinkTask('link-with-cmake-windows',
               extra_commands=[func('link sample program MSVC')]),
      LinkTask('link-with-cmake-windows-ssl',
               extra_commands=[func('link sample program MSVC', ENABLE_SSL=1)],
               orchestration='ssl'),
      LinkTask('link-with-cmake-windows-snappy',
               extra_commands=[
                   func('link sample program MSVC', ENABLE_SNAPPY=1)]),
      LinkTask('link-with-cmake-mingw',
               extra_commands=[func('link sample program mingw')]),
      LinkTask('link-with-pkg-config',
               extra_commands=[func('link sample program')]),
      LinkTask('link-with-pkg-config-mac',
               extra_commands=[func('link sample program')]),
      LinkTask('link-with-pkg-config-ssl',
               extra_commands=[func('link sample program', ENABLE_SSL=1)]),
      LinkTask('link-with-bson',
               extra_commands=[func('link sample program bson')],
               orchestration=False),
      LinkTask('link-with-bson-mac',
               extra_commands=[func('link sample program bson')],
               orchestration=False),
      LinkTask('link-with-bson-windows',
               extra_commands=[func('link sample program MSVC bson')],
               orchestration=False),
      LinkTask('link-with-bson-mingw',
               extra_commands=[func('link sample program mingw bson')],
               orchestration=False),
      NamedTask('debian-package-build',
                commands=[
                    shell_mongoc('export IS_PATCH="${is_patch}"\n'
                               'sh .evergreen/debian_package_build.sh'),
                    s3_put(local_file='deb.tar.gz',
                           remote_file='${branch_name}/mongo-c-driver-debian-packages-${CURRENT_VERSION}.tar.gz',
                           content_type='${content_type|application/x-gzip}')]),
      NamedTask('rpm-package-build',
                commands=[
                    shell_mongoc('sh .evergreen/build_snapshot_rpm.sh'),
                    s3_put(local_file='rpm.tar.gz',
                           remote_file='${branch_name}/mongo-c-driver-rpm-packages-${CURRENT_VERSION}.tar.gz',
                           content_type='${content_type|application/x-gzip}')]),
      NamedTask('install-uninstall-check-mingw',
                depends_on=OD([('name', 'make-release-archive'),
                               ('variant', 'releng')]),
                commands=[shell_mongoc(r'''
                    export CC="C:/mingw-w64/x86_64-4.9.1-posix-seh-rt_v3-rev1/mingw64/bin/gcc.exe"
                    BSON_ONLY=1 cmd.exe /c .\\.evergreen\\install-uninstall-check-windows.cmd
                    cmd.exe /c .\\.evergreen\\install-uninstall-check-windows.cmd''')]),
      NamedTask('install-uninstall-check-msvc',
                depends_on=OD([('name', 'make-release-archive'),
                               ('variant', 'releng')]),
                commands=[shell_mongoc(r'''
                    export CC="Visual Studio 14 2015 Win64"
                    BSON_ONLY=1 cmd.exe /c .\\.evergreen\\install-uninstall-check-windows.cmd
                    cmd.exe /c .\\.evergreen\\install-uninstall-check-windows.cmd''')]),
      NamedTask('install-uninstall-check',
                depends_on=OD([('name', 'make-release-archive'),
                               ('variant', 'releng')]),
                commands=[shell_mongoc(r'''
                    DESTDIR="$(pwd)/dest" sh ./.evergreen/install-uninstall-check.sh
                    BSON_ONLY=1 sh ./.evergreen/install-uninstall-check.sh
                    sh ./.evergreen/install-uninstall-check.sh''')]),
      CompileTask('debug-compile-with-warnings', CFLAGS='-Werror -Wno-cast-align'),
  ]
  
  
  class IntegrationTask(MatrixTask):
      axes = OD([('valgrind', ['valgrind', False]),
                 ('asan', ['asan', False]),
                 ('coverage', ['coverage', False]),
                 ('version', ['latest', '4.2', '4.0', '3.6', '3.4', '3.2', '3.0']),
                 ('topology', ['server', 'replica_set', 'sharded_cluster']),
                 ('auth', [True, False]),
                 ('sasl', ['sasl', 'sspi', False]),
                 ('ssl', ['openssl', 'darwinssl', 'winssl', False])])
  
      def __init__(self, *args, **kwargs):
          super(IntegrationTask, self).__init__(*args, **kwargs)
          if self.valgrind:
              self.add_tags('test-valgrind')
              self.options['exec_timeout_secs'] = 7200
          elif self.coverage:
              self.add_tags('test-coverage')
              self.options['exec_timeout_secs'] = 3600
          elif self.asan:
              self.add_tags('test-asan')
              self.options['exec_timeout_secs'] = 3600
          else:
              self.add_tags(self.topology,
                            self.version,
                            self.display('ssl'),
                            self.display('sasl'),
                            self.display('auth'))
  
          # E.g., test-latest-server-auth-sasl-ssl needs debug-compile-sasl-ssl.
          # Coverage tasks use a build function instead of depending on a task.
          if self.valgrind:
              self.add_dependency('debug-compile-valgrind')
          elif self.asan and self.ssl:
              self.add_dependency('debug-compile-asan-clang-%s' % (
                  self.display('ssl'),))
          elif self.asan:
              self.add_dependency('debug-compile-asan-clang')
          elif not self.coverage:
              self.add_dependency('debug-compile-%s-%s' % (
                  self.display('sasl'), self.display('ssl')))
  
      @property
      def name(self):
          def name_part(axis_name):
              part = self.display(axis_name)
              if part == 'replica_set':
                  return 'replica-set'
              elif part == 'sharded_cluster':
                  return 'sharded'
              return part
  
          return self.name_prefix + '-' + '-'.join(
              name_part(axis_name) for axis_name in self.axes
              if getattr(self, axis_name) or axis_name in ('auth', 'sasl', 'ssl'))
  
      def to_dict(self):
          task = super(IntegrationTask, self).to_dict()
          commands = task['commands']
          if self.depends_on:
              commands.append(
                  func('fetch build', BUILD_NAME=self.depends_on['name']))
          if self.coverage:
              commands.append(func('debug-compile-coverage-notest-%s-%s' % (
                  self.display('sasl'), self.display('ssl')
              )))
          commands.append(bootstrap(VERSION=self.version,
                                    TOPOLOGY=self.topology,
                                    AUTH='auth' if self.auth else 'noauth',
                                    SSL=self.display('ssl')))
          commands.append(run_tests(VALGRIND=self.on_off('valgrind'),
                                    ASAN=self.on_off('asan'),
                                    AUTH=self.display('auth'),
                                    SSL=self.display('ssl')))
          if self.coverage:
              commands.append(func('update codecov.io'))
  
          return task
  
      def _check_allowed(self):
          if self.valgrind:
              prohibit(self.asan)
              prohibit(self.sasl)
              require(self.ssl in ('openssl', False))
              prohibit(self.coverage)
              # Valgrind only with auth+SSL or no auth + no SSL.
              if self.auth:
                  require(self.ssl == 'openssl')
              else:
                  prohibit(self.ssl)
  
          if self.auth:
              require(self.ssl)
  
          if self.sasl == 'sspi':
              # Only one self.
              require(self.topology == 'server')
              require(self.version == 'latest')
              require(self.ssl == 'winssl')
              require(self.auth)
  
          if not self.ssl:
              prohibit(self.sasl)
  
          if self.coverage:
              prohibit(self.sasl)
  
              if self.auth:
                  require(self.ssl == 'openssl')
              else:
                  prohibit(self.ssl)
  
          if self.asan:
              prohibit(self.sasl)
              prohibit(self.coverage)
  
              # Address sanitizer only with auth+SSL or no auth + no SSL.
              if self.auth:
                  require(self.ssl == 'openssl')
              else:
                  prohibit(self.ssl)
  
  
  all_tasks = chain(all_tasks, IntegrationTask.matrix())
  
  
  class DNSTask(MatrixTask):
      axes = OD([('auth', [False, True]),
                 ('ssl', ['openssl', 'winssl', 'darwinssl'])])
  
      name_prefix = 'test-dns'
  
      def __init__(self, *args, **kwargs):
          super(DNSTask, self).__init__(*args, **kwargs)
          sasl = 'sspi' if self.ssl == 'winssl' else 'sasl'
          self.add_dependency('debug-compile-%s-%s' % (sasl, self.display('ssl')))
  
      @property
      def name(self):
          return self.name_prefix + '-' + '-'.join(
              self.display(axis_name) for axis_name in self.axes
              if getattr(self, axis_name))
  
      def to_dict(self):
          task = super(MatrixTask, self).to_dict()
          commands = task['commands']
          commands.append(
              func('fetch build', BUILD_NAME=self.depends_on['name']))
  
          orchestration = bootstrap(TOPOLOGY='replica_set',
                                    AUTH='auth' if self.auth else 'noauth',
                                    SSL='ssl')
  
          if self.auth:
              orchestration['vars']['AUTHSOURCE'] = 'thisDB'
              orchestration['vars']['ORCHESTRATION_FILE'] = 'auth-thisdb-ssl'
  
          commands.append(orchestration)
          commands.append(run_tests(SSL='ssl',
                                    AUTH=self.display('auth'),
                                    DNS='dns-auth' if self.auth else 'on'))
  
          return task
  
  
  all_tasks = chain(all_tasks, DNSTask.matrix())
  
  
  class CompressionTask(MatrixTask):
      axes = OD([('compression', ['zlib', 'snappy', 'zstd', 'compression'])])
      name_prefix = 'test-latest-server'
  
      def __init__(self, *args, **kwargs):
          super(CompressionTask, self).__init__(*args, **kwargs)
          self.add_dependency('debug-compile-' + self._compressor_suffix())
          self.add_tags('compression', 'latest')
          self.add_tags(*self._compressor_list())
  
      @property
      def name(self):
          return self.name_prefix + '-' + self._compressor_suffix()
  
      def to_dict(self):
          task = super(CompressionTask, self).to_dict()
          commands = task['commands']
          commands.append(func('fetch build', BUILD_NAME=self.depends_on['name']))
          if self.compression == 'compression':
              orchestration_file = 'snappy-zlib-zstd'
          else:
              orchestration_file = self.compression
  
          commands.append(bootstrap(
              AUTH='noauth',
              SSL='nossl',
              ORCHESTRATION_FILE=orchestration_file))
          commands.append(run_tests(
              AUTH='noauth',
              SSL='nossl',
              COMPRESSORS=','.join(self._compressor_list())))
  
          return task
  
      def _compressor_suffix(self):
          if self.compression == 'zlib':
              return 'compression-zlib'
          elif self.compression == 'snappy':
              return 'compression-snappy'
          elif self.compression == 'zstd':
              return 'compression-zstd'
          else:
              return 'compression'
  
      def _compressor_list(self):
          if self.compression == 'zlib':
              return ['zlib']
          elif self.compression == 'snappy':
              return ['snappy']
          elif self.compression == 'zstd':
              return ['zstd']
          else:
              return ['snappy', 'zlib', 'zstd']
  
  
  all_tasks = chain(all_tasks, CompressionTask.matrix())
  
  
  class SpecialIntegrationTask(NamedTask):
      def __init__(self, task_name, depends_on='debug-compile-sasl-openssl',
                   extra_commands=None, uri=None,
                   tags=None, version='latest', topology='server'):
          commands = [func('fetch build', BUILD_NAME=depends_on),
                      bootstrap(VERSION=version, TOPOLOGY=topology),
                      run_tests(uri)] + (extra_commands or [])
          super(SpecialIntegrationTask, self).__init__(task_name,
                                                       commands=commands,
                                                       depends_on=depends_on,
                                                       tags=tags)
  
  
  all_tasks = chain(all_tasks, [
      # Verify that retryWrites=true is ignored with standalone.
      SpecialIntegrationTask('retry-true-latest-server',
                             uri='mongodb://localhost/?retryWrites=true'),
      # Verify that retryWrites=true is ignored with old server.
      SpecialIntegrationTask('retry-true-3.4-replica-set',
                             version='3.4',
                             topology='replica_set'),
      SpecialIntegrationTask('test-latest-server-hardened',
                             'hardened-compile',
                             tags=['hardened', 'latest']),
  ])
  
  
  class AuthTask(MatrixTask):
      axes = OD([('sasl', ['sasl', 'sspi', False]),
                 ('ssl', ['openssl', 'darwinssl', 'winssl'])])
  
      name_prefix = 'authentication-tests'
  
      def __init__(self, *args, **kwargs):
          super(AuthTask, self).__init__(*args, **kwargs)
          self.add_tags('authentication-tests',
                        self.display('ssl'),
                        self.display('sasl'))
  
          self.add_dependency('debug-compile-%s-%s' % (
              self.display('sasl'), self.display('ssl')))
  
          self.commands.extend([
              func('fetch build', BUILD_NAME=self.depends_on['name']),
              func('run auth tests')])
  
      @property
      def name(self):
          rv = self.name_prefix + '-' + self.display('ssl')
          if self.sasl:
              return rv
          else:
              return rv + '-nosasl'
  
      def _check_allowed(self):
          both_or_neither(self.ssl == 'winssl', self.sasl == 'sspi')
          if not self.sasl:
              require(self.ssl == 'openssl')
  
  
  all_tasks = chain(all_tasks, AuthTask.matrix())
  
  
  class PostCompileTask(NamedTask):
      def __init__(self, *args, **kwargs):
          super(PostCompileTask, self).__init__(*args, **kwargs)
          self.commands.insert(
              0, func('fetch build', BUILD_NAME=self.depends_on['name']))
  
  
  all_tasks = chain(all_tasks, [
      PostCompileTask(
          'test-valgrind-memcheck-mock-server',
          tags=['test-valgrind'],
          depends_on='debug-compile-valgrind',
          commands=[func('run mock server tests', VALGRIND='on', SSL='ssl')]),
      PostCompileTask(
          'test-asan-memcheck-mock-server',
          tags=['test-asan'],
          depends_on='debug-compile-asan-clang',
          commands=[func('run mock server tests', ASAN='on', SSL='ssl')]),
      # Compile with a function, not a task: gcov files depend on the absolute
      # path of the executable, so we can't compile as a separate task.
      NamedTask(
          'test-coverage-mock-server',
          tags=['test-coverage'],
          commands=[func('debug-compile-coverage-notest-nosasl-openssl'),
                    func('run mock server tests', SSL='ssl'),
                    func('update codecov.io')]),
      NamedTask(
          'test-coverage-latest-server-dns',
          tags=['test-coverage'],
          exec_timeout_secs=3600,
          commands=[func('debug-compile-coverage-notest-nosasl-openssl'),
                    bootstrap(TOPOLOGY='replica_set', AUTH='auth', SSL='ssl'),
                    run_tests(AUTH='auth', SSL='ssl', DNS='on'),
                    func('update codecov.io')]),
      NamedTask(
          'authentication-tests-memcheck',
          tags=['authentication-tests', 'valgrind'],
          exec_timeout_seconds=3600,
          commands=[
              shell_mongoc("""
                  VALGRIND=ON DEBUG=ON CC='${CC}' MARCH='${MARCH}' SASL=AUTO \
                    SSL=OPENSSL CFLAGS='-DBSON_MEMCHECK' sh .evergreen/compile.sh
                  """),
              func('run auth tests', valgrind='true')]),
  ])
  
  
  class SSLTask(Task):
      def __init__(self, version, patch, cflags=None, fips=False, **kwargs):
          full_version = version + patch + ('-fips' if fips else '')
          script = ''
          if cflags:
              script += 'export CFLAGS=%s\n' % (cflags,)
  
          script += "DEBUG=ON CC='${CC}' MARCH='${MARCH}' SASL=OFF"
          if 'libressl' in version:
              script += " SSL=LIBRESSL"
          else:
              script += " SSL=OPENSSL"
  
          if fips:
              script += " OPENSSL_FIPS=1"
  
          script += " sh .evergreen/compile.sh"
  
          super(SSLTask, self).__init__(commands=[
              func('install ssl', SSL=full_version),
              shell_mongoc(script),
              func('run auth tests', **kwargs),
              func('upload build')])
  
          self.version = version
          self.fips = fips
  
      @property
      def name(self):
          s = 'build-and-run-authentication-tests-' + self.version
          if self.fips:
              return s + '-fips'
  
          return s
  
  
  all_tasks = chain(all_tasks, [
      SSLTask('openssl-0.9.8', 'zh', obsolete_tls=True),
      SSLTask('openssl-1.0.0', 't', obsolete_tls=True),
      SSLTask('openssl-1.0.1', 'u', cflags='-Wno-redundant-decls'),
      SSLTask('openssl-1.0.1', 'u', cflags='-Wno-redundant-decls', fips=True),
      SSLTask('openssl-1.0.2', 'l'),
      SSLTask('openssl-1.1.0', 'f'),
      SSLTask('libressl-2.5', '.2', require_tls12=True),
      NamedTask('compile-libmongocapi',
                commands=[shell_mongoc(r'''
                    . ./.evergreen/find-cmake.sh
                    ${setup_android_toolchain|}
                    export ${libmongocapi_compile_env|}
                    mkdir cmake-build-libmongocapi
                    $CMAKE \
                      -DCMAKE_INSTALL_PREFIX=cmake-build-libmongocapi \
                      -DENABLE_SNAPPY=OFF \
                      -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF \
                      -DENABLE_ZLIB=OFF -DENABLE_SSL=OFF \
                      -DENABLE_SASL=OFF \
                      -DENABLE_TESTS=OFF \
                      -DENABLE_SRV=OFF \
                      -DENABLE_EXAMPLES=OFF \
                      -DENABLE_STATIC=OFF \
                      -DENABLE_SHM_COUNTERS=OFF \
                      ${libmongocapi_cmake_flags}
                    make install VERBOSE=1''')]),
  ])
  
  
  class IPTask(MatrixTask):
      axes = OD([('client', ['ipv6', 'ipv4', 'localhost']),
                 ('server', ['ipv6', 'ipv4'])])
  
      name_prefix = 'test-latest'
  
      def __init__(self, *args, **kwargs):
          super(IPTask, self).__init__(*args, **kwargs)
          self.add_tags('nossl', 'nosasl', 'server', 'ipv4-ipv6', 'latest')
          self.add_dependency('debug-compile-nosasl-nossl')
          self.commands.extend([
              func('fetch build', BUILD_NAME=self.depends_on['name']),
              bootstrap(IPV4_ONLY=self.on_off(server='ipv4')),
              run_tests(IPV4_ONLY=self.on_off(server='ipv4'),
                        URI={'ipv6': 'mongodb://[::1]/',
                             'ipv4': 'mongodb://127.0.0.1/',
                             'localhost': 'mongodb://localhost/'}[self.client])])
  
      def display(self, axis_name):
          return axis_name + '-' + getattr(self, axis_name)
  
      @property
      def name(self):
          return '-'.join([
              self.name_prefix, self.display('server'), self.display('client'),
              'noauth', 'nosasl', 'nossl'])
  
      def _check_allowed(self):
          # This would fail by design.
          if self.server == 'ipv4':
              prohibit(self.client == 'ipv6')
  
          # Default configuration is tested in other variants.
          if self.server == 'ipv6':
              prohibit(self.client == 'localhost')
  
  
  all_tasks = chain(all_tasks, IPTask.matrix())
  all_tasks = list(all_tasks)
  