text:
<file_sep># Copyright 2015 PerfKitBenchmarker Authors. All rights reserved.
#
# 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.

"""Tests for perfkitbenchmarker.providers"""

import unittest

import mock

from perfkitbenchmarker import providers
from perfkitbenchmarker import requirements
from perfkitbenchmarker.configs import benchmark_config_spec
from tests import mock_flags

class LoadProvidersTestCase(unittest.TestCase):

  def setUp(self):
    p = mock.patch.object(providers, '_imported_providers', new=set())
    p.start()
    self.addCleanup(p.stop)

  def testImportAllProviders(self):
    # Test that all modules can be imported successfully, but mock out the
    # import of CloudStack's csapi.
    with mock.patch.dict('sys.modules', csapi=mock.Mock()):
      for cloud in providers.VALID_CLOUDS:
        providers.LoadProvider(cloud)

  def testLoadInvalidProvider(self):
    with self.assertRaises(ImportError):
      providers.LoadProvider('InvalidCloud')

  def testLoadProviderChecksRequirements(self):
    with mock.patch(requirements.__name__ + '.CheckProviderRequirements'):
      providers.LoadProvider('GCP', ignore_package_requirements=False)
      requirements.CheckProviderRequirements.assert_called_once_with('gcp')

  def testLoadProviderIgnoresRequirements(self):
    with mock.patch(requirements.__name__ + '.CheckProviderRequirements'):
      providers.LoadProvider('GCP')
      requirements.CheckProviderRequirements.assert_not_called()

  def testBenchmarkConfigSpecLoadsProvider(self):
    p = mock.patch(providers.__name__ + '.LoadProvider')
    p.start()
    self.addCleanup(p.stop)
    config = {
        'vm_groups': {
            'group1': {
                'cloud': 'AWS',
                'os_type': 'debian',
                'vm_count': 0,
                'vm_spec': {'AWS': {}}
            }
        }
    }
    with mock_flags.PatchFlags() as mocked_flags:
      benchmark_config_spec.BenchmarkConfigSpec(
          'name', flag_values=mocked_flags, **config)
    providers.LoadProvider.assert_called_with('AWS', True)
<file_sep># Copyright 2015 PerfKitBenchmarker Authors. All rights reserved.
#
# 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.

"""Run NTttcp between two VMs."""

from perfkitbenchmarker import configs
from perfkitbenchmarker import flags
from perfkitbenchmarker import vm_util

from perfkitbenchmarker.windows_packages import ntttcp

FLAGS = flags.FLAGS

BENCHMARK_NAME = 'ntttcp'
BENCHMARK_CONFIG = """
ntttcp:
  description: Run ntttcp between two VMs.
  vm_groups:
    default:
      vm_spec: *default_single_core
      vm_count: 2
"""

def GetConfig(user_config):
  return configs.LoadConfig(BENCHMARK_CONFIG, user_config, BENCHMARK_NAME)

def Prepare(benchmark_spec):
  vms = benchmark_spec.vms

  for vm in vms:
    vm.Install('ntttcp')
    vm.AllowPort(ntttcp.CONTROL_PORT)
    for port in xrange(ntttcp.BASE_DATA_PORT,
                       ntttcp.BASE_DATA_PORT + FLAGS.ntttcp_threads):
      vm.AllowPort(port)

def Run(benchmark_spec):
  """Measure TCP stream throughput between two VMs.

  Args:
    benchmark_spec: The benchmark specification. Contains all data that is
        required to run the benchmark.

  Returns:
    A list of sample.Sample objects with the benchmark results.
  """

  vms = benchmark_spec.vms
  results = []

  # Send traffic in both directions
  for originator in [0, 1]:
    sending_vm = vms[originator]
    receiving_vm = vms[originator ^ 1]
    # Send using external IP addresses
    if vm_util.ShouldRunOnExternalIpAddress():
      results.extend(ntttcp.RunNtttcp(sending_vm,
                                      receiving_vm,
                                      receiving_vm.ip_address,
                                      'external'))

    # Send using internal IP addresses
    if vm_util.ShouldRunOnInternalIpAddress(sending_vm,
                                            receiving_vm):
      results.extend(ntttcp.RunNtttcp(sending_vm,
                                      receiving_vm,
                                      receiving_vm.internal_ip,
                                      'internal'))
  return results

def Cleanup(unused_benchmark_spec):
  pass
<file_sep># Copyright 2014 PerfKitBenchmarker Authors. All rights reserved.
#
# 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.

"""Module containing HPCC installation and cleanup functions.

The HPC Challenge is a collection of High Performance Computing benchmarks,
including High Performance Linpack (HPL). More information can be found here:
http://icl.cs.utk.edu/hpcc/
"""

import re

from perfkitbenchmarker import flags
from perfkitbenchmarker import errors
from perfkitbenchmarker.linux_packages import INSTALL_DIR
from perfkitbenchmarker.linux_packages import openblas

HPCC_TAR = 'hpcc-1.4.3.tar.gz'
HPCC_URL = 'http://icl.cs.utk.edu/projectsfiles/hpcc/download/' + HPCC_TAR
HPCC_DIR = '%s/hpcc-1.4.3' % INSTALL_DIR

MAKE_FLAVOR_CBLAS = 'Linux_PII_CBLAS'
MAKE_FLAVOR_MKL = 'intel64'
MAKE_FLAVOR_OPEN_BLAS = 'OPEN_BLAS'

HPCC_MAKEFILE_CBLAS = 'Make.%s' % MAKE_FLAVOR_CBLAS
HPCC_MAKEFILE_MKL = 'Make.%s' % MAKE_FLAVOR_MKL
HPCC_MAKEFILE_OPEN_BLAS = 'Make.%s' % MAKE_FLAVOR_OPEN_BLAS

HPCC_MAKEFILE_PATH_MKL = '%s/hpl/%s' % (HPCC_DIR, HPCC_MAKEFILE_MKL)
HPCC_MAKEFILE_PATH_OPEN_BLAS = '%s/hpl/%s' % (HPCC_DIR, HPCC_MAKEFILE_OPEN_BLAS)

HPCC_MATH_LIBRARY_OPEN_BLAS = 'openblas'
HPCC_MATH_LIBRARY_MKL = 'mkl'

flags.DEFINE_enum(
    'hpcc_math_library', HPCC_MATH_LIBRARY_OPEN_BLAS,
    [HPCC_MATH_LIBRARY_OPEN_BLAS, HPCC_MATH_LIBRARY_MKL],
    'The math library to use when compiling hpcc: openBlas or MKL. '
    'The default is openBlas')
FLAGS = flags.FLAGS

def _Install(vm):
  """Installs the HPCC package on the VM."""
  vm.Install('wget')
  vm.Install('openmpi')
  vm.RemoteCommand('wget %s -P %s' % (HPCC_URL, INSTALL_DIR))
  vm.RemoteCommand('cd %s && tar xvfz %s' % (INSTALL_DIR, HPCC_TAR))
  if FLAGS.hpcc_math_library == HPCC_MATH_LIBRARY_OPEN_BLAS:
    _CompileHpccOpenblas(vm)
  elif FLAGS.hpcc_math_library == HPCC_MATH_LIBRARY_MKL:
    _CompileHpccMKL(vm)
  else:
    raise errors.Setup.InvalidFlagConfigurationError(
        'Unexpected hpcc_math_library option encountered.')

def _CompileHpccOpenblas(vm):
  """Compile HPCC with OpenBlas."""
  vm.Install('openblas')
  vm.RemoteCommand(
      'cp %s/hpl/setup/%s %s' %
      (HPCC_DIR, HPCC_MAKEFILE_CBLAS, HPCC_MAKEFILE_PATH_OPEN_BLAS))
  sed_cmd = (
      'sed -i -e "/^MP/d" -e "s/gcc/mpicc/" -e "s/g77/mpicc/" '
      '-e "s/\\$(HOME)\\/netlib\\/ARCHIVES\\/Linux_PII/%s/" '
      '-e "s/libcblas.*/libopenblas.a/" '
      '-e "s/\\-lm/\\-lgfortran \\-lm/" %s' %
      (re.escape(openblas.OPENBLAS_DIR), HPCC_MAKEFILE_PATH_OPEN_BLAS))
  vm.RemoteCommand(sed_cmd)
  vm.RemoteCommand('cd %s; make arch=OPEN_BLAS' % HPCC_DIR)

def _CompileHpccMKL(vm):
  """Compiling HPCC with Intel MKL.

  The following link provides instructions of using intel MKL in hpcc_benchmark.
  https://software.intel.com/en-us/articles/performance-tools-for-software-developers-use-of-intel-mkl-in-hpcc-benchmark
  TODO(yanfeiren):The free version MKL pacakage does not have
  'interfaces/fftw2x_cdft' which is the MPI FFTW 2.x interfaces to the
  Intel MKL Cluster FFT. Such that we have to at first install OpenBlas and
  build hpcc binary using OpenBlas. Need to investigate how to build hpcc
  binary without 'interfaces/fftw2x_cdft'.
  """
  _CompileHpccOpenblas(vm)
  vm.RemoteCommand('cd %s; rm hpcc' % HPCC_DIR)
  vm.Install('mkl')
  vm.RemoteCommand(
      'cp %s/hpl/setup/%s %s' %
      (HPCC_DIR, HPCC_MAKEFILE_CBLAS, HPCC_MAKEFILE_PATH_MKL))
  mkl_lalib = (
      '-Wl,--start-group $(LAdir)/libfftw2xc_double_gnu.a '
      '$(LAdir)/libfftw2xf_double_gnu.a '
      '$(LAdir)/libmkl_intel_lp64.a '
      '$(LAdir)/libmkl_intel_thread.a '
      '$(LAdir)/libmkl_core.a '
      '$(LAdir)/libmkl_blas95_lp64.a '
      '-Wl,--end-group')
  mkl_ccflags = (
      ' -Wl,--no-as-needed -ldl -lmpi -liomp5 -lpthread -lm '
      '-DUSING_FFTW -DMKL_INT=long -DLONG_IS_64BITS')
  sed_cmd_mkl = (
      'sed -i -e "/^MP/d" -e "s/gcc/mpicc/" -e "s/g77/mpicc/" '
      '-e "s/\\$(HOME)\\/netlib\\/ARCHIVES\\/Linux_PII/'
      '\\/opt\\/intel\\/mkl\\/lib\\/intel64/" '
      '-e "s/\\$(LAdir)\\/libcblas.*/%s/" '
      '-e "s/\\-lm/\\-lgfortran \\-lm/" '
      '-e "/CCFLAGS / s/$/%s/" %s' %
      (re.escape(mkl_lalib), re.escape(mkl_ccflags), HPCC_MAKEFILE_PATH_MKL))
  vm.RemoteCommand(sed_cmd_mkl)
  vm.RemoteCommand('source /opt/intel/compilers_and_libraries/linux/bin/'
                   'compilervars.sh -arch intel64 -platform linux && '
                   'cd %s; make arch=intel64' % HPCC_DIR)

def YumInstall(vm):
  """Installs the HPCC package on the VM."""
  _Install(vm)

def AptInstall(vm):
  """Installs the HPCC package on the VM."""
  _Install(vm)
<file_sep># Copyright 2016 PerfKitBenchmarker Authors. All rights reserved.
#
# 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.

"""Module containing memcached server installation and cleanup functions."""

import logging

from perfkitbenchmarker import errors
from perfkitbenchmarker import flags
from perfkitbenchmarker import vm_util
from perfkitbenchmarker.linux_packages import INSTALL_DIR

FLAGS = flags.FLAGS

DOWNLOAD_URL = 'http://memcached.org/files/memcached-1.4.33.tar.gz'
MEMCACHED_DIR_NAME = 'memcached'
MEMCACHED_DIR = '%s/%s' % (INSTALL_DIR, MEMCACHED_DIR_NAME)

MEMCACHED_PORT = 11211

flags.DEFINE_integer('memcached_size_mb', 64,
                     'Size of memcached cache in megabytes.')

def _Install(vm):
  """Installs the memcached server on the VM."""
  vm.Install('build_tools')
  vm.Install('event')
  vm.RemoteCommand('cd {0} && wget {1} -O memcached.tar.gz'.format(
                   INSTALL_DIR, DOWNLOAD_URL))
  out, _ = vm.RemoteCommand('cd %s && tar -xzvf memcached.tar.gz' % INSTALL_DIR)
  # The directory name should be the first line of stdout
  memcached_dir = out.split('\n', 1)[0]
  # Rename the directory to a standard name
  vm.RemoteCommand('cd {0} && mv {1} {2}'.format(
                   INSTALL_DIR, memcached_dir, MEMCACHED_DIR_NAME))
  # Make memcached
  vm.RemoteCommand('cd {0} && ./configure && make'.format(MEMCACHED_DIR))

def YumInstall(vm):
  """Installs the memcache package on the VM."""
  _Install(vm)

def AptInstall(vm):
  """Installs the memcache package on the VM."""
  _Install(vm)

@vm_util.Retry(poll_interval=5, timeout=300,
               retryable_exceptions=(errors.Resource.RetryableCreationError))
def _WaitForServerUp(server):
  """Block until the memcached server is up and responsive.

  Will timeout after 5 minutes, and raise an exception. Before the timeout
  expires any exceptions are caught and the status check is retried.

  We check the status of the server by issuing a 'stats' command. This should
  return many lines of form 'STAT <name> <value>\\r\\n' if the server is up and
  running.

  Args:
    server: VirtualMachine memcached has been installed on.

  Raises:
    errors.Resource.RetryableCreationError when response is not as expected or
      if there is an error connecting to the port or otherwise running the
      remote check command.
  """
  address = server.internal_ip
  port = MEMCACHED_PORT

  logging.info("Trying to connect to memcached at %s:%s", address, port)
  try:
    out, _ = server.RemoteCommand(
        '(echo -e "stats\n" ; sleep 1)| netcat %s %s' % (address, port))
    if out.startswith('STAT '):
      logging.info("memcached server stats received. Server up and running.")
      return
  except errors.VirtualMachine.RemoteCommandError as e:
    raise errors.Resource.RetryableCreationError(
        "memcached server not up yet: %s." % str(e))
  else:
    raise errors.Resource.RetryableCreationError(
        "memcached server not up yet. Expected 'STAT' but got '%s'." % out)

def ConfigureAndStart(server):
  """Prepare the memcached server on a VM.

  Args:
    server: VirtualMachine to install and start memcached on.
  """
  server.Install('memcached_server')

  for scratch_disk in server.scratch_disks:
    server.RemoteCommand('sudo umount %s' % scratch_disk.mount_point)

  server.RemoteCommand('cd {mcdir}; ./memcached -m {size} '
                       '&> /dev/null &'.format(
                           mcdir=MEMCACHED_DIR, size=FLAGS.memcached_size_mb))
  _WaitForServerUp(server)
  logging.info("memcached server configured and started.")

def StopMemcached(server):
  out, _ = server.RemoteCommand(
      '(echo -e "quit\n" ; sleep 1)| netcat %s %s' %
      (server.internal_ip, MEMCACHED_PORT))

def FlushMemcachedServer(ip, port):
  vm_util.IssueCommand(
      '(echo -e "flush_all\n" ; sleep 1)| netcat %s %s' % (ip, port))

def Uninstall(vm):
  vm.RemoteCommand('pkill memcached')
  vm.RemoteCommand('rm -rf %s' % MEMCACHED_DIR)
<file_sep># Copyright 2014 PerfKitBenchmarker Authors. All rights reserved.
#
# 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.

"""Module containing memtier installation and cleanup functions."""

from perfkitbenchmarker.linux_packages import INSTALL_DIR

GIT_REPO = 'https://github.com/RedisLabs/memtier_benchmark'
GIT_TAG = '1.2.0'
LIBEVENT_TAR = 'libevent-2.0.21-stable.tar.gz'
LIBEVENT_URL = 'https://github.com/downloads/libevent/libevent/' + LIBEVENT_TAR
LIBEVENT_DIR = '%s/libevent-2.0.21-stable' % INSTALL_DIR
MEMTIER_DIR = '%s/memtier_benchmark' % INSTALL_DIR
APT_PACKAGES = ('autoconf automake libpcre3-dev '
                'libevent-dev pkg-config zlib1g-dev')
YUM_PACKAGES = 'zlib-devel pcre-devel libmemcached-devel'

def YumInstall(vm):
  """Installs the memtier package on the VM."""
  vm.Install('build_tools')
  vm.InstallPackages(YUM_PACKAGES)
  vm.Install('wget')
  vm.RemoteCommand('wget {0} -P {1}'.format(LIBEVENT_URL, INSTALL_DIR))
  vm.RemoteCommand('cd {0} && tar xvzf {1}'.format(INSTALL_DIR,
                                                   LIBEVENT_TAR))
  vm.RemoteCommand('cd {0} && ./configure && sudo make install'.format(
      LIBEVENT_DIR))
  vm.RemoteCommand('git clone {0} {1}'.format(GIT_REPO, MEMTIER_DIR))
  vm.RemoteCommand('cd {0} && git checkout {1}'.format(MEMTIER_DIR, GIT_TAG))
  pkg_config = 'PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:${PKG_CONFIG_PATH}'
  vm.RemoteCommand('cd {0} && autoreconf -ivf && {1} ./configure && '
                   'sudo make install'.format(MEMTIER_DIR, pkg_config))

def AptInstall(vm):
  """Installs the memtier package on the VM."""
  vm.Install('build_tools')
  vm.InstallPackages(APT_PACKAGES)
  vm.RemoteCommand('git clone {0} {1}'.format(GIT_REPO, MEMTIER_DIR))
  vm.RemoteCommand('cd {0} && git checkout {1}'.format(MEMTIER_DIR, GIT_TAG))
  vm.RemoteCommand('cd {0} && autoreconf -ivf && ./configure && '
                   'sudo make install'.format(MEMTIER_DIR))

def _Uninstall(vm):
  """Uninstalls the memtier package on the VM."""
  vm.RemoteCommand('cd {0} && sudo make uninstall'.format(MEMTIER_DIR))

def YumUninstall(vm):
  """Uninstalls the memtier package on the VM."""
  _Uninstall(vm)

def AptUninstall(vm):
  """Uninstalls the memtier package on the VM."""
  _Uninstall(vm)
<file_sep># Copyright 2018 PerfKitBenchmarker Authors. All rights reserved.
#
# 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.
"""Module containing TensorFlow Serving installation functions.

  At the moment some of TensorFlow Serving is broken on the master branch
  (https://github.com/tensorflow/serving/issues/684), so this module builds
  the r1.4 from source.
"""
import posixpath
from perfkitbenchmarker import flags
from perfkitbenchmarker import vm_util
from perfkitbenchmarker.linux_packages import INSTALL_DIR

FLAGS = flags.FLAGS
VM_TMP_DIR = vm_util.VM_TMP_DIR

BAZEL_INSTALLER_URL = 'https://github.com/bazelbuild/bazel/releases/download/0.6.0/bazel-0.6.0-installer-linux-x86_64.sh'
TF_SERVING_BIN_DIRECTORY = posixpath.join(
    INSTALL_DIR, 'serving/bazel-bin/tensorflow_serving')
TF_SERVING_BASE_DIRECTORY = posixpath.join(INSTALL_DIR, 'serving')

def InstallBazel(vm):
  """Installs Bazel 0.6.0."""
  # TODO(ferneyhough): Consider moving this to its own package.
  basename = posixpath.basename(BAZEL_INSTALLER_URL)
  vm.RemoteCommand('cd {0} && wget {1}'.format(VM_TMP_DIR, BAZEL_INSTALLER_URL))
  vm.RemoteCommand('cd {0} && chmod +x {1}'.format(VM_TMP_DIR, basename))
  vm.RemoteCommand('cd {0} && sudo ./{1}'.format(
      VM_TMP_DIR, basename))  # This installs to /usr/local/bin

def BuildAndInstallPipPackage(vm):
  """Builds a TensorFlowServing pip package and install it on the vm.

  Currently this is only useful so that the clients can run python
  scripts that import tensorflow_serving. The server vms make no use
  of it.

  Args:
    vm: VM to operate on.
  """
  build_pip_package_tool = posixpath.join(
      TF_SERVING_BIN_DIRECTORY, 'tools/pip_package/build_pip_package')
  pip_package_output_dir = posixpath.join(VM_TMP_DIR, 'tf_serving_pip_package')
  pip_package = posixpath.join(pip_package_output_dir,
                               'tensorflow_serving_api-1.4.0-py2-none-any.whl')

  # The following command must be run from root of the tf serving build tree.
  vm.RemoteCommand('cd {0} && {1} {2}'.format(TF_SERVING_BASE_DIRECTORY,
                                              build_pip_package_tool,
                                              pip_package_output_dir))
  vm.RemoteCommand('sudo pip install {0}'.format(pip_package))

def BuildTfServing(vm):
  """Builds the Tensorflow Serving r1.4 from source."""
  vm.InstallPackages('git')
  vm.RemoteCommand('cd {0} && git clone -b r1.4 --recurse-submodules '
                   'https://github.com/tensorflow/serving'.format(INSTALL_DIR))
  # Run the configure script using default for all prompts.
  vm.RemoteCommand('cd {0} && yes "" | ./configure'.format(
      posixpath.join(TF_SERVING_BASE_DIRECTORY, 'tensorflow')))

  # Note: This took 45 minutes to build on an n1-standard-8 but is much
  # faster on an n1-standard-64.
  vm.RemoteCommand(
      'cd {0} && /usr/local/bin/bazel '
      'build -c opt tensorflow_serving/...'.format(TF_SERVING_BASE_DIRECTORY))

  BuildAndInstallPipPackage(vm)

def InstallFromSource(vm):
  """Downloads and builds Tensorflow Serving."""
  vm.InstallPackages('build-essential curl libcurl3-dev libfreetype6-dev '
                     'libpng12-dev libzmq3-dev pkg-config python-dev '
                     'python-numpy software-properties-common swig '
                     'zip zlib1g-dev')
  vm.RemoteCommand('sudo pip install grpcio')
  InstallBazel(vm)
  BuildTfServing(vm)

def AptInstall(vm):
  """Installs TensorFlowServing on the VM."""
  vm.Install('pip')
  vm.InstallPackages('python-numpy')
  InstallFromSource(vm)

def Uninstall(vm):
  """Uninstalls TensorFlow Serving on the VM."""
  del vm
<file_sep># Copyright 2014 PerfKitBenchmarker Authors. All rights reserved.
#
# 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.

"""Tests for beam_benchmark_helper."""

import unittest

from perfkitbenchmarker import beam_benchmark_helper

class BeamBenchmarkHelperTestCase(unittest.TestCase):

  def test_runner_option_override_use_override(self):
    testOptionVal = "TestVal"
    actual_options = []
    beam_benchmark_helper.AddRunnerPipelineOption(actual_options, None, testOptionVal)
    self.assertListEqual(["--runner=" + testOptionVal], actual_options)

  def test_runner_option_override_empty_override(self):
    testOptionVal = ""
    actual_options = []
    beam_benchmark_helper.AddRunnerPipelineOption(actual_options, None, testOptionVal)
    self.assertListEqual([], actual_options)

  def test_dataflow_runner_name_added(self):
    testOptionVal = "dataflow"
    actual_command = []
    beam_benchmark_helper.AddRunnerArgument(actual_command, testOptionVal)
    self.assertListEqual(["-DintegrationTestRunner=" + testOptionVal], actual_command)

  def test_direct_runner_name_added(self):
    testOptionVal = "direct"
    actual_command = []
    beam_benchmark_helper.AddRunnerArgument(actual_command, testOptionVal)
    self.assertListEqual(["-DintegrationTestRunner=" + testOptionVal], actual_command)

  def test_runner_name_empty(self):
    testOptionVal = ""
    actual_command = []
    beam_benchmark_helper.AddRunnerArgument(actual_command, testOptionVal)
    self.assertListEqual([], actual_command)

  def test_extra_property_empty_property(self):
    testOptionVal = ""
    actual_command = []
    beam_benchmark_helper.AddExtraProperties(actual_command, testOptionVal)
    self.assertListEqual([], actual_command)

  def test_extra_property_single_property(self):
    testOptionVal = "[key=value]"
    actual_mvn_command = []
    beam_benchmark_helper.AddExtraProperties(actual_mvn_command, testOptionVal)
    self.assertListEqual(["-Dkey=value"], actual_mvn_command)

  def test_extra_property_single_property_quoted(self):
    testOptionVal = "[\"key=value\"]"
    actual_mvn_command = []
    beam_benchmark_helper.AddExtraProperties(actual_mvn_command, testOptionVal)
    self.assertListEqual(["-Dkey=value"], actual_mvn_command)

  def test_extra_property_multiple_properties(self):
    testOptionVal = "[\"key=value\", \"key2=value2\"]"
    actual_mvn_command = []
    beam_benchmark_helper.AddExtraProperties(actual_mvn_command, testOptionVal)
    self.assertListEqual(["-Dkey=value", "-Dkey2=value2"], actual_mvn_command)

  def test_integrationPipelineOptions_rejection(self):
    testOptionVal = "[\"integrationTestPipelineOptions=...\"]"
    actual_mvn_command = []
    with self.assertRaises(ValueError):
      beam_benchmark_helper.AddExtraProperties(actual_mvn_command, testOptionVal)

  def test_hdfs_filesystem_addition(self):
    testOptionVal = "hdfs"
    actual_command = []
    beam_benchmark_helper.AddFilesystemArgument(actual_command, testOptionVal)
    self.assertListEqual(["-Dfilesystem=hdfs"], actual_command)

  def test_empty_filesystem(self):
    testOptionVal = ""
    actual_command = []
    beam_benchmark_helper.AddFilesystemArgument(actual_command, testOptionVal)
    self.assertListEqual([], actual_command)

  def test_add_module(self):
    testOptionVal = "sdks/java/io/tests"
    actual_command = []
    beam_benchmark_helper.AddModuleArgument(actual_command, testOptionVal)
    self.assertListEqual(['-p', testOptionVal], actual_command)

  def test_add_empty_module(self):
    testOptionVal = ""
    actual_command = []
    beam_benchmark_helper.AddModuleArgument(actual_command, testOptionVal)
    self.assertListEqual([], actual_command)

if __name__ == '__main__':
  unittest.main()
<file_sep># Copyright 2015 PerfKitBenchmarker Authors. All rights reserved.
#
# 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.

"""Tests for ntttcp_benchmark."""

import os
import unittest

from perfkitbenchmarker import sample
from perfkitbenchmarker import test_util
from perfkitbenchmarker.windows_packages import ntttcp

class NtttcpBenchmarkTestCase(unittest.TestCase, test_util.SamplesTestMixin):

  def setUp(self):
    self.maxDiff = None
    # Load data
    path = os.path.join(os.path.dirname(__file__),
                        '..', 'data',
                        'ntttcp_results.xml')
    with open(path) as fp:
      self.ntttcp_xml_results = fp.read()

  def testNtttcpParsing(self):
    extra_metadata = {}
    samples = ntttcp.ParseNtttcpResults(self.ntttcp_xml_results,
                                        extra_metadata)

    expected_metadata = {
        'async': 'False', 'bind_sender': 'False', 'cooldown_time': '15000',
        'dash_n_timeout': '10800000', 'max_active_threads': '2',
        'port': '5003', 'recv_socket_buff': '-1', 'run_time': '30000',
        'send_socket_buff': '8192', 'sync_port': 'False', 'udp': 'False',
        'use_ipv6': 'False', 'verbose': 'False', 'verify_data': 'False',
        'wait_all': 'False', 'warmup_time': '15000', 'wsa': 'False'
    }

    expected_thread_0_metadata = expected_metadata.copy()
    expected_thread_0_metadata['thread_index'] = '0'

    expected_thread_1_metadata = expected_metadata.copy()
    expected_thread_1_metadata['thread_index'] = '1'

    expected_samples = [
        sample.Sample('Total Throughput', 1990.541, 'Mbps',
                      expected_metadata),
        sample.Sample('Thread Throughput', 975.871, 'Mbps',
                      expected_thread_0_metadata),
        sample.Sample('Thread Throughput', 1014.669, 'Mbps',
                      expected_thread_1_metadata)]

    self.assertSampleListsEqualUpToTimestamp(expected_samples, samples)
<file_sep># Copyright 2015 PerfKitBenchmarker Authors. All rights reserved.
#
# 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.
"""Tests for tests.mock_flags."""

import copy
import unittest

from perfkitbenchmarker import flags
from tests import mock_flags

FLAGS = flags.FLAGS

flags.DEFINE_integer('test_flag', 0, 'Test flag.')

class MockFlagsTestCase(unittest.TestCase):

  def setUp(self):
    super(MockFlagsTestCase, self).setUp()
    self.flags = mock_flags.MockFlags()

  def testGetUnsetFlag(self):
    flag = self.flags['test_flag']
    self.assertFalse(flag.present)
    self.assertIsNone(flag.value)

  def testSetViaAttribute(self):
    self.flags.test_flag = 5
    self.assertEqual(self.flags.test_flag, 5)
    self.assertFalse(self.flags['test_flag'].present)
    self.assertEqual(self.flags['test_flag'].value, 5)

  def testSetViaItemAttribute(self):
    self.flags['test_flag'].value = 5
    self.assertFalse(self.flags['test_flag'].present)
    self.assertEqual(self.flags['test_flag'].value, 5)
    self.flags['test_flag'].present = True
    self.assertTrue(self.flags['test_flag'].present)
    self.assertEqual(self.flags['test_flag'].value, 5)

  def testSetViaParse(self):
    self.flags['test_flag'].parse(5)
    self.assertTrue(self.flags['test_flag'].present)
    self.assertEqual(self.flags['test_flag'].value, 5)

  def testCopy(self):
    copied_flags = copy.deepcopy(self.flags)
    copied_flags['test_flag'].parse(5)
    self.assertFalse(self.flags['test_flag'].present)
    self.assertIsNone(self.flags['test_flag'].value)
    self.assertTrue(copied_flags['test_flag'].present)
    self.assertEqual(copied_flags['test_flag'].value, 5)

class PatchFlagsTestCase(unittest.TestCase):

  def setUp(self):
    super(PatchFlagsTestCase, self).setUp()
    self.flags = mock_flags.MockFlags()

  def testGetFlag(self):
    self.flags['test_flag'].parse(5)
    with mock_flags.PatchFlags(self.flags):
      self.assertEqual(FLAGS.test_flag, 5)
      self.assertTrue(FLAGS['test_flag'].present)
      self.assertEqual(FLAGS['test_flag'].value, 5)
    self.assertEqual(FLAGS.test_flag, 0)
    self.assertFalse(FLAGS['test_flag'].present)
    self.assertEqual(FLAGS['test_flag'].value, 0)

  def testSetFlag(self):
    with mock_flags.PatchFlags(self.flags):
      FLAGS.test_flag = 5
      self.assertEqual(FLAGS.test_flag, 5)
      self.assertFalse(FLAGS['test_flag'].present)
      self.assertEqual(FLAGS['test_flag'].value, 5)
      FLAGS['test_flag'].present = True
      self.assertTrue(FLAGS['test_flag'].present)
      self.assertEqual(FLAGS['test_flag'].value, 5)
    self.assertEqual(self.flags.test_flag, 5)
    self.assertTrue(self.flags['test_flag'].present)
    self.assertEqual(self.flags['test_flag'].value, 5)
    self.assertEqual(FLAGS.test_flag, 0)
    self.assertFalse(FLAGS['test_flag'].present)
    self.assertEqual(FLAGS['test_flag'].value, 0)

  def testCopyPatchedFlags(self):
    with mock_flags.PatchFlags(self.flags):
      FLAGS.test_flag = 1
      copied_flags = copy.deepcopy(FLAGS)
      copied_flags.test_flag = 2
      self.assertEqual(FLAGS.test_flag, 1)
      self.assertEqual(self.flags.test_flag, 1)
      self.assertEqual(copied_flags.test_flag, 2)
    self.assertEqual(FLAGS.test_flag, 0)
    self.assertEqual(self.flags.test_flag, 1)
    self.assertEqual(copied_flags.test_flag, 2)

class PatchTestCaseFlagsTestCase(unittest.TestCase):

  def testGetFlag(self):
    self.assertEqual(FLAGS.test_flag, 0)
    flags = mock_flags.PatchTestCaseFlags(self)
    flags.test_flag = 5
    self.assertEqual(FLAGS.test_flag, 5)

  def testSetFlag(self):
    self.assertEqual(FLAGS.test_flag, 0)
    flags = mock_flags.PatchTestCaseFlags(self)
    FLAGS.test_flag = 5
    self.assertEqual(flags.test_flag, 5)

if __name__ == '__main__':
  unittest.main()
<file_sep># Copyright 2014 PerfKitBenchmarker Authors. All rights reserved.
#
# 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.

"""Tests for HPCC benchmark."""
import os
import unittest

import mock

from perfkitbenchmarker.linux_benchmarks import hpcc_benchmark

class HPCCTestCase(unittest.TestCase):

  def setUp(self):
    p = mock.patch(hpcc_benchmark.__name__ + '.FLAGS')
    p.start()
    self.addCleanup(p.stop)

    path = os.path.join(os.path.dirname(__file__), '../data', 'hpcc-sample.txt')
    with open(path) as fp:
      self.contents = fp.read()

  def testParseHpcc(self):
    benchmark_spec = mock.MagicMock()
    result = hpcc_benchmark.ParseOutput(self.contents, benchmark_spec)
    self.assertEqual(150, len(result))
    results = {i[0]: i[1] for i in result}
    self.assertAlmostEqual(0.0331844, results['HPL Throughput'])
    self.assertAlmostEqual(0.0151415, results['Random Access Throughput'])
    self.assertAlmostEqual(11.5032, results['STREAM Copy Throughput'])
    self.assertAlmostEqual(11.6338, results['STREAM Scale Throughput'])
    self.assertAlmostEqual(12.7265, results['STREAM Add Throughput'])
    self.assertAlmostEqual(12.2433, results['STREAM Triad Throughput'])
    self.assertAlmostEqual(0.338561, results['PTRANS Throughput'])

    # Spot check a few of the metrics without units.
    self.assertAlmostEqual(4, results['sizeof_float'])
    self.assertAlmostEqual(5.80539, results['StarSTREAM_Add'])

if __name__ == '__main__':
  unittest.main()
<file_sep># Copyright 2015 PerfKitBenchmarker Authors. All rights reserved.
#
# 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.

"""Module containing NTttcp installation and cleanup functions.

NTttcp is a tool made for benchmarking Windows networking.

More information about NTttcp may be found here:
https://gallery.technet.microsoft.com/NTttcp-Version-528-Now-f8b12769
"""

import ntpath
import xml.etree.ElementTree

from perfkitbenchmarker import background_tasks
from perfkitbenchmarker import flags
from perfkitbenchmarker import sample
from perfkitbenchmarker import vm_util

FLAGS = flags.FLAGS

flags.DEFINE_integer('ntttcp_threads', 1,
                     'The number of client and server threads for NTttcp '
                     'to run with.')

flags.DEFINE_integer('ntttcp_time', 60,
                     'The number of seconds for NTttcp to run.')

CONTROL_PORT = 6001
BASE_DATA_PORT = 5001
NTTTCP_RETRIES = 10
NTTTCP_DIR = 'NTttcp-v5.33'
NTTTCP_ZIP = NTTTCP_DIR + '.zip'
NTTTCP_URL = ('https://gallery.technet.microsoft.com/NTttcp-Version-528-'
              'Now-f8b12769/file/159655/1/' + NTTTCP_ZIP)

def Install(vm):
  """Installs the NTttcp package on the VM."""
  zip_path = ntpath.join(vm.temp_dir, NTTTCP_ZIP)
  vm.DownloadFile(NTTTCP_URL, zip_path)
  vm.UnzipFile(zip_path, vm.temp_dir)

def _RunNtttcp(vm, options):
  timeout_duration = 3 * FLAGS.ntttcp_time
  ntttcp_exe_dir = ntpath.join(vm.temp_dir, 'x86fre')
  command = 'cd {ntttcp_exe_dir}; .\\NTttcp.exe {ntttcp_options}'.format(
      ntttcp_exe_dir=ntttcp_exe_dir, ntttcp_options=options)
  vm.RemoteCommand(command, timeout=timeout_duration)

@vm_util.Retry(max_retries=NTTTCP_RETRIES)
def RunNtttcp(sending_vm, receiving_vm, receiving_ip_address, ip_type):
  """Run NTttcp and return the samples collected from the run."""

  shared_options = '-xml -t {time} -p {port} '.format(time=FLAGS.ntttcp_time,
                                                      port=BASE_DATA_PORT)

  sending_options = shared_options + '-s -m \'{threads},*,{ip}\''.format(
      threads=FLAGS.ntttcp_threads, ip=receiving_ip_address)
  receiving_options = shared_options + '-r -m \'{threads},*,0.0.0.0\''.format(
      threads=FLAGS.ntttcp_threads)

  ntttcp_exe_dir = ntpath.join(sending_vm.temp_dir, 'x86fre')

  # NTttcp will append to the xml file when it runs, which causes parsing
  # to fail if there was a preexisting xml file. To be safe, try deleting
  # the xml file.
  rm_command = 'cd {ntttcp_exe_dir}; rm xml.txt'.format(
      ntttcp_exe_dir=ntttcp_exe_dir)
  sending_vm.RemoteCommand(
      rm_command, ignore_failure=True, suppress_warning=True)

  process_args = [(_RunNtttcp, (sending_vm, sending_options), {}),
                  (_RunNtttcp, (receiving_vm, receiving_options), {})]

  background_tasks.RunParallelProcesses(process_args, 200)

  cat_command = 'cd {ntttcp_exe_dir}; cat xml.txt'.format(
      ntttcp_exe_dir=ntttcp_exe_dir)
  stdout, _ = sending_vm.RemoteCommand(cat_command)

  metadata = {'ip_type': ip_type}
  for vm_specifier, vm in ('receiving', receiving_vm), ('sending', sending_vm):
    for k, v in vm.GetResourceMetadata().iteritems():
      metadata['{0}_{1}'.format(vm_specifier, k)] = v

  return ParseNtttcpResults(stdout, metadata)

def ParseNtttcpResults(xml_results, metadata):
  """Parses the xml output from NTttcp and returns a list of samples.

  The list of samples contains total throughput and per thread throughput
  metrics (if there is more than a single thread).

  Args:
    xml_results: ntttcp test output.
    metadata: metadata to be included as part of the samples.

  Returns:
    list of samples from the results of the ntttcp tests.
  """
  root = xml.etree.ElementTree.fromstring(xml_results)
  samples = []
  metadata = metadata.copy()

  for element in root.findall('parameters/*'):
    if element.tag and element.text:
      metadata[element.tag] = element.text

  # TODO(ehankland): There is more interesting metadata that we can
  # extract from the xml file such as the number of retransmits and
  # cpu usage.

  throughput_element = root.find('./throughput[@metric="mbps"]')
  samples.append(sample.Sample(
      'Total Throughput', float(throughput_element.text), 'Mbps', metadata))

  thread_elements = root.findall('./thread')
  if len(thread_elements) > 1:
    for element in thread_elements:
      throughput_element = element.find('./throughput[@metric="mbps"]')
      metadata = metadata.copy()
      metadata['thread_index'] = element.attrib['index']
      samples.append(sample.Sample('Thread Throughput',
                                   float(throughput_element.text),
                                   'Mbps',
                                   metadata))
  return samples
<file_sep># Copyright 2015 PerfKitBenchmarker Authors. All rights reserved.
#
# 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.
"""Class for mocking a FlagValues object."""

import contextlib

from perfkitbenchmarker import flag_util
from perfkitbenchmarker import flags

FLAGS = flags.FLAGS

class _MockFlag(object):
  """Mock version of a Flag object.

  Attributes:
    present: boolean. In the original Flag object, indicates whether the flag
        was provided a value by the user (in the case of PKB, either via the
        command-line flags or via the benchmark-specific YAML config flag
        overrides).
    validators: Empty tuple. FlagValues.__setattr__ invokes a real Flag's
        validators to validate the new value. When the FlagValues internal
        flag dict is substituted with a _MockFlagDict, this attribute must be
        present for FlagValues.__setattr__ to work, but because it is empty, no
        actual validation occurs.
    value: In the original Flag object, it is either the flag's default value or
        the user-provided value.
  """

  def __init__(self):
    self.present = False
    self.validators = ()
    self.value = None

  def parse(self, argument):
    self.present = True
    self.value = argument

class _MockFlagDict(dict):
  """Mock version of the internal dictionary of a FlagValues object.

  Typically, the internal dictionary of a FlagValues object maps each flag name
  string to a Flag object. This mock maps each flag name to a _MockFlag object
  that is created upon first access.

  Because FlagValues and MockFlags override __getattr__ to search their flag
  dictionaries, care is taken not to create a _MockFlag when searching for
  special attributes like the __copy__ method.
  """

  def __getitem__(self, key):
    if (not super(_MockFlagDict, self).__contains__(key) and
        not key.startswith('__')):
      self[key] = _MockFlag()
    return super(_MockFlagDict, self).__getitem__(key)

  def __contains__(self, item):
    if item.startswith('__'):
      return super(_MockFlagDict, self).__contains__(item)
    return True

class MockFlags(object):
  """Class for mocking a FlagValues object.

  Supports setting a flag value via __setattr__, getting a flag value via
  __getattr__, and getting a _MockFlag via __getitem__.
  """

  def __init__(self):
    super(MockFlags, self).__setattr__('_dict', _MockFlagDict())

  def FlagDict(self):
    return self._dict

  def __setattr__(self, key, value):
    self.FlagDict()[key].value = value

  def __getattr__(self, key):
    flag = self.FlagDict().get(key)
    return flag.value if flag else super(MockFlags, self).__getattr__(key)

  def __getitem__(self, key):
    return self.FlagDict()[key]

  def __contains__(self, item):
    return item in self.FlagDict()

@contextlib.contextmanager
def PatchFlags(mock_flags=None):
  """Patches read and write access to perfkitbenchmarker.flags.FLAGS.

  By patching the underlying FlagValues instance, this method affects all
  modules that have read FLAGS from perfkitbenchmarker.flags. For example, a
  module my_module.py may have the code
      from perfkitbenchmarker import flags
      FLAGS = flags.FLAGS
      ...
      def Func():
        my_flag = FLAGS['cloud']
        my_value = FLAGS.cloud
        FLAGS.cloud = my_override_value
  Within the effect of the PatchFlags contextmanager, calling my_module.Func()
  will cause my_flag and my_value to be initialized from mock_flags rather than
  an actual FlagValues instance. Similarly, mock_flags.cloud will be set with
  my_override_value.

  Args:
    mock_flags: None or MockFlags. If provided, the source of mocked flag
        values. If not provided, a new MockFlags object will be used.

  Yields:
    MockFlags. Either mock_flags or the newly created MockFlags value.
  """
  mock_flags = mock_flags or MockFlags()
  with flag_util.FlagDictSubstitution(FLAGS, mock_flags.FlagDict):
    yield mock_flags

def PatchTestCaseFlags(testcase):
  """Patches access to perfkitbenchmarker.flags.FLAGS for a TestCase.

  Similar to PatchFlags, but only needs to be called once during a test method
  or its setUp method, and remains in effect for the rest of the test method.

  Args:
    testcase: unittest.TestCase. The current test. A cleanup method is
        registered to undo the patch after this test completes.

  Returns:
    MockFlags. The mocked FlagValues object.
  """
  mock_flags = MockFlags()
  substitution = flag_util.FlagDictSubstitution(FLAGS, mock_flags.FlagDict)
  substitution.__enter__()
  testcase.addCleanup(substitution.__exit__)
  return mock_flags

repo_name: markflyhigh/PerfKitBenchmarker


text:
<file_sep>/**
 *
 */
package com.existential_crisis;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.List;

class existentialcrisis_testcase {
	private dreadCollection dc;
	private dread s1;
	private dread s2;
	private dread s3;
	private dread s4;
	private final int DREAD_COLLECTION_SIZE = 4;

	/**
	 * @throws java.lang.Exception
	 */
	@BeforeEach
	void setUp() throws Exception {
		//Arrange
		dc = new dreadCollection();
		s1 = new dread("0001","I think if we were to truly create a utopian society, the first thing we would do to tear it down, just to have a purpose.");
		s2 = new dread("0002","It is closer to the year 2030 than the year 2005.");
		s3 = new dread("0003","At some point in your life, you will be the next person on Earth to die.");
		s4 = new dread("0004","Of all the consciences that could have been born in my body, I'm the one looking through these eyes.");

		dc.addThought(s1);
		dc.addThought(s2);
		dc.addThought(s3);
		dc.addThought(s4);

	}

	/**
	 * @throws java.lang.Exception
	 */
	@AfterEach
	void tearDown() throws Exception {
	}

	/**
	 * Test method for {@link com.existential_crisis.dreadCollection#getThought()}.
	 */
	@Test
	void testGetThought() {
		//Act
		List<dread> testDc = dc.getThought();

		//Assert
		assertTrue(!testDc.isEmpty());

		//Assert
		assertEquals(testDc.size(), DREAD_COLLECTION_SIZE);
	}

	/**
	 * Test method for {@link com.existential_crisis.dreadCollection#addThought(com.existential_crisis.dread)}.
	 */
	@Test
	void testAddThought() {
		dread s5 = new dread("0005","I am no longer sure of anything. If I satiate my desires, I sin but I deliver myself from them; if I refuse to satisfy them, they infect the whole soul.");
		dc.addThought(s5);
		List<dread> testDc = dc.getThought();
		int afterAddSize = DREAD_COLLECTION_SIZE + 1;
		assertEquals(testDc.size(), afterAddSize);
	}

	/**
	 * Test method for {@link com.existential_crisis.dreadCollection#findThoughtsById(java.lang.String)}.
	 */
	@Test
	void testFindThoughtsById() {
		dread findId = dc.findThoughtsById("0003");
		assertEquals("0003",findId.getId());
	}

	/**
	 * Test method for {@link com.existential_crisis.dreadCollection#findThoughtsByName(java.lang.String)}.
	 */
	@Test
	void testFindThoughtsByName() {
		dread findName = dc.findThoughtsByName("It is closer to the year 2030 than the year 2005.");
		assertEquals("It is closer to the year 2030 than the year 2005.",findName.getThought());
	}

}

branch_name: refs/heads/master

repo_language: Java


text:
<repo_name>CareGuide/ramparts<file_sep>/spec/data/email_and_phone_data/falsy_email_and_phone_data.rb
# frozen_string_literal: true

EMAIL_PHONE_FALSY_BLOCKS = [
  "I need a babysitter and errand for my son textme direct on my number if you are interested",
  "I think that we would be a good match. shoot me a message"
].freeze
<file_sep>/spec/data/email_data/falsy_email_data.rb
# frozen_string_literal: true

EMAIL_FALSY_BLOCKS = [
  "I need a babysitter and errand for my son textme direct on my number if you are interested 3.2.3.4.3.8.4.8.3.8",
  "I think that we would be a good match. shoot me a message"
].freeze
<file_sep>/spec/data/url_data/truthy_url_data.rb
# frozen_string_literal: true

URL_TRUTHY = [
  {
    matches: ["cialis", "cialis", "cialis", "cialis", "cialis", "cialis", "cialis"],
    text: "cialis vs cialis spam guestbook.php?action=http://cialiswalmart.shop - cialis over the counter at walmart trimix for ed cialis over the counter at walmart- cialis from canada pharmacy this page has had cialis dongguk gallery"
  },
  {
    matches: ["viagra", "viagra", "viagra", "viagra", "viagra", "viagra", "viagra", "viagra"],
    text: "risk viagra http://viagrawithoutdoctorusa.net - viagra without a doctor prescription usa viagra tadalafil gaestebuch.htmlviagra without a doctor prescription viagra you cannot reply to topics in this forum http:juki.host-page.com4083buy viagra generic and brand.htmldiscount-viagra"
  }
].freeze
<file_sep>/Gemfile
# frozen_string_literal: true

source 'http://rubygems.org'

group :test do
  gem 'rspec'
  gem 'rubocop'
  gem 'simplecov', :require => false
end
<file_sep>/lib/ramparts/parsers/email_parser.rb
# frozen_string_literal: true

require_relative '../data/list_of_email_domains'
require_relative '../helpers'

# Parses text and attempts to locate email
class EmailParser
  # Counts email occurrences within a block of text
  # Note: Uses map reduce algorithm
  def count_email_instances(text, options)
    raise ArgumentError, ARGUMENT_ERROR_TEXT unless text.is_a? String

    text = parse_email(text)
    email_instances(MR_ALGO, text, options).length
  end

  # Replaces the occurrences of email within the block of text with an insertable
  def replace_email_instances(text, options, &block)
    raise ArgumentError, ARGUMENT_ERROR_TEXT unless text.is_a? String

    instances = find_email_instances(text, options)
    replace(text, instances.reverse!, &block)
  end

  # Fins the occurrences of emails within a block of text and returns their positions
  def find_email_instances(text, options)
    raise ArgumentError, ARGUMENT_ERROR_TEXT unless text.is_a? String

    text = text.downcase
    email_instances(GR_ALGO, text, options)
  end

  private

  # Matches a certain string of text allowed in emails
  TEXT_MATCH = 'a-z0-9._%+-'

  # rubocop:disable LineLength

  # Regex to find the emails, must have .com or something similar to match
  GR_REGEX = Regexp.new(/(([#{TEXT_MATCH}]{1}[^\w]{1})+|([#{TEXT_MATCH}])+)([^\w]*@[^\w]*){1}[a-z0-9.-]+((\.|[^\w]+(dot){1}[^\w]+){1}[a-z]{2,})+/)
  # Regex to find the emails, must have .com or something similar to match and also checks for the word 'at' as '@'
  GR_REGEX_WITH_AT = Regexp.new(/(([#{TEXT_MATCH}]{1}[^\w]{1})+|([#{TEXT_MATCH}])+)([^\w]+(at){1}[^\w]+|[^\w]*@[^\w]*){1}[a-z0-9.-]+((\.|[^\w]+(dot){1}[^\w]+){1}[a-z]{2,})+/)
  # Regex to find the emails, does .com or something similar to match
  GR_REGEX_WITHOUT_DOT = Regexp.new(/(([#{TEXT_MATCH}]{1}[^\w]{1})+|([#{TEXT_MATCH}])+)([^\w]+(at){1}[^\w]+|[^\w]*@[^\w]*){1}[a-z0-9.-]+([^\w]*\.[^\w]*|[^\w]+(dot){1}[^\w]+)?([a-z]{2,})?/)

  # rubocop:enable LineLength

  # Regex to find emails for MapReduce, must have .com or something similar to match
  MR_REGEX = Regexp.new(/[a-z0-9._%+-]+\${,2}@{1}\${,2}[a-z0-9.-]+\${,2}(\.){1}[a-z]{2,}/)
  # Regex to find emails for MapReduce, does not have to have .com or something similar to match
  MR_REGEX_WITHOUT_DOT = Regexp.new(/[a-z0-9._%+-]+\${,2}@{1}\${,2}[a-z0-9.-]+/)

  # Map these occurences down to their constituent parts
  REPLACEMENTS = {
    ' at ' => '@',
    '(at)' => '@',
    ' dot ' => '.'
  }.freeze

  # Parses the email and maps down certain occurrences
  def parse_email(text)
    text.downcase.gsub(/\ at\ |\(at\)|\ dot\ /, REPLACEMENTS).gsub(/[^\w\@\.\_\%\+\-]/, '$')
  end

  def email_instances(algo, text, options)
    # Determines which algorithm to use
    regex = algo == MR_ALGO ? MR_REGEX : GR_REGEX
    regex_without_dot = algo == MR_ALGO ? MR_REGEX_WITHOUT_DOT : GR_REGEX_WITHOUT_DOT
    regex_with_at = GR_REGEX_WITH_AT

    instances = []
    if options.fetch(:aggressive, false)
      temp_instances = scan(text, regex_without_dot, :email)

      # Since this is the aggressive option where '.com' or similar isn't needed
      # Check to make sure the last word of the string is a domain
      temp_instances.each do |instance|
        instances << instance if EMAIL_DOMAINS.any? { |domain| instance[:value].split('@')[1]&.include? domain }
      end
    elsif options.fetch(:check_for_at, false)
      instances = scan(text, regex_with_at, :email)
    else
      instances = scan(text, regex, :email)
    end
    instances
  end
end
<file_sep>/lib/ramparts/helpers.rb
# frozen_string_literal: false

ARGUMENT_ERROR_TEXT = 'Parameter 1, the block of text to parse, is not a string'.freeze

# The map reduce (MR) algorithm. Faster by ~2x than the other algorithm.
# Maps parts of the text such as 'at' or 'FOUR' down to '@' and '4'
# removes spaces etc, and then runs a simple regex over the remainder
# Information loss occurs and hence it can't return indices
MR_ALGO = 'MR'.freeze

# The glorified regex (GR) algorithm.
# An obtuse and yet heartily strong regex that does a single pass over
# the text. Since the regex is so complicated and robust - it is slower
# than the map reduce algorithm. No information loss occurs
# so we can return indices of where the phone numbers and etc. exist
GR_ALGO = 'GR'.freeze

# Given some text it replaces each matched instance with the given insertable
def replace(text, instances, &block) # rubocop:disable Lint/UnusedMethodArgument
  altered_text = String.new(text)

  instances.map do |instance|
    insertable = yield instance
    altered_text[instance[:start_offset]...instance[:end_offset]] = insertable
  end
  altered_text
end

# Given some text it scans the text with the given regex for matches
def scan(text, regex, type)
  text
    .enum_for(:scan, regex)
    .map do
      {
        start_offset: Regexp.last_match.begin(0),
        end_offset: Regexp.last_match.begin(0) + Regexp.last_match.to_s.length,
        value: Regexp.last_match.to_s,
        type: type
      }
    end
end

# Check if two ranges overlap
def ranges_overlap?(r1, r2)
  r1.cover?(r2.first) || r2.cover?(r1.first)
end
<file_sep>/CHANGELOG.md
# Change Log

## 0.3.1 (09/10/2018)
- Fix long-running regex match

## 0.2.1 (14/12/2017)
- Creating a `spec_helper.rb` and implement SimpleCov tool
- Refactored test architecture to use hashes instead of arrays
- Reached 100% code coverage

## 0.2.0 (12/12/2017)
- Implementation of multi functions that allows parsing of both email and phone in same method

## 0.1.0 (09/12/2017)
- Implementation of all basic functions for emails, urls, and phone numbers
- Initial draft release

## 0.0.4 (08/12/2017)
- Use Ruby that's already installed on TravisCI
- Implement [Stale](https://github.com/probot/stale) for issue
- Add error messages, especially for malformed input
<file_sep>/spec/data/phone_data/falsy_phone_data.rb
# frozen_string_literal: true

PHONE_FALSY_BLOCKS = [
  "Hi I have a four year old who is oh so sweet",
  "Hi my name is <NAME>!"
].freeze
<file_sep>/spec/parsers/phone_parser_spec.rb
# frozen_string_literal: true

require_relative '../data/phone_data/truthy_phone_data'
require_relative '../data/phone_data/falsy_phone_data'

describe '#count_phone_numbers' do
  it 'parses a number of positive test blocks correctly' do
    test_truthy_count(PHONE_TRUTHY_WITH_ANSWERS, :count_phone_numbers)
  end

  it 'parses a number of positive test blocks correctly with parse_leet option' do
    test_truthy_count(PHONE_TRUTHY_WITH_ANSWERS, :count_phone_numbers, parse_leet: true)
  end

  it 'parses a number of spaced positive test blocks correctly with remove_spaces option' do
    test_truthy_count(PHONE_TRUTHY_WITH_ANSWERS_AND_SPACES, :count_phone_numbers, remove_spaces: true)
  end

  it 'parses a number of positive test blocks correctly with remove_spaces and parse_leet option' do
    test_truthy_count(PHONE_TRUTHY_WITH_ANSWERS, :count_phone_numbers, parse_leet: true, remove_spaces: true)
  end

  it 'parses a number of negative test blocks correctly' do
    test_falsy_count(PHONE_FALSY_BLOCKS, :count_phone_numbers)
  end

  it 'parses a number of negative test blocks correctly with all the options' do
    test_falsy_count(PHONE_FALSY_BLOCKS, :count_phone_numbers, parse_leet: true, remove_spaces: true)
  end
end

describe '#find_phone_numbers' do
  it 'parses a number of positive test blocks correctly with glorified regex' do
    test_truthy_finds(PHONE_TRUTHY_WITH_ANSWERS, :find_phone_numbers)
  end

  it 'parses a number of positive test blocks correctly' do
    test_truthy_finds(PHONE_TRUTHY_WITH_ANSWERS_AND_SPACES, :find_phone_numbers)
  end

  it 'parses a number of negative test blocks correctly with glorified regex' do
    test_falsy_finds(PHONE_FALSY_BLOCKS, :find_phone_numbers)
  end
end

describe '#replace_phone_numbers' do
  it 'replaces a number of positive test blocks correctly with phone replacer' do
    test_replacements(PHONE_TRUTHY_WITH_ANSWERS, :replace_phone_numbers)
  end
end

describe 'Map/Reduce to Regex Run Time' do
  it 'times the two methods against each other' do
    compare_run_times(PHONE_TRUTHY_WITH_ANSWERS, :count_phone_numbers, :find_phone_numbers)
  end
end
<file_sep>/spec/data/email_and_phone_data/truthy_email_and_phone_data.rb
# frozen_string_literal: true

require_relative '../../spec_constants'

# Please place phone number answers first for testing
# It shouldn't matter if we implemented stronger test matchers
EMAIL_PHONE_TRUTHY_WITH_ANSWERS = [
  {
    matches: ["<EMAIL>"],
    text: "My name is Cynthia, a friend of mine needs a nanny to watch her baby in your area, her contact is ( <EMAIL> ) She will be waiting to hear from you kindly send her an email now!",
    filtered: "My name is Cynthia, a friend of mine needs a nanny to watch her baby in your area, her contact is ( #{INSERTABLE} ) She will be waiting to hear from you kindly send her an email now!"
  },
  {
    matches: ["216.555.FOUR FIVE EIGHT NINE", "<EMAIL>"],
    text: "My name is Cynthia, a friend of mine needs a nanny to watch her baby in your area, her contact is ( <EMAIL> ) or 216.555.FOUR FIVE EIGHT NINE!",
    filtered: "My name is Cynthia, a friend of mine needs a nanny to watch her baby in your area, her contact is ( #{INSERTABLE} ) or #{INSERTABLE}!"
  },
  {
    matches: ["432-555-5454", "<EMAIL>"],
    text: "You can contact me at <EMAIL>, or call me at 432-555-5454. Please get in touch.",
    filtered: "You can contact me at #{INSERTABLE}, or call me at #{INSERTABLE}. Please get in touch."
  },
  {
    matches: ["416-555-5454", "<EMAIL>"],
    text: "You can contact me at <EMAIL>, or call me at 416-555-5454. Please get in touch.",
    filtered: "You can contact me at #{INSERTABLE}, or call me at #{INSERTABLE}. Please get in touch."
  },
  {
    matches: ["416-555-5454", "<EMAIL>"],
    text: "You can contact me at <EMAIL>, or call me at 416-555-5454. Please get in touch.",
    filtered: "You can contact me at #{INSERTABLE}, or call me at #{INSERTABLE}. Please get in touch."
  }
].freeze
<file_sep>/lib/ramparts/data/list_of_email_domains.rb
# frozen_string_literal: true

EMAIL_DOMAINS = %w[
  gmail
  yahoo
  hotmail
  aol
  icloud
  live
  outlook
  ymail
  comcast
  shaw
  rogers
  msn
  mail
  me
  att
  careguide
  sbcglobal
  rocketmail
  telus
  sympatico
  cox
  gmai
  email
  aim
  yandex
  gamil
  gmx
  student
  students
  earthlink
  gnail
  juno
  gmsil
  netzero
  ail
  gmil
  gmal
  hmail
  yaho
  alumni
  gmial
  googlemail
  tampabay
  mtroyal
  usa
  cfl
  yshoo
  protonmail
  rediffmail
  liberty
  maine
  inbox
  optimum
  example
  yhaoo
  yorku
  mchsi
  yahoi
  zoho
  hushmail
  libero
  hotmal
  ukr
  wowway
  post
  lycos
  yaboo
  contractor
  yahool
].freeze
<file_sep>/CONTRIBUTING.md
# Contributing

Everyone is welcome to contribute to Ramparts. Contributing doesn’t just mean submitting pull requests—there are many different ways for you to get involved, including answering questions, reporting or triaging [issues](https://github.com/CareGuide/ramparts/issues), et al.

No matter how you want to get involved, we ask that you be kind, and treat others on the project with respect.

We love pull requests. We'd like to at least comment on, if not
accept, pull requests within a few days. We may suggest some changes or improvements or alternatives.

Some things that will increase the chance that your pull request is accepted:

* Make sure the tests pass (this includes linting)
* Update the documentation: code comments, example code, guides. Basically,
  update everything affected by your contribution.
* Include any information that would be relevant to reproducing bugs, use cases for new features, etc.
* If the change does break compatibility, how can it be updated to become backwards compatible, while directing users to the new way of doing things?
* A suitable and well thought throught commit message

# Branch Naming

Please follow the following naming convention for branch names. Use `-` to separate words.

- Use `feature/...` for feature related changes
- Use `fix/...` for changes that fix a bug
- Use `refactor/...` for general refactors of the code (eg. cleaning the code, adding comments)
- Finally use `update/...` for general updates that aren't refactors or bug fixes but aren't major enough to fall under features

# Testing

Run linting tests on your branch simply by typing `rubocop` when within the top level directory

Run general unit tests simply by typing `rspec` when within the top level directory

When writing tests please have the [first three digits](https://en.wikipedia.org/wiki/555_(telephone_number)) (not the area code) of phone numbers as `555` (or the phonetic/l33t equivalent) to avoid collisions with actual phone numbers

Please also use `example` for the domain of test email addresses for a similar reason

# Stale issue and pull request policy

Issues and pull requests have a shelf life and sometimes they are no longer relevant. All issues and pull requests that have not had any activity for 60 days will be marked as `stale`. Simply leave a comment with information about why it may still be relevant to keep it open. If no activity occurs in the next 7 days, the issue will be automatically closed. Stale PR's will be closed manually.

The goal of this process is to keep the list of open issues and pull requests focused on work that is actionable and important for the maintainers and the community.

# Pull Request Reviews & releasing

Once pull request has been given approval, leadership will realease and deploy the gem (See [Roadmap](https://github.com/CareGuide/ramparts/blob/master/ROADMAP.md)) for automatic deploys)<file_sep>/README.md
# Ramparts - Spam Detection ![Build Status](https://travis-ci.com/CareGuide/ramparts.svg?token=<KEY>&branch=master) [![Maintainability](https://api.codeclimate.com/v1/badges/5b5bcd41603e34dbc615/maintainability)](https://codeclimate.com/github/CareGuide/ramparts/maintainability) [![Gem Version](https://badge.fury.io/rb/ramparts.svg)](http://badge.fury.io/rb/ramparts)

Parses blocks of text to find phone numbers (including phonetic numbers), emails, and spammer urls

## Example

Find obfuscated phone numbers

```
>> message = "Contact me directly ( FOUR ONE FIVE E I G H T 9 FOUR TWO EIGHT SIX FIVE  ). Hope you cracked that number code."
>> Ramparts.find_phone_numbers(message)
[{start_offset: 22, end_offset: 71, type: :phone, value: 'FOUR ONE FIVE E I G H T 9 FOUR TOO EIGHT SIX FIVE'}]
```

Find obfuscated emails.

```
>> message = "Looking for honest worker .. contact ashley73299 AT yahoo dot com for more info"
>> Ramparts.find_emails(message)
[{start_offset: 37, end_offset: 65, type: :email, value: 'ashley73299 AT yahoo dot com'}]
```

Find both obfuscated emails and phone numbers.

```
>> message = "Looking for honest worker .. contact ashley73299 AT yahoo dot com or FOUR FIVE ONE 456 8900 for more info"
>> Ramparts.find_phone_numbers_and_emails(message)
[{start_offset: 37, end_offset: 65, type: :email, value: 'ashley73299 AT yahoo dot com'}, {start_offset: 70, end_offset: 92, type: :phone, value: 'FOUR FIVE ONE 456 8900'}]
```

Count the occurrences of well known spam URLs and keywords

```
>> message = ""cialis vs viagra spam guestbook.php?action=http://cialiswalmart.shop""
>> Ramparts.count_urls(message)
3
```
## Installation

In the root directory of your project
```
gem install ramparts
```
Remember to require `ramparts` as necessary
```
require 'ramparts'
```

## API

#### count_phone_numbers(text, options = {})
- Returns the count of the number of phone numbers in the text. Currently uses a map reduce paradigm,
  which incurs information loss but is cleaner to implement, achieves better results, and is
  **~2x faster** than `find_phone_numbers`
- **Input:**
    - text **[String]**
    - options **[Hash]**
        - parse_leet **[Boolean][Default → True]**
            - Parses phone numbers that contain l33t syntax. With this set to true eg. `FivE 4 3 F0r On3 67 NiN3` would be caught.
        - remove_spaces **[Boolean][Default → True]**
            - Parses phone numbers that contain spaces between the numbers. With this set to true eg. `F i v E 4 3 F 0 r O n 3 67 N i N 3` would be caught.
- **Output:**
    - number of occurrences of phone numbers **[Integer]**
- **Example**
    - **Input:**
        - text → `"If you're interested in this position, do contact me directly on my phone number ( FOUR ONE FIVE E I G H T 9 FOUR TWO EIGHT SIX FIVE  ). Hope you cracked that number code."`
    - **Output:** `1`

#### find_phone_numbers(text, options = {})
- **Description:** Finds all occurrences of emails within a block of text. Even when l33t speak, phonetics and
space variations are used.
- **Input:**
    - text **[String]**
    - options **[Hash]**
        - To Be Implemented
- **Output:**
    - **[Array]**
        - match **[Hash]**
            - offset: **[Integer]**
            - value: **[String]**
- **Example**
    - **Input:**
        - text → `"If you're interested in this position, do contact me directly on my phone number ( FOUR ONE FIVE E I G H T 9 FOUR TWO EIGHT SIX FIVE  ). Hope you cracked that number code."`
    - **Output:** `[{start_offset: 84, end_offset: 133, type: :phone, value: 'FOUR ONE FIVE E I G H T 9 FOUR TOO EIGHT SIX FIVE'}]`

#### replace_phone_numbers(text, options = {}, &block)
- **Description:** Replaces all the occurrences of phone numbers within the text with what is returned in the block. Returns the redacted text.
of text.
- **Input:**
    - text **[String]**
    - insertable **[String]**
    - options **[Hash]**
        - To Be Implemented
- **Output:**
    - updated text **[String]**
- **Example**
    - **Usage:** `altered_text = replace_phone_numbers(...) do CENSORED end`
    - **Input:**
        - text → `"If you're interested in this position, do contact me directly on my phone number ( FOUR ONE FIVE E I G H T 9 FOUR TWO EIGHT SIX FIVE  ). Hope you cracked that number code."`
    - **Output:** `"If you're interested in this position, do contact me directly on my phone number ( CENSORED  ). Hope you cracked that number code."`

#### count_emails(text, options = {})
- **Description:** Returns the count of the number of emails in the text. Currently uses a map reduce paradigm,
 which incurs information loss but is cleaner to implement, achieves better results, and is **~2x faster**
 than `find_emails`
 - **Input:**
     - text **[String]**
     - options **[Hash]**
         - aggressive **[Boolean] [Default → `False`]**
            - doesn't require a `.` or `dot` + a TLD at the end, but instead compares the last word against a well known list of email domains (eg. `contact ashley @ yandex for more info` would be caught)
 - **Output:**
     - number of occurences of emails **[Integer]**
 - **Example**
     - **Input:**
         - text → `"Hi, Are you seriously interested ..Looking for honest worker .. My e-mail is ashley73299 AT yahoo dot com, I repeat ashley73299 @ yahoo . com ?.. Ashley"`
     - **Output:** `2`

#### find_emails(text, options = {})
- **Description:** Finds all occurrences of emails within a block of text. Even when l33t speak, phonetics are used.
- **Input:**
    - text **[String]**
    - options **[Hash]**
        - aggressive **[Boolean] [Default → `False`]**
            - doesn't require a `.` or `dot` + a TLD at the end, but instead compares the last word against a well known list of email domains (eg. `contact ashley @ yandex for more info` would be caught)
        - check_for_at **[Boolean] [Default → `False`]**
            - checks for the word 'at' as '@', currently can result in algorithm being overly greedy as 'at' is such a common word
- **Output:**
    - **[Array]**
        - match **[Hash]**
            - offset: **[Integer]**
            - value: **[String]**
- **Example**
    - **Input:**
        - text → `"Hi, Are you seriously interested ..Looking for honest worker .. My e-mail is ashley73299 AT yahoo dot com, I repeat ashley73299 @ yahoo . com ?.. Ashley"`
    - **Output:** `[{start_offset: 78, end_offset: 106, type: :email, value: 'ashley73299 AT yahoo dot com'}, {start_offset: 118, end_offset: 143, type: :email, value: 'ashley73299 @ yahoo . com'}]`

#### replace_emails(text, options = {}, &block)
- **Description:** Replaces all the occurrences of emails within the text with what is returned in the block. Returns the redacted text
of text.
- **Input:**
    - text **[String]**
    - options **[Hash]**
         - aggressive **[Boolean] [Default → `False`]**
            - doesn't require a `.` or `dot` + a TLD at the end, but instead compares the last word against a well known list of email domains (eg. `contact ashley @ yandex for more info` would be caught)
         - check_for_at **[Boolean] [Default → `False`]**
             - checks for the word 'at' as '@', currently can result in algorithm being overly greedy as 'at' is such a common word
- **Output:**
    - updated text **[String]**
- **Example**
    - **Usage:** `altered_text = replace_emails(...) do CENSORED end`
    - **Input:**
        - text → `"My name is Cynthia, a friend of mine needs a nanny to watch her baby in your area, her contact is ( <EMAIL> ) She will be waiting to hear from you kindly send her an email now!"`
    - **Output:** `My name is Cynthia, a friend of mine needs a nanny to watch her baby in your area, her contact is ( CENSORED ) She will be waiting to hear from you kindly send her an email now!`

#### count_phone_numbers_and_emails(text, options = {})
- **Description:** Returns the count of the number of emails in the text. Currently uses a map reduce paradigm,
 which incurs information loss but is cleaner to implement, achieves better results, and is **~2x faster**
 than `find_emails`
 - **Input:**
     - text **[String]**
     - options **[Hash]**
         - parse_leet **[Boolean][Default → True]**
            - Parses phone numbers that contain l33t syntax. With this set to true eg. `FivE 4 3 F0r On3 67 NiN3` would be caught.
         - remove_spaces **[Boolean][Default → True]**
            - Parses phone numbers that contain spaces between the numbers. With this set to true eg. `F i v E 4 3 F 0 r O n 3 67 N i N 3` would be caught.
         - aggressive **[Boolean] [Default → `False`]**
            - doesn't require a `.` or `dot` + a TLD at the end, but instead compares the last word against a well known list of email domains (eg. `contact ashley @ yandex for more info` would be caught)
         - check_for_at **[Boolean] [Default → `False`]**
            - checks for the word 'at' as '@', currently can result in algorithm being overly greedy as 'at' is such a common word
 - **Output:**
     - number of occurences of emails **[Integer]**
 - **Example**
     - **Input:**
         - text → `"Hi, Are you seriously interested ..Looking for honest worker .. My e-mail is ashley73299 AT yahoo dot com, phone 416 090 78 NINE 5 ?.. Ashley"`
     - **Output:** `2`

#### find_phone_numbers_and_emails(text, options = {})
- **Description:** Finds all occurrences of phone numbers and emails within a block of text.
- **Input:**
    - text **[String]**
    - options **[Hash]**
        - parse_leet **[Boolean][Default → True]**
            - Parses phone numbers that contain l33t syntax. With this set to true eg. `FivE 4 3 F0r On3 67 NiN3` would be caught.
        - remove_spaces **[Boolean][Default → True]**
            - Parses phone numbers that contain spaces between the numbers. With this set to true eg. `F i v E 4 3 F 0 r O n 3 67 N i N 3` would be caught.
        - aggressive **[Boolean] [Default → `False`]**
            - doesn't require a `.` or `dot` + a TLD at the end, but instead compares the last word against a well known list of email domains (eg. `contact ashley @ yandex for more info` would be caught)
        - check_for_at **[Boolean] [Default → `False`]**
            - checks for the word 'at' as '@', currently can result in algorithm being overly greedy as 'at' is such a common word
 - **Output:**
     - **[Array]**
        - match **[Hash]**
            - offset: **[Integer]**
            - value: **[String]**
- **Example**
    - **Input:**
        - text → `"Hi, Are you seriously interested ..Looking for honest worker .. My e-mail is ashley73299 AT yahoo dot com, phone 416 090 78 NINE 5 ?.. Ashley"`
    - **Output:** `[{start_offset: 78, end_offset: 106, type: :email, value: 'ashley73299 AT yahoo dot com'}, {start_offset: 115, end_offset: 132, type: :phone, value: 'FOUR FIVE ONE 456 8900'}]`

#### replace_phone_numbers_and_emails(text, options = {}, &block)
- **Description:** Replaces all the occurrences of phone numbers and emails within the text with what is returned from the block. Returns the redacted text
of text.
- **Input:**
    - text **[String]**
    - options **[Hash]**
         - parse_leet **[Boolean][Default → True]**
            - Parses phone numbers that contain l33t syntax. With this set to true eg. `FivE 4 3 F0r On3 67 NiN3` would be caught.
         - remove_spaces **[Boolean][Default → True]**
            - Parses phone numbers that contain spaces between the numbers. With this set to true eg. `F i v E 4 3 F 0 r O n 3 67 N i N 3` would be caught.
         - aggressive **[Boolean] [Default → `False`]**
            - doesn't require a `.` or `dot` + a TLD at the end, but instead compares the last word against a well known list of email domains (eg. `contact ashley @ yandex for more info` would be caught)
         - check_for_at **[Boolean] [Default → `False`]**
             - checks for the word 'at' as '@', currently can result in algorithm being overly greedy as 'at' is such a common word
- **Output:**
    - updated text **[String]**
- **Example**
    - **Usage:** `altered_text = replace_phone_numbers_and_emails(...) do CENSORED end`
    - **Input:**
        - text → `"My name is Cynthia, a friend of mine needs a nanny to watch her baby in your area, her contact is ( <EMAIL> or FOUR FIVE ONE 789 4568 ) She will be waiting to hear from you kindly send her an email now!"`
    - **Output:** `My name is Cynthia, a friend of mine needs a nanny to watch her baby in your area, her contact is ( CENSORED or CENSORED ) She will be waiting to hear from you kindly send her an email now!`

#### count_urls(text, options = {})
- **Description:** Simple union regex to find if the text contains bad urls eg. viagra/cialis. Returns a count of the number of occurrences.
appear in the text.
- **Input:**
    - text **[String]**
    - options **[Hash]**
        - To Be Implemented
 - **Output:**
     - number of occurences of matches **[Integer]**
- **Example**
    - **Input:**
        - text → `"cialis vs cialis spam guestbook.php?action=http://cialiswalmart.shop"`
    - **Output:** `3`

<file_sep>/ROADMAP.md
# Roadmap
- [x] Add error messages, especially for malformed input
- [ ] Implement options for `find_phone_numbers` and `replace_phone_numbers`
- [x] Implement [Stale](https://github.com/probot/stale) for issue
- [ ] Implement Automatic Deployments
- [x] Look into using hashes instead of array for testing infrastructure
- [ ] Look into using custom rspec matchers
- [x] Travis badge for marketing
- [x] Use Ruby that's already installed on TravisCI
- [ ] Use threads for true Map/Reduce. Look into [Celluloid](https://github.com/celluloid/celluloid)
- [ ] Have check domain (for email matches) as an option (not only on :aggressive option) to reduce over matching
- [ ] Check TLD to make sure it's a valid TLD as an option to reduce over matching
- [x] Refactor tests to use hashes instead of arrays
- [ ] Allow use of function based replacement instead of forcing yield functionality
- [ ] Implement URL functionality
- [ ] Change URL to keywords list functionality
- [ ] Robust-ify the overlapping interval scenario
- [x] Get setup on Code Climate once the repo goes open source
- [ ] Think about using InchCI (inline docs) instead of README
- [x] Creating a `spec_helper.rb` and use tools like SimpleCov,
- [ ] Look into using Shoulda matchers, and test randomization.
<file_sep>/lib/ramparts/parsers/phone_parser.rb
# frozen_string_literal: true

require_relative '../helpers'

# Parses text and attempts to locate phone numbers
class PhoneParser
  # Counts the number of phone number instances that occur within the block of text
  def count_phone_number_instances(text, options)
    raise ArgumentError, ARGUMENT_ERROR_TEXT unless text.is_a? String

    parsed_text = parse_phone_number(text, options)

    # Uses the map reduce algorithm
    phone_number_instances(MR_ALGO, parsed_text, options).length
  end

  # Replaces phone number instances within the block of text with the insertable
  def replace_phone_number_instances(text, options, &block)
    raise ArgumentError, ARGUMENT_ERROR_TEXT unless text.is_a? String

    instances = find_phone_number_instances(text, options)
    replace(text, instances.reverse!, &block)
  end

  # Finds phone number instances within the block of text
  def find_phone_number_instances(text, options)
    raise ArgumentError, ARGUMENT_ERROR_TEXT unless text.is_a? String

    text = text.downcase

    # Finds the phone number instances using the glorified regex algorithm
    phone_number_instances(GR_ALGO, text, options)
  end

  private

  # Phonetic versions of numbers
  PHONETICS = %w[
    one
    two
    three
    four
    five
    six
    seven
    eight
    nine
    oh
    zero
  ].freeze

  # L33t speak versions of numbers
  LEET_SPEAK = %w[
    w0n
    too
    thr33
    f0r
    f1v3
    s3x
    sex
    s3v3n
    at3
    nin3
  ].freeze

  # Handles multiple spaces
  MULTI_SPACE = '( )*'

  # Regex for phonetics, both with spaces and otherwise
  REGEX_PHONETICS = PHONETICS.join('|')
  REGEX_PHONETICS_SPACED = PHONETICS.map { |word| word.split('').join(MULTI_SPACE) }.join('|')

  # Regex for l33t, both with spaces and otherwise
  REGEX_LEET_SPEAK = LEET_SPEAK.join('|')
  REGEX_LEET_SPEAK_SPACED = LEET_SPEAK.map { |word| word.split('').join(MULTI_SPACE) }.join('|')

  # Base matching for a possible phone number digit
  BASE_MATCHING = "#{REGEX_PHONETICS}|#{REGEX_LEET_SPEAK}|#{REGEX_PHONETICS_SPACED}|#{REGEX_LEET_SPEAK_SPACED}"

  # The final regex used to match phone numbers for GR
  GR_REGEX =
    Regexp.new(/(\()?(\d|#{BASE_MATCHING}){1}([^\w]*(\d|#{BASE_MATCHING}){1}[^\w]*){5,}(\d|#{BASE_MATCHING}){1}/)

  # The final regex used to match phone numbers for MR
  MR_REGEX = Regexp.new(/(\-*\.?\d{1}\.?\-?){7,}/)

  # Replacements used for phonetics for MR
  REPLACEMENTS = {
    'one' => '1',
    'two' => '2',
    'three' => '3',
    'four' => '4',
    'five' => '5',
    'six' => '6',
    'seven' => '7',
    'eight' => '8',
    'nine' => '9',
    'oh' => '0',
    'zero' => '0'
  }.freeze

  # Replacements used for l33t for MR
  LEET_REPLACEMENTS = {
    'w0n' => '1',
    'too' => '2',
    'thr33' => '3',
    'f0r' => '4',
    'f1v3' => '5',
    's3x' => '6',
    'sex' => '6',
    's3v3n' => '7',
    'at3' => '8',
    'nin3' => '9'
  }.freeze

  # Parses the phone number for MR, uses a variety of options
  def parse_phone_number(text, options)
    text = text.delete(' ') if options.fetch(:remove_spaces, true)
    text = text.downcase.gsub(/#{REGEX_PHONETICS}/, REPLACEMENTS)
    text = text.gsub(/#{REGEX_LEET_SPEAK}/, LEET_REPLACEMENTS) if options.fetch(:parse_leet, true)
    text.gsub(/[^\w]/, '-').gsub(/[a-z]/, '.')
  end

  # Returns the phone number instances using the specified algorithm
  def phone_number_instances(algo, text, _options)
    # Determines which algorithm to use
    regex = algo == MR_ALGO ? MR_REGEX : GR_REGEX

    instances = scan(text, regex, :phone)
    instances
  end
end
<file_sep>/ramparts.gemspec
# -*- encoding: utf-8 -*-
$:.push File.expand_path('../lib', __FILE__)
require 'ramparts/version'

Gem::Specification.new do |s|
  s.name        = 'ramparts'
  s.version     = Ramparts::VERSION
  s.platform    = Gem::Platform::RUBY
  s.authors     = ['<NAME>', 'CareGuide']
  s.email       = ['<EMAIL>', '<EMAIL>']
  s.homepage    = 'https://github.com/CareGuide/ramparts'
  s.metadata    = { "source_code_uri" => "https://github.com/CareGuide/ramparts" }
  s.license     = 'MIT'
  s.summary     = %q{Parses blocks of text to find phone numbers (including phonetic numbers), emails, and bad url}
  s.description = %q{Parses blocks of text to find phone numbers (including phonetic numbers), emails, and bad url. Useful for finding scammers who tend to try to post their phone number in messages.}

  s.add_development_dependency 'rspec', '~> 2.5', '>= 2.5.0'
  s.add_development_dependency 'rubocop', '~>0.51.0'
  s.add_development_dependency 'simplecov', '~>0.15.1'

  s.files         = `git ls-files`.split("\n")
  s.test_files    = `git ls-files -- {test,spec,features}/*`.split("\n")
  s.executables   = `git ls-files -- bin/*`.split('\n').map{ |f| File.basename(f) }
  s.require_paths = ['lib']

  s.required_ruby_version = '>= 2.1.0'
end<file_sep>/lib/ramparts.rb
# frozen_string_literal: true

require_relative './ramparts/base'
<file_sep>/spec/spec_helper.rb
# frozen_string_literal: true

# Load first so it can track the application code
require 'simplecov'
SimpleCov.start

require './lib/ramparts'
require 'spec_constants'

# Times a method run length in milliseconds
def time_method(method, *args)
  beginning_time = Time.now
  Ramparts.send(method, args[0])
  end_time = Time.now
  milliseconds = (end_time - beginning_time) * 1000
  milliseconds
end

# Compares the run time of two methods
# In this case the MR and GR algos
def compare_run_times(tests, method1, method2)
  total_time_map_reduce = 0
  total_time_regex = 0

  tests.each do |test|
    map_reduce_time = time_method(method1, test[:text])
    regex_time = time_method(method2, test[:text])

    total_time_map_reduce += map_reduce_time
    total_time_regex += regex_time
  end

  puts
  puts "Map Reduce Total Time: #{total_time_map_reduce.round(2)} milliseconds"
  puts "Regex Total Time: #{total_time_regex.round(2)} milliseconds"
end

# Test helper for testing truthy values against count type methods
def test_truthy_count(tests, method, options = {})
  tests.each do |test|
    matches = Ramparts.send(method, test[:text], options)
    expect(matches)
      .to eq(test[:matches].length),
          "Expected #{test[:matches].length}, got #{matches} for '#{test[:text]}'"
  end
end

# Test helper for testing truthy values against find type methods
def test_truthy_finds(tests, method, options = {})
  tests.each do |test|
    matches = Ramparts.send(method, test[:text], options)
    test[:matches].each_with_index do |match_string, index|
      if matches[index].nil? || matches[index][:value].casecmp(match_string) != 0
        got_result = matches[index].nil? ? 'NIL' : matches[index][:value]
        raise "Expected: #{match_string}\nGot: #{got_result}\nBlock '#{test[:text]}'\nResult: #{matches}"
      end
    end
  end
end

# Test helper for testing truthy values against find type methods
def test_replacements(tests, method, options = {})
  tests.each do |test|
    text = Ramparts.send(method, test[:text], options) do
      INSERTABLE
    end
    if text.casecmp(test[:filtered]) != 0
      raise "Expected: #{test[:filtered]}\nGot: #{text}\nBlock '#{test[:filtered]}'"
    end
  end
end

# Test helper for testing falsy values against count type methods
def test_falsy_count(tests, method, options = {})
  tests.each do |test|
    matches = Ramparts.send(method, test, options)
    expect(matches).to eq(0), "Expected empty array, got #{matches} for '#{test}'"
  end
end

# Test helper for testing falsy values against find type methods
def test_falsy_finds(tests, method, options = {})
  tests.each do |test|
    matches = Ramparts.send(method, test, options)
    expect(matches.length).to eq(0), "Expected empty array, got #{matches.length} for '#{test}'"
  end
end
<file_sep>/spec/parsers/email_parser_spec.rb
# frozen_string_literal: true

require_relative '../data/email_data/truthy_email_data'
require_relative '../data/email_data/falsy_email_data'

describe '#count_emails' do
  it 'parses a number of positive test blocks correctly' do
    test_truthy_count(EMAIL_TRUTHY_WITH_ANSWERS, :count_emails)
  end

  it 'parses a number of positive test blocks correctly with aggressive option' do
    test_truthy_count(EMAIL_TRUTHY_WITH_ANSWERS, :count_emails, aggressive: true)
  end

  it 'parses a number of positive aggressive test blocks correctly with check_for_at option' do
    test_truthy_count(EMAIL_TRUTHY_AT, :count_emails, check_for_at: true)
  end

  it 'parses a number of positive aggressive test blocks correctly with aggressive option' do
    test_truthy_count(EMAIL_TRUTHY_AGGRESSIVE, :count_emails, aggressive: true)
  end

  it 'parses a number of negative test blocks correctly' do
    test_falsy_count(EMAIL_FALSY_BLOCKS, :count_emails)
  end
end

describe '#find_emails' do
  it 'finds a number of positive test blocks correctly' do
    test_truthy_finds(EMAIL_TRUTHY_WITH_ANSWERS, :find_emails)
  end

  it 'finds a number of positive aggressive test blocks correctly with check_for_at option' do
    test_truthy_finds(EMAIL_TRUTHY_AT, :find_emails, check_for_at: true)
  end

  # TODO: Update algorithm to be able to pass test with EMAIL_TRUTHY_AGGRESSIVE

  it 'finds a number of negative test blocks correctly and regex only' do
    test_falsy_finds(EMAIL_FALSY_BLOCKS, :find_emails)
  end
end

describe '#replace_emails' do
  it 'replaces a number of positive test blocks correctly with email replacer' do
    test_replacements(EMAIL_TRUTHY_WITH_ANSWERS, :replace_emails)
  end

  it 'replaces a number of positive aggressive test blocks correctly with check_for_at option' do
    test_replacements(EMAIL_TRUTHY_AT, :replace_emails, check_for_at: true)
  end

  # TODO: Update algorithm to be able to pass test with EMAIL_TRUTHY_AGGRESSIVE
end

describe 'Map/Reduce to Regex Run Time' do
  it 'times the two methods against each other' do
    compare_run_times(EMAIL_TRUTHY_WITH_ANSWERS, :count_emails, :find_emails)
  end
end
<file_sep>/lib/ramparts/version.rb
# frozen_string_literal: true

module Ramparts
  VERSION = '0.3.1'
end
<file_sep>/lib/ramparts/parsers/url_parser.rb
# frozen_string_literal: true

require_relative '../helpers'

# Parses text and attempts to find urls
class UrlParser
  # Counts the number of occurrences of that url within the block of text
  def count_url_instances(text, options)
    raise ArgumentError, ARGUMENT_ERROR_TEXT unless text.is_a? String

    text = parse_url(text)
    url_instances(text, options).length
  end

  private

  BAD_URL_REGEX = Regexp.union(/cialis/, /viagra/)

  # Parses the url to make it easier to search
  def parse_url(text)
    text.downcase
  end

  # Returns the instances that match the regex
  def url_instances(text, _options)
    text
      .enum_for(:scan, BAD_URL_REGEX)
      .map { { offset: Regexp.last_match.begin(0), value: Regexp.last_match.to_s.strip } }
  end
end
<file_sep>/spec/spec_constants.rb
# frozen_string_literal: true

INSERTABLE = 'CENSORED'
<file_sep>/.rubocop.yml
AllCops:
  TargetRubyVersion: 2.3
  Exclude:
    - 'ramparts.gemspec'
    - 'Gemfile'

ClassLength:
  Enabled: false

CyclomaticComplexity:
  Enabled: false

Documentation:
  Enabled: false

Metrics/AbcSize:
  Enabled: false

Lint/AssignmentInCondition:
  Enabled: false

Style/ParenthesesAroundCondition:
  Enabled: false

Style/DoubleNegation:
  Enabled: false

Style/ConditionalAssignment:
  Enabled: false

Style/StringLiterals:
  Exclude:
    - 'spec/data/**/*'

Layout/SpaceAfterComma:
  Exclude:
    - 'spec/data/**/*'

Style/WordArray:
  Exclude:
    - 'spec/data/**/*'

LineLength:
  Max: 120
  Exclude:
    - 'spec/data/**/*'

BlockLength:
  Exclude:
    - 'spec/**/*'

MethodLength:
  CountComments: false
  Max: 100<file_sep>/spec/parsers/url_parser_spec.rb
# frozen_string_literal: true

require './lib/ramparts'
require_relative '../data/url_data/truthy_url_data'
require_relative '../data/url_data/falsy_url_data'

describe '#count_urls' do
  it 'parses a number of positive test blocks correctly' do
    test_truthy_count(URL_TRUTHY, :count_urls)
  end

  it 'parses a number of negative test blocks correctly' do
    test_falsy_count(URL_FALSY, :count_urls)
  end
end
<file_sep>/lib/ramparts/base.rb
# frozen_string_literal: true

require_relative './parsers/email_parser'
require_relative './parsers/phone_parser'
require_relative './parsers/url_parser'
require_relative './helpers'

class Ramparts
  def self.count_phone_numbers(text, options = {})
    pp = PhoneParser.new
    pp.count_phone_number_instances(text, options)
  end

  def self.find_phone_numbers(text, options = {})
    pp = PhoneParser.new
    pp.find_phone_number_instances(text, options)
  end

  def self.replace_phone_numbers(text, options = {}, &block)
    pp = PhoneParser.new
    pp.replace_phone_number_instances(text, options, &block)
  end

  def self.count_emails(text, options = {})
    ep = EmailParser.new
    ep.count_email_instances(text, options)
  end

  def self.find_emails(text, options = {})
    ep = EmailParser.new
    ep.find_email_instances(text, options)
  end

  def self.replace_emails(text, options = {}, &block)
    ep = EmailParser.new
    ep.replace_email_instances(text, options, &block)
  end

  def self.count_urls(text, options = {})
    up = UrlParser.new
    up.count_url_instances(text, options)
  end

  def self.count_phone_numbers_and_emails(text, options = {})
    pp = PhoneParser.new
    ep = EmailParser.new

    phone_instances = pp.count_phone_number_instances(text, options)
    email_instances = ep.count_email_instances(text, options)
    phone_instances + email_instances
  end

  def self.find_phone_numbers_and_emails(text, options = {})
    pp = PhoneParser.new
    ep = EmailParser.new

    phone_instances = pp.find_phone_number_instances(text, options)
    email_instances = ep.find_email_instances(text, options)

    if options.fetch(:compare, false)
      phone_instances.each do |phone|
        phone_range = (phone[:start_offset]...phone[:end_offset])
        email_instances.delete_if do |email|
          email_range = (email[:start_offset]...email[:end_offset])
          ranges_overlap?(phone_range, email_range)
        end
      end
    end

    phone_instances + email_instances
  end

  def self.replace_phone_numbers_and_emails(text, options = {}, &block)
    pp = PhoneParser.new
    ep = EmailParser.new

    phone_instances = pp.find_phone_number_instances(text, options)
    email_instances = ep.find_email_instances(text, options)
    total_instances = phone_instances + email_instances

    if options.fetch(:compare, false)
      phone_instances.each do |phone|
        phone_range = (phone[:start_offset]...phone[:end_offset])
        email_instances.delete_if do |email|
          email_range = (email[:start_offset]...email[:end_offset])
          ranges_overlap?(phone_range, email_range)
        end
      end
    end

    # We have no idea the order of the matches unless we ran the regex for both occurrences at the same time.
    # Instead we sort by start offset and then reverse so that we can replace from the end of the
    # string to the start to not screw up indices. Apparently this is the fastest way to sort in reverse
    # https://stackoverflow.com/questions/2642182/sorting-an-array-in-descending-order-in-ruby#answer-2651028
    total_instances_sorted = total_instances.sort_by { |instance| instance[:start_offset] }.reverse!

    replace(text, total_instances_sorted, &block)
  end
end
<file_sep>/spec/parsers/email_and_phone_parser_spec.rb
# frozen_string_literal: true

require_relative '../data/email_and_phone_data/truthy_email_and_phone_data'
require_relative '../data/email_and_phone_data/falsy_email_and_phone_data'

describe '#count_phone_numbers_and_emails' do
  it 'parses a number of positive test blocks correctly' do
    test_truthy_count(EMAIL_PHONE_TRUTHY_WITH_ANSWERS, :count_phone_numbers_and_emails)
  end

  it 'parses a number of negative test blocks correctly' do
    test_falsy_count(EMAIL_PHONE_FALSY_BLOCKS, :count_phone_numbers)
  end
end

describe '#find_phone_numbers_and_emails' do
  it 'parses a number of positive test blocks correctly with multi method' do
    test_truthy_finds(EMAIL_PHONE_TRUTHY_WITH_ANSWERS, :find_phone_numbers_and_emails)
  end

  it 'parses a number of positive test blocks correctly with multi method and compare option' do
    test_truthy_finds(EMAIL_PHONE_TRUTHY_WITH_ANSWERS, :find_phone_numbers_and_emails, compare: true)
  end

  it 'parses a number of negative test blocks correctly with multi method' do
    test_falsy_finds(EMAIL_PHONE_FALSY_BLOCKS, :find_phone_numbers_and_emails)
  end
end

describe '#replace_phone_numbers_and_emails' do
  it 'replaces a number of positive test blocks correctly with multi method' do
    test_replacements(EMAIL_PHONE_TRUTHY_WITH_ANSWERS, :replace_phone_numbers_and_emails)
  end

  it 'replaces a number of positive test blocks correctly with multi method and compare option' do
    test_replacements(EMAIL_PHONE_TRUTHY_WITH_ANSWERS, :replace_phone_numbers_and_emails, compare: true)
  end
end

describe 'Map/Reduce to Regex Run Time' do
  it 'times the two methods against each other' do
    compare_run_times(EMAIL_PHONE_TRUTHY_WITH_ANSWERS, :count_phone_numbers_and_emails, :find_phone_numbers_and_emails)
  end
end

languages: Markdown Ruby YAML

repo_language: Markdown

repo_name: CareGuide/ramparts


text:
<repo_name>PiotrChowaniec77/losowanie<file_sep>/js/main.js
let arr = [];

const addBtn = document.querySelector(".add");
const input = document.querySelector("input");
const cleanBtn = document.querySelector(".clean");
const showAdviceBtn = document.querySelector(".showAdvice");
const showOptionsBtn = document.querySelector(".showOptions");
const div = document.querySelector("div");

addAdvice = e => {
    e.preventDefault();
    newAdvice = input.value;
    if (newAdvice) {
        arr.push(newAdvice);
        input.value = "";
    }
};
showAdvice = () => {
    indexAdvice = Math.floor(Math.random() * arr.length);
    div.textContent = arr[indexAdvice];
};

showOption = () => {
    div.textContent = arr.join(", ");
};

showAdviceBtn.addEventListener("click", showAdvice);
showOptionsBtn.addEventListener("click", showOption);
addBtn.addEventListener("click", addAdvice);
cleanBtn.addEventListener("click", e => {
    e.preventDefault();
    arr = [];
});

repo_language: JavaScript


text:
<repo_name>BunnyStudios/venison<file_sep>/README.md
venison
=======

TBA

repo_name: BunnyStudios/venison