# Copyright 2021 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

AUTHOR = 'abergman, chromeos-engprod-platform-syd'
NAME = 'ui_QuickCheckCUJ2_basic_wakeup'
ATTRIBUTES = 'suite:performance_cuj_quick'
TIME = 'long'
TEST_CATEGORY = 'Stress'
TEST_CLASS = 'Hardware'
TEST_TYPE = 'Server'
PRIORITY = 4995
MAX_RESULT_SIZE_KB = 1024 * 1024
JOB_RETRIES = 2
REQUIRE_SSP = True
DEPENDENCIES = ''

DOC = '''
Run the Tast-based MTBF performance CUJ test.

Tast is an integration-testing framework analogous to the test-running portion
of Autotest. See https://chromium.googlesource.com/chromiumos/platform/tast/ for
more information.

See http://go/tast-failures for information about investigating failures.
'''

import common
import json
import logging
import tempfile
from six.moves import urllib
import yaml

from autotest_lib.client.common_lib import utils
from autotest_lib.client.common_lib.cros import dev_server
from autotest_lib.utils import labellib

test_args = dict()
test_args['test_version'] = 1

def report_host_info(host):
  labels = labellib.LabelsMapping(host.host_info_store.get().labels)
  labels['test'] = 'ui.QuickCheckCUJ2.basic_wakeup'
  labels['test_iteration'] = '1'
  utils.write_keyval(job.resultdir, labels)

def parse_config(config_url):
  response = urllib.request.urlopen(config_url)
  vars = json.loads(response.read())
  for key in vars:
    test_args[key] = vars[key]
  logging.info('Read %d values from remote configuration.', len(vars))

def stage_config(host):
  devservers = dev_server.ImageServer.get_available_devservers()
  devserver_url = devservers[0][0]
  if devserver_url:
    logging.info('Using devserver: %s', devserver_url)
    labels = host.host_info_store.get().labels
    build = labellib.LabelsMapping(labels).get(labellib.Key.CROS_VERSION)
    if not build:
      # Not able to detect build, means not running on Moblab.
      return
    ds = dev_server.ImageServer(devserver_url)
    gs_bucket = dev_server._get_image_storage_server()
    if gs_bucket:
      config_path = 'config/perf_cuj/'
      config_file = 'perf_cuj.config'
      archive_url = gs_bucket + config_path
      logging.info('Staging configuration from %s.', gs_bucket)
      try:
        ds.stage_artifacts(build,
                          archive_url = archive_url,
                          files = [config_file])
      except Exception as e:
          logging.error('Staging artifacts failed: %s', str(e))
      else:
        logging.info('Parsing configuration from %s.', archive_url)
        parse_config(devserver_url + '/static/' + config_path + config_file)

def run(machine):
  with tempfile.NamedTemporaryFile(suffix='.yaml') as temp_file:
      host=hosts.create_host(machine)
      report_host_info(host)
      stage_config(host)

      # Writing all test arguments to yaml file.
      yaml.dump(test_args, stream=temp_file, default_flow_style=False)
      job.run_test('tast',
                  host=host,
                  test_exprs=['ui.QuickCheckCUJ2.basic_wakeup'],
                  ignore_test_failures=False,
                  max_run_sec=3600,
                  command_args=args,
                  varsfiles=[temp_file.name])

parallel_simple(run, machines)
