#!/usr/bin/env python
# -*- encoding: utf-8 -*-

#  Licensed to the Apache Software Foundation (ASF) under one
#  or more contributor license agreements.  See the NOTICE file
#  distributed with this work for additional information
#  regarding copyright ownership.  The ASF licenses this file
#  to you 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.

''' opts_unittest.py '''
import unittest2 as unittest
import mock
from mock import call, patch, Mock, MagicMock
import os
import getpass
import subprocess
import sys
import tempfile
import heron.tools.cli.src.python.main as main
import heron.tools.cli.src.python.cdefs as cdefs
import heron.tools.cli.src.python.submit as submit
import heron.tools.cli.src.python.result as result
import heron.tools.common.src.python.utils.config as config

class ClientCommandTest(unittest.TestCase):

  def setUp(self):
    # Mock config calls
    config.parse_cluster_role_env = MagicMock(return_value=('local', 'user', 'default'))
    config.get_heron_release_file = MagicMock(return_value=None)
    config.create_tar = MagicMock(return_value=None)
    config.get_heron_lib_dir = MagicMock(return_value='/heron/lib/jars')
    config.get_heron_dir = MagicMock(return_value='/heron/home')
    config.get_java_path = MagicMock(return_value='/usr/lib/bin/java')
    config.get_heron_release_file = MagicMock(return_value='/heron/home/release.yaml')
    config.parse_override_config_and_write_file = MagicMock(return_value='/heron/home/override.yaml')
    # Mock result module
    result.render = MagicMock(return_value=None)
    result.is_successful = MagicMock(return_value=True)
    result.SimpleResult.__init__ = Mock(return_value=None)
    result.ProcessResult.__init__ = Mock(return_value=None)
    # mock others
    def launch(cl_args, topology_file, tmp_dir):
      return submit.launch_a_topology(cl_args, tmp_dir, topology_file, 'T.defn', 'WordCount')
    submit.launch_topologies = Mock(side_effect=launch)
    tempfile.mkdtemp = MagicMock(return_value='/tmp/heron_tmp')
    main.check_environment = MagicMock(return_value=True)
    os.path.isdir = MagicMock(return_value=True)
    os.path.isfile = MagicMock(return_value=True)
    os.environ.copy = MagicMock(return_value={})
    main.server_deployment_mode = MagicMock(return_value=dict())
    cdefs.check_direct_mode_cluster_definition = MagicMock(return_value=True)

  def run_test(self, command, issued_commands, environ):
    calls = []
    for cmd in issued_commands:
      calls.append(call(cmd.split(' '), env=environ, stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE, bufsize=1))
    subprocess.Popen = MagicMock()
    with patch.object(sys, 'argv', command.split(' ')):
      main.main()
      for called, expect in zip(subprocess.Popen.call_args_list, calls):
        self.assertEqual(called, expect)

class SubmitTest(ClientCommandTest):

  def test(self):
    subprocess.Popen = MagicMock()

    command = 'heron submit local ~/.heron/examples/heron-api-examples.jar ' + \
              'org.apache.heron.examples.api.ExclamationTopology EX'

    create_defn_commands = '/usr/lib/bin/java -client -Xmx1g -cp ' \
    '~/.heron/examples/heron-api-examples.jar:/heron/lib/jars/third_party/* ' \
    'org.apache.heron.examples.api.ExclamationTopology EX'

    submit_commands = '/usr/lib/bin/java -client -Xmx1g -cp ' \
                      ':/heron/lib/jars/scheduler/*:/heron/lib/jars/uploader/*:' \
                      '/heron/lib/jars/statemgr/*:/heron/lib/jars/packing/* ' \
                      'org.apache.heron.scheduler.SubmitterMain --cluster local ' \
                      '--role user --environment default --submit_user %s ' \
                      '--heron_home /heron/home ' \
                      '--config_path /heron/home/conf/local --override_config_file ' \
                      '/heron/home/override.yaml --release_file /heron/home/release.yaml ' \
                      '--topology_package /tmp/heron_tmp/topology.tar.gz --topology_defn T.defn ' \
                      '--topology_bin heron-examples.jar' % (getpass.getuser())
    env = {'HERON_OPTIONS':
           'cmdline.topologydefn.tmpdirectory=/tmp/heron_tmp,cmdline.topology.initial.state=RUNNING'}
    ClientCommandTest.run_test(self, command, [create_defn_commands, submit_commands], env)
