mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-07 05:42:46 +08:00
585 lines
15 KiB
Go
585 lines
15 KiB
Go
package uixt
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/httprunner/httprunner/v5/uixt/option"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// Helper function to clean up cache before each test
|
|
func setupTest() {
|
|
CleanupAllDrivers()
|
|
}
|
|
|
|
func TestGetOrCreateXTDriver_EmptySerial_AutoDetect(t *testing.T) {
|
|
setupTest()
|
|
|
|
config := DriverCacheConfig{
|
|
Platform: "android",
|
|
Serial: "", // Empty serial will be auto-detected by NewAndroidDevice
|
|
}
|
|
|
|
driver, err := GetOrCreateXTDriver(config)
|
|
// Auto-detection may succeed or fail depending on test environment
|
|
if err != nil {
|
|
// If device creation fails (no devices or multiple devices)
|
|
assert.Nil(t, driver)
|
|
assert.Contains(t, err.Error(), "failed to create XTDriver")
|
|
} else {
|
|
// If device creation succeeds (exactly one device connected)
|
|
assert.NotNil(t, driver)
|
|
// Verify that a driver was created and cached with actual serial
|
|
drivers := ListCachedDrivers()
|
|
assert.Len(t, drivers, 1)
|
|
assert.NotEmpty(t, drivers[0].Key) // Serial should be populated with actual device serial
|
|
}
|
|
}
|
|
|
|
func TestGetOrCreateXTDriver_EmptySerial_DefaultPlatform(t *testing.T) {
|
|
setupTest()
|
|
|
|
config := DriverCacheConfig{
|
|
Platform: "", // Empty platform should default to android in createXTDriverWithConfig
|
|
Serial: "", // Empty serial will be auto-detected by NewAndroidDevice
|
|
}
|
|
|
|
driver, err := GetOrCreateXTDriver(config)
|
|
// Device creation may succeed or fail depending on test environment
|
|
if err != nil {
|
|
// If device creation fails (no devices or multiple devices)
|
|
assert.Nil(t, driver)
|
|
assert.Contains(t, err.Error(), "failed to create XTDriver")
|
|
} else {
|
|
// If device creation succeeds (exactly one device connected)
|
|
assert.NotNil(t, driver)
|
|
// Verify that a driver was created and cached with actual serial
|
|
drivers := ListCachedDrivers()
|
|
assert.Len(t, drivers, 1)
|
|
assert.NotEmpty(t, drivers[0].Key) // Serial should be populated with actual device serial
|
|
}
|
|
}
|
|
|
|
func TestGetOrCreateXTDriver_WithUnifiedDeviceOptions(t *testing.T) {
|
|
setupTest()
|
|
|
|
// Test creating driver config with unified DeviceOptions
|
|
deviceOpts := option.NewDeviceOptions(
|
|
option.WithPlatform("android"),
|
|
option.WithDeviceSerialNumber("test_device_001"),
|
|
option.WithDeviceUIA2(true),
|
|
)
|
|
|
|
config := DriverCacheConfig{
|
|
Platform: deviceOpts.Platform,
|
|
Serial: deviceOpts.GetSerial(),
|
|
DeviceOpts: deviceOpts,
|
|
AIOptions: []option.AIServiceOption{
|
|
option.WithCVService(option.CVServiceTypeVEDEM),
|
|
},
|
|
}
|
|
|
|
// Verify config is properly constructed
|
|
assert.Equal(t, "android", config.Platform)
|
|
assert.Equal(t, "test_device_001", config.Serial)
|
|
assert.NotNil(t, config.DeviceOpts)
|
|
assert.Equal(t, "android", config.DeviceOpts.Platform)
|
|
assert.Equal(t, "test_device_001", config.DeviceOpts.GetSerial())
|
|
}
|
|
|
|
func TestGetOrCreateXTDriver_DifferentPlatformConfigs(t *testing.T) {
|
|
setupTest()
|
|
|
|
// Test Android config
|
|
androidOpts := option.NewDeviceOptions(
|
|
option.WithDeviceSerialNumber("android_001"),
|
|
option.WithDeviceUIA2(true),
|
|
)
|
|
androidConfig := DriverCacheConfig{
|
|
Platform: "android",
|
|
Serial: "android_001",
|
|
DeviceOpts: androidOpts,
|
|
}
|
|
assert.Equal(t, "android", androidConfig.DeviceOpts.Platform)
|
|
|
|
// Test iOS config
|
|
iosOpts := option.NewDeviceOptions(
|
|
option.WithDeviceUDID("ios_001"),
|
|
option.WithDeviceWDAPort(8100),
|
|
)
|
|
iosConfig := DriverCacheConfig{
|
|
Platform: "ios",
|
|
Serial: "ios_001",
|
|
DeviceOpts: iosOpts,
|
|
}
|
|
assert.Equal(t, "ios", iosConfig.DeviceOpts.Platform)
|
|
|
|
// Test Harmony config
|
|
harmonyOpts := option.NewDeviceOptions(
|
|
option.WithDeviceConnectKey("harmony_001"),
|
|
)
|
|
harmonyConfig := DriverCacheConfig{
|
|
Platform: "harmony",
|
|
Serial: "harmony_001",
|
|
DeviceOpts: harmonyOpts,
|
|
}
|
|
assert.Equal(t, "harmony", harmonyConfig.DeviceOpts.Platform)
|
|
|
|
// Test Browser config
|
|
browserOpts := option.NewDeviceOptions(
|
|
option.WithDeviceBrowserID("browser_001"),
|
|
option.WithDeviceBrowserPageSize(1920, 1080),
|
|
)
|
|
browserConfig := DriverCacheConfig{
|
|
Platform: "browser",
|
|
Serial: "browser_001",
|
|
DeviceOpts: browserOpts,
|
|
}
|
|
assert.Equal(t, "browser", browserConfig.DeviceOpts.Platform)
|
|
}
|
|
|
|
func TestRegisterXTDriver_EmptySerial(t *testing.T) {
|
|
setupTest()
|
|
|
|
err := RegisterXTDriver("", nil)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "serial cannot be empty")
|
|
}
|
|
|
|
func TestRegisterXTDriver_NilDriver(t *testing.T) {
|
|
setupTest()
|
|
|
|
err := RegisterXTDriver("test_serial", nil)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "driver cannot be nil")
|
|
}
|
|
|
|
func TestRegisterXTDriver_Success(t *testing.T) {
|
|
setupTest()
|
|
|
|
// Create a minimal XTDriver for testing
|
|
xtDriver := &XTDriver{}
|
|
|
|
// Register external driver
|
|
err := RegisterXTDriver("external_001", xtDriver)
|
|
require.NoError(t, err)
|
|
|
|
// Verify driver is cached
|
|
drivers := ListCachedDrivers()
|
|
assert.Len(t, drivers, 1)
|
|
assert.Equal(t, "external_001", drivers[0].Key)
|
|
assert.Equal(t, int32(1), drivers[0].RefCount)
|
|
assert.Equal(t, xtDriver, drivers[0].Item)
|
|
}
|
|
|
|
func TestReleaseXTDriver_NonExistentSerial(t *testing.T) {
|
|
setupTest()
|
|
|
|
// Release non-existent driver should not error
|
|
err := ReleaseXTDriver("non_existent")
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestReleaseXTDriver_CleanupWhenZero(t *testing.T) {
|
|
setupTest()
|
|
|
|
// Register driver
|
|
xtDriver := &XTDriver{}
|
|
err := RegisterXTDriver("cleanup_test", xtDriver)
|
|
require.NoError(t, err)
|
|
|
|
// Verify driver is cached
|
|
drivers := ListCachedDrivers()
|
|
assert.Len(t, drivers, 1)
|
|
|
|
// Release driver (ref count goes to 0)
|
|
err = ReleaseXTDriver("cleanup_test")
|
|
require.NoError(t, err)
|
|
|
|
// Verify driver is removed from cache
|
|
drivers = ListCachedDrivers()
|
|
assert.Len(t, drivers, 0)
|
|
}
|
|
|
|
func TestCleanupAllDrivers(t *testing.T) {
|
|
setupTest()
|
|
|
|
// Create multiple drivers
|
|
xtDriver1 := &XTDriver{}
|
|
xtDriver2 := &XTDriver{}
|
|
xtDriver3 := &XTDriver{}
|
|
|
|
err := RegisterXTDriver("cleanup_all_1", xtDriver1)
|
|
require.NoError(t, err)
|
|
err = RegisterXTDriver("cleanup_all_2", xtDriver2)
|
|
require.NoError(t, err)
|
|
err = RegisterXTDriver("cleanup_all_3", xtDriver3)
|
|
require.NoError(t, err)
|
|
|
|
// Verify all drivers are cached
|
|
drivers := ListCachedDrivers()
|
|
assert.Len(t, drivers, 3)
|
|
|
|
// Cleanup all drivers
|
|
CleanupAllDrivers()
|
|
|
|
// Verify cache is empty
|
|
drivers = ListCachedDrivers()
|
|
assert.Len(t, drivers, 0)
|
|
}
|
|
|
|
func TestListCachedDrivers_Empty(t *testing.T) {
|
|
setupTest()
|
|
|
|
drivers := ListCachedDrivers()
|
|
assert.Len(t, drivers, 0)
|
|
}
|
|
|
|
func TestListCachedDrivers_Multiple(t *testing.T) {
|
|
setupTest()
|
|
|
|
// Register multiple drivers
|
|
xtDriver1 := &XTDriver{}
|
|
xtDriver2 := &XTDriver{}
|
|
|
|
err := RegisterXTDriver("list_test_1", xtDriver1)
|
|
require.NoError(t, err)
|
|
err = RegisterXTDriver("list_test_2", xtDriver2)
|
|
require.NoError(t, err)
|
|
|
|
// List drivers
|
|
drivers := ListCachedDrivers()
|
|
assert.Len(t, drivers, 2)
|
|
|
|
// Verify driver information
|
|
serials := make(map[string]bool)
|
|
for _, cached := range drivers {
|
|
serials[cached.Key] = true
|
|
assert.Equal(t, int32(1), cached.RefCount)
|
|
assert.NotNil(t, cached.Item)
|
|
}
|
|
assert.True(t, serials["list_test_1"])
|
|
assert.True(t, serials["list_test_2"])
|
|
}
|
|
|
|
func TestDriverCacheConfig_WithoutDeviceOpts(t *testing.T) {
|
|
setupTest()
|
|
|
|
// Test creating config without DeviceOpts
|
|
config := DriverCacheConfig{
|
|
Platform: "android",
|
|
Serial: "default_test",
|
|
// DeviceOpts is nil
|
|
}
|
|
|
|
// Verify config structure
|
|
assert.Equal(t, "android", config.Platform)
|
|
assert.Equal(t, "default_test", config.Serial)
|
|
assert.Nil(t, config.DeviceOpts)
|
|
}
|
|
|
|
func TestDriverCacheConfig_DefaultAIOptions(t *testing.T) {
|
|
setupTest()
|
|
|
|
deviceOpts := option.NewDeviceOptions(
|
|
option.WithPlatform("android"),
|
|
option.WithDeviceSerialNumber("ai_test"),
|
|
)
|
|
|
|
config := DriverCacheConfig{
|
|
Platform: deviceOpts.Platform,
|
|
Serial: deviceOpts.GetSerial(),
|
|
DeviceOpts: deviceOpts,
|
|
// AIOptions is empty, should use default
|
|
}
|
|
|
|
// Verify config structure
|
|
assert.Equal(t, "android", config.Platform)
|
|
assert.Equal(t, "ai_test", config.Serial)
|
|
assert.NotNil(t, config.DeviceOpts)
|
|
assert.Len(t, config.AIOptions, 0) // Empty AI options
|
|
}
|
|
|
|
func TestConcurrentAccess(t *testing.T) {
|
|
setupTest()
|
|
|
|
// Test concurrent access to cache with GetOrCreateXTDriver
|
|
const numGoroutines = 10
|
|
const serial = "concurrent_test"
|
|
|
|
deviceOpts := option.NewDeviceOptions(
|
|
option.WithPlatform("android"),
|
|
option.WithDeviceSerialNumber(serial),
|
|
)
|
|
config := DriverCacheConfig{
|
|
Platform: deviceOpts.Platform,
|
|
Serial: deviceOpts.GetSerial(),
|
|
DeviceOpts: deviceOpts,
|
|
}
|
|
|
|
// Create drivers concurrently - this tests the cache's ability to handle concurrent access
|
|
results := make(chan *XTDriver, numGoroutines)
|
|
errors := make(chan error, numGoroutines)
|
|
|
|
for i := 0; i < numGoroutines; i++ {
|
|
go func(index int) {
|
|
driver, err := GetOrCreateXTDriver(config)
|
|
results <- driver
|
|
errors <- err
|
|
}(i)
|
|
}
|
|
|
|
// Collect results
|
|
var drivers []*XTDriver
|
|
var errorCount int
|
|
for i := 0; i < numGoroutines; i++ {
|
|
driver := <-results
|
|
err := <-errors
|
|
if err != nil {
|
|
errorCount++
|
|
} else {
|
|
drivers = append(drivers, driver)
|
|
}
|
|
}
|
|
|
|
// All operations should succeed (or all fail if device creation fails)
|
|
if errorCount == 0 {
|
|
// If device creation succeeds, all drivers should be the same instance
|
|
assert.Len(t, drivers, numGoroutines)
|
|
firstDriver := drivers[0]
|
|
for _, driver := range drivers[1:] {
|
|
assert.Equal(t, firstDriver, driver)
|
|
}
|
|
|
|
// Verify ref count
|
|
cachedDrivers := ListCachedDrivers()
|
|
assert.Len(t, cachedDrivers, 1)
|
|
assert.Equal(t, int32(numGoroutines), cachedDrivers[0].RefCount)
|
|
} else {
|
|
// If device creation fails (expected in test environment), all should fail
|
|
assert.Equal(t, numGoroutines, errorCount)
|
|
assert.Len(t, drivers, 0)
|
|
}
|
|
}
|
|
|
|
func TestIntegrationExample_BasicUsage(t *testing.T) {
|
|
setupTest()
|
|
|
|
// Example 1: Basic external driver registration using unified DeviceOptions
|
|
deviceOpts := option.NewDeviceOptions(
|
|
option.WithPlatform("android"),
|
|
option.WithDeviceSerialNumber("integration_001"),
|
|
option.WithDeviceUIA2(true),
|
|
)
|
|
|
|
config := DriverCacheConfig{
|
|
Platform: deviceOpts.Platform,
|
|
Serial: deviceOpts.GetSerial(),
|
|
DeviceOpts: deviceOpts,
|
|
AIOptions: []option.AIServiceOption{
|
|
option.WithCVService(option.CVServiceTypeVEDEM),
|
|
},
|
|
}
|
|
|
|
// Verify config is properly constructed
|
|
assert.Equal(t, "android", config.Platform)
|
|
assert.Equal(t, "integration_001", config.Serial)
|
|
assert.NotNil(t, config.DeviceOpts)
|
|
assert.Len(t, config.AIOptions, 1)
|
|
}
|
|
|
|
func TestIntegrationExample_TraditionalWay(t *testing.T) {
|
|
setupTest()
|
|
|
|
// Example 1b: Traditional way (still supported)
|
|
xtDriver := &XTDriver{}
|
|
|
|
// Register using cache API directly
|
|
err := RegisterXTDriver("integration_002", xtDriver)
|
|
require.NoError(t, err)
|
|
|
|
// Verify registration
|
|
drivers := ListCachedDrivers()
|
|
assert.Len(t, drivers, 1)
|
|
assert.Equal(t, "integration_002", drivers[0].Key)
|
|
|
|
// Clean up
|
|
err = ReleaseXTDriver("integration_002")
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestIntegrationExample_MultipleDevices(t *testing.T) {
|
|
setupTest()
|
|
|
|
// Test multiple devices like in external_driver_example.go
|
|
devices := []struct {
|
|
platform string
|
|
serial string
|
|
opts *option.DeviceOptions
|
|
}{
|
|
{
|
|
platform: "android",
|
|
serial: "multi_android_001",
|
|
opts: option.NewDeviceOptions(
|
|
option.WithDeviceSerialNumber("multi_android_001"),
|
|
option.WithDeviceUIA2(true),
|
|
),
|
|
},
|
|
{
|
|
platform: "ios",
|
|
serial: "multi_ios_001",
|
|
opts: option.NewDeviceOptions(
|
|
option.WithDeviceUDID("multi_ios_001"),
|
|
option.WithDeviceWDAPort(8100),
|
|
),
|
|
},
|
|
{
|
|
platform: "harmony",
|
|
serial: "multi_harmony_001",
|
|
opts: option.NewDeviceOptions(
|
|
option.WithDeviceConnectKey("multi_harmony_001"),
|
|
),
|
|
},
|
|
{
|
|
platform: "browser",
|
|
serial: "multi_browser_001",
|
|
opts: option.NewDeviceOptions(
|
|
option.WithDeviceBrowserID("multi_browser_001"),
|
|
option.WithDeviceBrowserPageSize(1920, 1080),
|
|
),
|
|
},
|
|
}
|
|
|
|
// Create configs for all devices
|
|
var configs []DriverCacheConfig
|
|
for _, device := range devices {
|
|
config := DriverCacheConfig{
|
|
Platform: device.platform,
|
|
Serial: device.serial,
|
|
DeviceOpts: device.opts,
|
|
}
|
|
configs = append(configs, config)
|
|
}
|
|
|
|
// Verify all configs are properly constructed
|
|
assert.Len(t, configs, len(devices))
|
|
|
|
// Verify each device config
|
|
for i, config := range configs {
|
|
assert.Equal(t, devices[i].platform, config.Platform)
|
|
assert.Equal(t, devices[i].serial, config.Serial)
|
|
assert.NotNil(t, config.DeviceOpts)
|
|
assert.Equal(t, devices[i].platform, config.DeviceOpts.Platform)
|
|
}
|
|
}
|
|
|
|
func TestDeviceOptionsIntegration(t *testing.T) {
|
|
setupTest()
|
|
|
|
// Test unified DeviceOptions with different platforms
|
|
testCases := []struct {
|
|
name string
|
|
platform string
|
|
opts []option.DeviceOption
|
|
expected string
|
|
}{
|
|
{
|
|
name: "Android with auto-detection",
|
|
platform: "",
|
|
opts: []option.DeviceOption{
|
|
option.WithDeviceSerialNumber("android_auto"),
|
|
option.WithDeviceUIA2(true),
|
|
},
|
|
expected: "android",
|
|
},
|
|
{
|
|
name: "iOS with auto-detection",
|
|
platform: "",
|
|
opts: []option.DeviceOption{
|
|
option.WithDeviceUDID("ios_auto"),
|
|
option.WithDeviceWDAPort(8100),
|
|
},
|
|
expected: "ios",
|
|
},
|
|
{
|
|
name: "Harmony with auto-detection",
|
|
platform: "",
|
|
opts: []option.DeviceOption{
|
|
option.WithDeviceConnectKey("harmony_auto"),
|
|
},
|
|
expected: "harmony",
|
|
},
|
|
{
|
|
name: "Browser with auto-detection",
|
|
platform: "",
|
|
opts: []option.DeviceOption{
|
|
option.WithDeviceBrowserID("browser_auto"),
|
|
option.WithDeviceBrowserPageSize(1920, 1080),
|
|
},
|
|
expected: "browser",
|
|
},
|
|
{
|
|
name: "Explicit platform setting",
|
|
platform: "android",
|
|
opts: []option.DeviceOption{
|
|
option.WithPlatform("android"),
|
|
option.WithDeviceSerialNumber("explicit_android"),
|
|
},
|
|
expected: "android",
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
deviceOpts := option.NewDeviceOptions(tc.opts...)
|
|
assert.Equal(t, tc.expected, deviceOpts.Platform)
|
|
assert.NotEmpty(t, deviceOpts.GetSerial())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCacheReferenceCountManagement(t *testing.T) {
|
|
setupTest()
|
|
|
|
// Test reference count increment and decrement
|
|
xtDriver := &XTDriver{}
|
|
serial := "ref_count_test"
|
|
|
|
// Register driver
|
|
err := RegisterXTDriver(serial, xtDriver)
|
|
require.NoError(t, err)
|
|
|
|
// Verify initial ref count
|
|
drivers := ListCachedDrivers()
|
|
assert.Len(t, drivers, 1)
|
|
assert.Equal(t, int32(1), drivers[0].RefCount)
|
|
|
|
// Simulate multiple references by getting from cache (which increments ref count)
|
|
if cachedItem, ok := driverCacheManager.Get(serial); ok {
|
|
assert.NotNil(t, cachedItem.Item)
|
|
}
|
|
|
|
// Verify ref count increased
|
|
drivers = ListCachedDrivers()
|
|
assert.Len(t, drivers, 1)
|
|
assert.Equal(t, int32(2), drivers[0].RefCount)
|
|
|
|
// Release once
|
|
err = ReleaseXTDriver(serial)
|
|
require.NoError(t, err)
|
|
|
|
// Verify ref count decreased but driver still cached
|
|
drivers = ListCachedDrivers()
|
|
assert.Len(t, drivers, 1)
|
|
assert.Equal(t, int32(1), drivers[0].RefCount)
|
|
|
|
// Release again
|
|
err = ReleaseXTDriver(serial)
|
|
require.NoError(t, err)
|
|
|
|
// Verify driver removed from cache
|
|
drivers = ListCachedDrivers()
|
|
assert.Len(t, drivers, 0)
|
|
}
|