Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/all.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ module AutoHCK
autoload_relative :HCKInstall, 'engines/hckinstall/hckinstall'
autoload_relative :HCKStudio, 'setupmanagers/hckstudio'
autoload_relative :HCKTest, 'engines/hcktest/hcktest'
autoload_relative :PlatformClients, 'engines/hcktest/platform_clients'
autoload_relative :Helper, 'helper'
autoload_relative :InvalidConfigFile, 'exceptions'
autoload_relative :InvalidEngineTypeError, 'engines/exceptions'
Expand Down
108 changes: 79 additions & 29 deletions lib/engines/hcktest/hcktest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class HCKTest
extend T::Sig
include Helper

attr_reader :config, :drivers, :platform, :extensions
attr_reader :config, :drivers, :platform, :extensions, :platform_clients

PLATFORMS_JSON_DIR = 'lib/engines/hcktest/platforms'
CONFIG_JSON = 'lib/engines/hcktest/hcktest.json'
Expand All @@ -18,6 +18,16 @@ class HCKTest
ENGINE_MODE = 'test'
AUTOHCK_RETRIES = 5

# Maps platform roles to the HLK machine-set role names used in QueueTest.
HLK_ROLE_MAP = {
Models::ClientRole::Support => 'Support',
Models::ClientRole::Master => 'MC',
Models::ClientRole::Stress => 'SC'
}.freeze

# Roles that are the primary test target
PRIMARY_ROLES = [Models::ClientRole::Dut, Models::ClientRole::Sut].freeze

def initialize(project)
@project = project
@logger = project.logger
Expand All @@ -28,6 +38,12 @@ def initialize(project)
@extensions = find_extensions
prepare_extra_sw
validate_paths unless @driver_path.nil?
@platform_clients = build_platform_clients
end

sig { returns(PlatformClients) }
def build_platform_clients
PlatformClients.new(@project.engine_platform, logger: @logger)
end

def test_steps
Expand Down Expand Up @@ -126,24 +142,31 @@ def find_extensions
end

def target
if @project.options.test.svvp
{
'name' => @clients.values[0].name,
'type' => @svvp_info.type,
'select_test_names' => @svvp_info.select_test_names,
'sequence_test_names' => @svvp_info.sequence_test_names,
'reject_test_names' => @svvp_info.reject_test_names
}
else
driver = drivers.first
{
'name' => driver.name,
'type' => driver.type,
'select_test_names' => driver.select_test_names,
'sequence_test_names' => [],
'reject_test_names' => driver.reject_test_names
}
end
@project.options.test.svvp ? svvp_target : whql_target
end

def svvp_target
primary_entry = @platform_clients.primary_entry
raise InvalidConfigFile, 'SVVP platform is missing a sut client' if primary_entry.nil?

{
'name' => primary_entry['name'],
'type' => @svvp_info.type,
'select_test_names' => @svvp_info.select_test_names,
'sequence_test_names' => @svvp_info.sequence_test_names,
'reject_test_names' => @svvp_info.reject_test_names
}
end

def whql_target
driver = drivers.first
{
'name' => driver.name,
'type' => driver.type,
'select_test_names' => driver.select_test_names,
'sequence_test_names' => [],
'reject_test_names' => driver.reject_test_names
}
end

sig { params(logger: MultiLogger, options: CLI).returns(Models::HLKPlatform) }
Expand All @@ -168,16 +191,17 @@ def run_studio(scope, run_opts = {})

def run_clients(scope, run_opts = {})
@clients = {}
@project.engine_platform.clients.each_value do |client|
@clients[client.name] = @project.setup_manager.run_hck_client(scope, @studio, client.name, run_opts)
@platform_clients.entries.each { |client| start_client(scope, client, run_opts) }
raise InvalidConfigFile, 'Clients configuration for this platform is incorrect' if @clients.empty?
end

break if @project.options.test.svvp
break unless @drivers.any?(&:support)
end
return unless @clients.empty?
def start_client(scope, client, run_opts)
name = client['name']
role = client['role']
return if !PRIMARY_ROLES.include?(role) && [email protected] && @drivers.none?(&:support)

raise InvalidConfigFile, 'Clients configuration for \
this platform is incorrect'
@logger.info("Starting client #{name} (role: #{role})")
@clients[name] = @project.setup_manager.run_hck_client(scope, @studio, name, run_opts)
end

def post_start_commands
Expand Down Expand Up @@ -296,14 +320,16 @@ def pause_run
end

def prepare_tests
client, support = @clients.values
client = primary_client
aux_clients = aux_clients_by_hlk_role

@tests = Tests.new(client, support, @project, client.target, @studio.tools)
@tests = Tests.new(client, @project, client.target, @studio.tools, aux_clients: aux_clients)

if client.target.nil?
raise EngineError, 'HLK test target is not defined' unless @project.options.test.manual

@project.logger.info('HLK test target is not defined, allow in manual mode')
return
end

@test_list = @tests.update_tests(log: true)
Expand Down Expand Up @@ -434,5 +460,29 @@ def run
def result_uploader_needed?
true
end

private

sig { returns(T::Hash[String, T::Array[HCKClient]]) }
def aux_clients_by_hlk_role
@platform_clients.entries
.reject { |e| PRIMARY_ROLES.include?(e['role']) }
.each_with_object({}) do |e, result|
hlk_role = HLK_ROLE_MAP[e['role']]
client = @clients[e['name']]
(result[hlk_role] ||= []) << client if hlk_role && client
end
Comment thread
elizashurov marked this conversation as resolved.
end

sig { returns(HCKClient) }
def primary_client
entry = @platform_clients.primary_entry
raise InvalidConfigFile, 'Platform is missing a primary client (sut or dut)' if entry.nil?

client = @clients[entry['name']]
raise InvalidConfigFile, "Client #{entry['name']} was not started" if client.nil?

client
end
end
end
117 changes: 117 additions & 0 deletions lib/engines/hcktest/platform_clients.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# typed: true
Comment thread
elizashurov marked this conversation as resolved.
# frozen_string_literal: true

# AutoHCK module
module AutoHCK
# Reads client roles from a platform JSON and exposes helpers used by the engine.
class PlatformClients
extend T::Sig

ClientEntry = T.type_alias { T::Hash[String, T.untyped] }

# Allowed role sets for WHQL platforms.
WHQL_CONFIGURATIONS = [
[Models::ClientRole::Dut],
[Models::ClientRole::Dut, Models::ClientRole::Support]
].freeze

# Minimum roles required for SVVP. Extra stress clients are fine.
SVVP_REQUIRED_ROLES = [Models::ClientRole::Sut, Models::ClientRole::Master].freeze

# MC and SC join the pool but skip driver install and HLK target registration.
POOL_ONLY_ROLES = [Models::ClientRole::Master, Models::ClientRole::Stress].freeze

sig do
params(
platform: Models::HLKPlatform,
logger: T.any(MultiLogger, ::Logger)
).void
end
def initialize(platform, logger:)
@logger = logger
@entries = build_entries(platform.clients)
validate!
end

# All clients in platform order.
attr_reader :entries

# Role for a given machine name.
sig { params(name: String).returns(Models::ClientRole) }
def role_for(name)
entry = @entries.find { |e| e['name'] == name }
raise InvalidConfigFile, "Unknown client #{name} in platform configuration" if entry.nil?

entry.fetch('role')
end

# First entry whose role matches (nil if not found).
sig { params(role: Models::ClientRole).returns(T.nilable(ClientEntry)) }
def entry_for_role(role)
@entries.find { |e| e['role'] == role }
end

# The primary client entry — SUT for SVVP, DUT for WHQL.
sig { returns(T.nilable(ClientEntry)) }
def primary_entry
entry_for_role(Models::ClientRole::Sut) || entry_for_role(Models::ClientRole::Dut)
end

sig { params(name: String).returns(T::Boolean) }
def pool_only?(name)
POOL_ONLY_ROLES.include?(role_for(name))
end

private

sig { params(clients: T::Hash[String, Models::HLKClient]).returns(T::Array[ClientEntry]) }
def build_entries(clients)
clients.map do |key, client|
client_hash = client.serialize
role = resolve_role(client_hash)
client_hash.merge('role' => role, '_key' => key)
end
end

sig { params(client: T::Hash[String, T.untyped]).returns(Models::ClientRole) }
def resolve_role(client)
raw_role = client['role']

if raw_role.nil? || raw_role.to_s.strip.empty?
raise InvalidConfigFile,
"Client '#{client['name']}' is missing a 'role' field in the platform JSON."
end

Models::ClientRole.deserialize(raw_role.strip.downcase)
rescue KeyError
raise InvalidConfigFile, "Client '#{client['name']}' has unknown role #{raw_role.inspect}. " \
"Expected one of: #{Models::ClientRole.values.join(', ')}"
end
Comment thread
elizashurov marked this conversation as resolved.

sig { void }
def validate!
roles = @entries.map { |e| e.fetch('role') }
return if valid_whql_configuration?(roles) || valid_svvp_configuration?(roles)

raise InvalidConfigFile, invalid_roles_message(roles)
end

sig { params(roles: T::Array[Models::ClientRole]).returns(T::Boolean) }
def valid_whql_configuration?(roles)
WHQL_CONFIGURATIONS.any? { |config| roles.sort_by(&:to_s) == config.sort_by(&:to_s) }
end

sig { params(roles: T::Array[Models::ClientRole]).returns(T::Boolean) }
def valid_svvp_configuration?(roles)
SVVP_REQUIRED_ROLES.all? { |role| roles.include?(role) }
end

sig { params(roles: T::Array[Models::ClientRole]).returns(String) }
def invalid_roles_message(roles)
role_list = roles.join(', ')
whql_list = WHQL_CONFIGURATIONS.map { |c| c.join(', ') }.join(' | ')
"Invalid platform client roles [#{role_list}]. " \
"Expected WHQL (#{whql_list}) or SVVP (must include: #{SVVP_REQUIRED_ROLES.join(', ')})."
end
end
end
1 change: 1 addition & 0 deletions lib/engines/hcktest/platforms/PhyWin2016.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"clients": {
"c1": {
"name": "C1",
"role": "dut",
"winrm_port": 4002
}
}
Expand Down
1 change: 1 addition & 0 deletions lib/engines/hcktest/platforms/PhyWin2019.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"clients": {
"c1": {
"name": "CL1",
"role": "dut",
"winrm_port": 4002
}
}
Expand Down
6 changes: 4 additions & 2 deletions lib/engines/hcktest/platforms/Win10_2004x64.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@
"clients": {
"c1": {
"name": "CL1",
"role": "dut",
"cpus": 4,
"memory_gb": 4,
"winrm_addr": "192.168.100.2",
"winrm_addr": "192.168.100.2",
"image": "HLK2004-C1-Win10_2004x64.qcow2"
},
"c2": {
"name": "CL2",
"role": "support",
"cpus": 4,
"memory_gb": 4,
"winrm_addr": "192.168.100.3",
"winrm_addr": "192.168.100.3",
"image": "HLK2004-C2-Win10_2004x64.qcow2"
}
}
Expand Down
2 changes: 2 additions & 0 deletions lib/engines/hcktest/platforms/Win10_2004x86_bios.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
"clients": {
"c1": {
"name": "CL1",
"role": "dut",
"cpus": 4,
"memory_gb": 4,
"winrm_addr": "192.168.100.2",
"image": "HLK2004-C1-Win10_2004x86.qcow2"
},
"c2": {
"name": "CL2",
"role": "support",
"cpus": 4,
"memory_gb": 4,
"winrm_addr": "192.168.100.3",
Expand Down
2 changes: 2 additions & 0 deletions lib/engines/hcktest/platforms/Win10_22H2x64.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
"clients": {
"c1": {
"name": "CL1",
"role": "dut",
"cpus": 4,
"memory_gb": 8,
"winrm_addr": "192.168.100.2",
"image": "HLK2004-C1-Win10_22H2x64.qcow2"
},
"c2": {
"name": "CL2",
"role": "support",
"cpus": 4,
"memory_gb": 8,
"winrm_addr": "192.168.100.3",
Expand Down
2 changes: 2 additions & 0 deletions lib/engines/hcktest/platforms/Win10_22H2x86_bios.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
"clients": {
"c1": {
"name": "CL1",
"role": "dut",
"cpus": 4,
"memory_gb": 4,
"winrm_addr": "192.168.100.2",
"image": "HLK2004-C1-Win10_22H2x86.qcow2"
},
"c2": {
"name": "CL2",
"role": "support",
"cpus": 4,
"memory_gb": 4,
"winrm_addr": "192.168.100.3",
Expand Down
6 changes: 4 additions & 2 deletions lib/engines/hcktest/platforms/Win11_22H2x64_viommu.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@
"clients": {
"c1": {
"name": "CL1",
"role": "dut",
"cpus": 4,
"memory_gb": 8,
"winrm_addr": "192.168.100.2",
"winrm_addr": "192.168.100.2",
"image": "HLK11_22H2-C1-Win11_22H2x64-viommu.qcow2"
},
"c2": {
"name": "CL2",
"role": "support",
"cpus": 4,
"memory_gb": 8,
"winrm_addr": "192.168.100.3",
"winrm_addr": "192.168.100.3",
"image": "HLK11_22H2-C2-Win11_22H2x64-viommu.qcow2"
}
}
Expand Down
Loading
Loading