#!/usr/bin/env python3
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import json
import optimize_webui
import os
import shutil
import tempfile
import unittest


_CWD = os.getcwd()
_HERE_DIR = os.path.dirname(__file__)


class OptimizeWebUiTest(unittest.TestCase):
  def setUp(self):
    self._tmp_dirs = []
    self._tmp_src_dir = None
    self._out_folder = self._create_tmp_dir()

  def tearDown(self):
    for tmp_dir in self._tmp_dirs:
      shutil.rmtree(tmp_dir)

  def _write_file_to_dir(self, file_path, file_contents):
    file_dir = os.path.dirname(file_path)
    if not os.path.exists(file_dir):
      os.makedirs(file_dir)
    with open(file_path, 'w') as tmp_file:
      tmp_file.write(file_contents)

  def _write_file_to_src_dir(self, file_path, file_contents):
    if not self._tmp_src_dir:
      self._tmp_src_dir = self._create_tmp_dir()
    file_path_normalized = os.path.normpath(os.path.join(self._tmp_src_dir,
                                                         file_path))
    self._write_file_to_dir(file_path_normalized, file_contents)

  def _create_tmp_dir(self):
    # TODO(dbeam): support cross-drive paths (i.e. d:\ vs c:\).
    tmp_dir = tempfile.mkdtemp(dir=_HERE_DIR)
    self._tmp_dirs.append(tmp_dir)
    return tmp_dir

  def _read_out_file(self, file_name):
    assert self._out_folder
    with open(os.path.join(self._out_folder, file_name), 'r') as f:
      return f.read()

  def _run_optimize(self, input_args):
    # TODO(dbeam): make it possible to _run_optimize twice? Is that useful?
    args = input_args + [
      '--depfile', os.path.join(self._out_folder, 'depfile.d'),
      '--target_name', 'dummy_target_name',
      '--input', self._tmp_src_dir,
      '--out_folder', self._out_folder,
    ]
    optimize_webui.main(args)

  def _write_v3_files_to_src_dir(self):
    self._write_file_to_src_dir('element.js', "alert('yay');")
    self._write_file_to_src_dir('element_in_dir/element_in_dir.js',
                                "alert('hello from element_in_dir');")
    self._write_file_to_src_dir('ui.js', '''
import './element.js';
import './element_in_dir/element_in_dir.js';
''')
    self._write_file_to_src_dir('ui.html', '''
<script type="module" src="ui.js"></script>
''')

  def _write_v3_files_with_custom_path_to_src_dir(self, custom_path):
    self._write_file_to_dir(os.path.join(
        custom_path, 'external_dir', 'external_element.js'), '''
import './sub_dir/external_element_dep.js';
alert('hello from external_element');
''')

    self._write_file_to_dir(os.path.join(
        custom_path, 'external_dir', 'sub_dir', 'external_element_dep.js'),
        "alert('hello from external_element_dep');")

    self._write_file_to_src_dir('element.js', "alert('yay');")
    self._write_file_to_src_dir('ui.js', '''
import './element.js';
import 'some-fake-scheme://foo/external_dir/external_element.js';
''')
    self._write_file_to_src_dir('ui.html', '''
<script type="module" src="ui.js"></script>
''')

  def _write_v3_files_with_resources_to_src_dir(self, resources_scheme):
    resources_path = os.path.join(
        _HERE_DIR.replace('\\', '/'), 'gen', 'ui', 'webui', 'resources',
        'preprocessed', 'js')
    fake_resource_path = os.path.join(resources_path, 'fake_resource.js')
    scheme_relative_resource_path = os.path.join(resources_path, 'scheme_relative_resource.js')
    os.makedirs(os.path.dirname(resources_path))

    self._tmp_dirs.append('gen')
    self._write_file_to_dir(fake_resource_path, '''
export const foo = 5;
alert('hello from shared resource');''');
    self._write_file_to_dir(scheme_relative_resource_path, '''
export const bar = 6;
alert('hello from another shared resource');''');

    self._write_file_to_src_dir('element.js', '''
import '%s//resources/js/fake_resource.js';
import {bar} from '//resources/js/scheme_relative_resource.js';
alert('yay ' + bar);
''' % resources_scheme)
    self._write_file_to_src_dir('element_in_dir/element_in_dir.js', '''
import {foo} from '%s//resources/js/fake_resource.js';
import '../strings.m.js';
alert('hello from element_in_dir ' + foo);
''' % resources_scheme)
    self._write_file_to_src_dir('ui.js', '''
import './strings.m.js';
import './element.js';
import './element_in_dir/element_in_dir.js';
''')
    self._write_file_to_src_dir('ui.html', '''
<script type="module" src="ui.js"></script>
''')

  def _check_output_html(self, out_html):
    self.assertNotIn('element.html', out_html)
    self.assertNotIn('element.js', out_html)
    self.assertNotIn('element_in_dir.html', out_html)
    self.assertNotIn('element_in_dir.js', out_html)
    self.assertIn('got here!', out_html)

  def _check_output_js(self, output_js_name):
    output_js = self._read_out_file(output_js_name)
    self.assertIn('yay', output_js)
    self.assertIn('hello from element_in_dir', output_js)

  def _check_output_depfile(self, has_html):
    depfile_d = self._read_out_file('depfile.d')
    self.assertIn('element.js', depfile_d)
    self.assertIn(os.path.normpath('element_in_dir/element_in_dir.js'),
                  depfile_d)
    if (has_html):
      self.assertIn('element.html', depfile_d)
      self.assertIn(os.path.normpath('element_in_dir/element_in_dir.html'),
                    depfile_d)

  def testV3SimpleOptimize(self):
    self._write_v3_files_to_src_dir()
    args = [
      '--host', 'fake-host',
      '--js_module_in_files', 'ui.js',
      '--js_out_files', 'ui.rollup.js',
    ]
    self._run_optimize(args)

    self._check_output_js('ui.rollup.js')
    self._check_output_depfile(False)

  def testV3OptimizeWithResources(self):
    self._write_v3_files_with_resources_to_src_dir('chrome:')
    resources_path = os.path.join(
        'gen', 'ui', 'webui', 'resources', 'preprocessed')
    args = [
      '--host', 'fake-host',
      '--js_module_in_files', 'ui.js',
      '--js_out_files', 'ui.rollup.js',
      '--external_paths', 'chrome://resources|%s' % resources_path,
    ]
    self._run_optimize(args)

    ui_rollup_js = self._read_out_file('ui.rollup.js')
    self.assertIn('yay', ui_rollup_js)
    self.assertIn('hello from element_in_dir', ui_rollup_js)
    self.assertIn('hello from shared resource', ui_rollup_js)

    depfile_d = self._read_out_file('depfile.d')
    self.assertIn('element.js', depfile_d)
    self.assertIn(os.path.normpath('element_in_dir/element_in_dir.js'),
                  depfile_d)
    self.assertIn(
        os.path.normpath(
            '../gen/ui/webui/resources/preprocessed/js/scheme_relative_resource.js'),
        depfile_d)
    self.assertIn(
        os.path.normpath(
            '../gen/ui/webui/resources/preprocessed/js/fake_resource.js'),
        depfile_d)

  def testV3MultiBundleOptimize(self):
    self._write_v3_files_to_src_dir()
    self._write_file_to_src_dir('lazy_element.js',
                                "alert('hello from lazy_element');")
    self._write_file_to_src_dir('lazy.js', '''
import './lazy_element.js';
import './element_in_dir/element_in_dir.js';
''')

    args = [
      '--host', 'fake-host',
      '--js_module_in_files', 'ui.js', 'lazy.js',
      '--js_out_files', 'ui.rollup.js', 'lazy.rollup.js', 'shared.rollup.js',
      '--out-manifest', os.path.join(self._out_folder, 'out_manifest.json'),
    ]
    self._run_optimize(args)

    # Check that the shared element is in the shared bundle and the non-shared
    # elements are in the individual bundles.
    ui_js = self._read_out_file('ui.rollup.js')
    self.assertIn('yay', ui_js)
    self.assertNotIn('hello from lazy_element', ui_js)
    self.assertNotIn('hello from element_in_dir', ui_js)

    lazy_js = self._read_out_file('lazy.rollup.js')
    self.assertNotIn('yay', lazy_js)
    self.assertIn('hello from lazy_element', lazy_js)
    self.assertNotIn('hello from element_in_dir', lazy_js)

    shared_js = self._read_out_file('shared.rollup.js')
    self.assertNotIn('yay', shared_js)
    self.assertNotIn('hello from lazy_element', shared_js)
    self.assertIn('hello from element_in_dir', shared_js)

    # All 3 JS files should be in the depfile.
    self._check_output_depfile(False)
    depfile_d = self._read_out_file('depfile.d')
    self.assertIn('lazy_element.js', depfile_d)

    manifest = json.loads(self._read_out_file('out_manifest.json'))
    self.assertEqual(3, len(manifest['files']))
    self.assertTrue('lazy.rollup.js' in manifest['files'])
    self.assertTrue('ui.rollup.js' in manifest['files'])
    self.assertTrue('shared.rollup.js' in manifest['files'])

    self.assertEqual(
        os.path.relpath(self._out_folder, _CWD).replace('\\', '/'),
        os.path.relpath(manifest['base_dir'], _CWD).replace('\\', '/'))

  def testV3OptimizeWithCustomPaths(self):
    custom_dir = os.path.join(self._create_tmp_dir(), 'foo_root')
    self._write_v3_files_with_custom_path_to_src_dir(custom_dir)
    resources_path = os.path.join(
        'gen', 'ui', 'webui', 'resources', 'preprocessed')
    args = [
      '--host', 'fake-host',
      '--js_module_in_files', 'ui.js',
      '--js_out_files', 'ui.rollup.js',
      '--external_paths',
      'chrome://resources|%s' % resources_path,
      'some-fake-scheme://foo|%s' % os.path.abspath(custom_dir),
    ]
    self._run_optimize(args)

    ui_rollup_js = self._read_out_file('ui.rollup.js')
    self.assertIn('yay', ui_rollup_js)
    self.assertIn('hello from external_element', ui_rollup_js)
    self.assertIn('hello from external_element_dep', ui_rollup_js)

    depfile_d = self._read_out_file('depfile.d')
    self.assertIn('element.js', depfile_d)
    # Relative path from the src of the root module to the external root dir
    relpath = os.path.relpath(custom_dir, self._tmp_src_dir)
    self.assertIn(os.path.normpath(
        os.path.join(relpath, 'external_dir', 'external_element.js')),
        depfile_d)
    self.assertIn(os.path.normpath(
        os.path.join(relpath, 'external_dir', 'sub_dir',
                     'external_element_dep.js')),
        depfile_d)

  def testV3SimpleOptimizeExcludes(self):
    self._write_v3_files_to_src_dir()
    args = [
      '--host', 'chrome-extension://myextensionid/',
      '--js_module_in_files', 'ui.js',
      '--js_out_files', 'ui.rollup.js',
      '--exclude', 'element_in_dir/element_in_dir.js',
    ]
    self._run_optimize(args)

    output_js = self._read_out_file('ui.rollup.js')
    self.assertIn('yay', output_js)
    self.assertNotIn('hello from element_in_dir', output_js)
    depfile_d = self._read_out_file('depfile.d')
    self.assertIn('element.js', depfile_d)
    self.assertNotIn('element_in_dir', depfile_d)

  # Tests that bundling resources for an untrusted UI can successfully exclude
  # resources imported from both chrome-untrusted://resources and scheme
  # relative paths.
  def testV3SimpleOptimizeExcludesResources(self):
    self._write_v3_files_with_resources_to_src_dir('chrome-untrusted:')
    resources_path = os.path.join(
        'gen', 'ui', 'webui', 'resources', 'preprocessed')
    args = [
        '--host', 'chrome-untrusted://fake-host',
      '--js_module_in_files', 'ui.js',
      '--js_out_files', 'ui.rollup.js',
      '--external_paths',
      '//resources|%s' % resources_path,
      'chrome-untrusted://resources|%s' % resources_path,
      '--exclude', '//resources/js/scheme_relative_resource.js',
      'chrome-untrusted://resources/js/fake_resource.js',
    ]
    self._run_optimize(args)

    output_js = self._read_out_file('ui.rollup.js')
    self.assertIn('yay', output_js)
    self.assertIn('//resources/js/scheme_relative_resource.js', output_js)
    self.assertIn('chrome-untrusted://resources/js/fake_resource.js', output_js)
    self.assertNotIn('hello from another shared resource', output_js)
    self.assertNotIn('hello from shared resource', output_js)
    depfile_d = self._read_out_file('depfile.d')
    self.assertNotIn('fake_resource', depfile_d)
    self.assertNotIn('scheme_relative_resource', depfile_d)

  # Tests that bundling resources for an untrusted UI successfully bundles
  # resources from both chrome-untrusted://resources and //resources.
  def testV3SimpleOptimizeUntrustedResources(self):
    self._write_v3_files_with_resources_to_src_dir('chrome-untrusted:')
    resources_path = os.path.join(
        'gen', 'ui', 'webui', 'resources', 'preprocessed')
    args = [
        '--host', 'chrome-untrusted://fake-host',
      '--js_module_in_files', 'ui.js',
      '--js_out_files', 'ui.rollup.js',
      '--external_paths',
      '//resources|%s' % resources_path,
      'chrome-untrusted://resources|%s' % resources_path,
    ]
    self._run_optimize(args)

    output_js = self._read_out_file('ui.rollup.js')
    self.assertIn('yay', output_js)
    self.assertIn('hello from another shared resource', output_js)
    self.assertIn('hello from shared resource', output_js)
    depfile_d = self._read_out_file('depfile.d')
    self.assertIn('fake_resource', depfile_d)
    self.assertIn('scheme_relative_resource', depfile_d)


  def testV3OptimizeWithCustomLayeredPaths(self):
    tmp_dir = self._create_tmp_dir()
    custom_dir_foo = os.path.join(tmp_dir, 'foo_root')
    custom_dir_bar = os.path.join(tmp_dir, 'bar_root')

    self._write_v3_files_with_custom_path_to_src_dir(custom_dir_foo)

    # Overwrite one of the foo files to import something from
    # some-fake-scheme://bar.
    self._write_file_to_dir(os.path.join(
        custom_dir_foo, 'external_dir', 'sub_dir',
        'external_element_dep.js'), '''
import 'some-fake-scheme://bar/another_element.js';
alert('hello from external_element_dep');''')

    # Write that file to the bar_root directory.
    self._write_file_to_dir(os.path.join(custom_dir_bar, 'another_element.js'),
                            "alert('hello from another external dep');")

    resources_path = os.path.join(
        'gen', 'ui', 'webui', 'resources', 'preprocessed')
    args = [
      '--host', 'fake-host',
      '--js_module_in_files', 'ui.js',
      '--js_out_files', 'ui.rollup.js',
      '--external_paths',
      '//resources|%s' % resources_path,
      'some-fake-scheme://foo|%s' % os.path.abspath(custom_dir_foo),
      'some-fake-scheme://bar|%s' % os.path.abspath(custom_dir_bar),
    ]
    self._run_optimize(args)

    ui_rollup_js = self._read_out_file('ui.rollup.js')
    self.assertIn('yay', ui_rollup_js)
    self.assertIn('hello from external_element', ui_rollup_js)
    self.assertIn('hello from external_element_dep', ui_rollup_js)
    self.assertIn('hello from another external dep', ui_rollup_js)

    depfile_d = self._read_out_file('depfile.d')
    self.assertIn('element.js', depfile_d)
    # Relative path from the src of the root module to the external root dir
    relpath = os.path.relpath(custom_dir_foo, self._tmp_src_dir)
    self.assertIn(os.path.normpath(
        os.path.join(relpath, 'external_dir', 'external_element.js')),
        depfile_d)
    self.assertIn(os.path.normpath(
        os.path.join(relpath, 'external_dir', 'sub_dir',
                     'external_element_dep.js')),
        depfile_d)
    # Relative path from the src of the root module to the secondary dependency
    # root dir.
    relpath_bar = os.path.relpath(custom_dir_bar, self._tmp_src_dir)
    self.assertIn(os.path.normpath(
        os.path.join(relpath_bar, 'another_element.js')), depfile_d)

if __name__ == '__main__':
  unittest.main()
