mirror of
https://github.com/httprunner/httprunner.git
synced 2026-07-06 06:51:23 +08:00
feat: capture pcap file with PID/ProcName/bundleID
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# Release History
|
# Release History
|
||||||
|
|
||||||
## v4.3.1 (2022-12-16)
|
## v4.3.1 (2022-12-22)
|
||||||
|
|
||||||
**go version**
|
**go version**
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
- feat: run xctest before start ios automation
|
- feat: run xctest before start ios automation
|
||||||
- feat: run step with specified loop times
|
- feat: run step with specified loop times
|
||||||
- feat: add options for FindTexts
|
- feat: add options for FindTexts
|
||||||
- feat: capture pcap file for iOS, including CLI `hrp ios pcap` and option `uixt.WithIOSPcapOn(true)`
|
- feat: capture pcap file for iOS, including CLI `hrp ios pcap` and option `uixt.WithIOSPcapOptions(...)`
|
||||||
- feat: add performance monitor for iOS, including CLI `hrp ios perf` and options `uixt.WithIOSPerfOptions(...)`
|
- feat: add performance monitor for iOS, including CLI `hrp ios perf` and options `uixt.WithIOSPerfOptions(...)`
|
||||||
- refactor: move all UI APIs to uixt pkg
|
- refactor: move all UI APIs to uixt pkg
|
||||||
- docs: add examples for UI APIs
|
- docs: add examples for UI APIs
|
||||||
|
|||||||
@@ -64,7 +64,12 @@ func TestIOSDouyinWorldCupLive(t *testing.T) {
|
|||||||
uixt.WithIOSPerfNetwork(true),
|
uixt.WithIOSPerfNetwork(true),
|
||||||
// uixt.WithIOSPerfBundleID("com.ss.iphone.ugc.Aweme"),
|
// uixt.WithIOSPerfBundleID("com.ss.iphone.ugc.Aweme"),
|
||||||
),
|
),
|
||||||
uixt.WithIOSPcapOn(true),
|
uixt.WithIOSPcapOptions(
|
||||||
|
// uixt.WithIOSPcapAll(true),
|
||||||
|
// uixt.WithIOSPcapPID(1234),
|
||||||
|
// uixt.WithIOSPcapProcName("Awe"),
|
||||||
|
uixt.WithIOSPcapBundleID("com.ss.iphone.ugc.Aweme"),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
TestSteps: []hrp.IStep{
|
TestSteps: []hrp.IStep{
|
||||||
hrp.NewStep("启动抖音").
|
hrp.NewStep("启动抖音").
|
||||||
|
|||||||
@@ -18,8 +18,23 @@ var pcapCmd = &cobra.Command{
|
|||||||
Use: "pcap",
|
Use: "pcap",
|
||||||
Short: "capture ios network packets",
|
Short: "capture ios network packets",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
pcapOptions := []uixt.IOSPcapOption{}
|
||||||
|
if pid > 0 {
|
||||||
|
pcapOptions = append(pcapOptions, uixt.WithIOSPcapPID(pid))
|
||||||
|
}
|
||||||
|
if procName != "" {
|
||||||
|
pcapOptions = append(pcapOptions, uixt.WithIOSPcapProcName(procName))
|
||||||
|
}
|
||||||
|
if bundleID != "" {
|
||||||
|
pcapOptions = append(pcapOptions, uixt.WithIOSPcapBundleID(bundleID))
|
||||||
|
}
|
||||||
|
if len(pcapOptions) == 0 {
|
||||||
|
pcapOptions = append(pcapOptions, uixt.WithIOSPcapAll(true))
|
||||||
|
}
|
||||||
|
|
||||||
device, err := uixt.NewIOSDevice(
|
device, err := uixt.NewIOSDevice(
|
||||||
uixt.WithUDID(udid),
|
uixt.WithUDID(udid),
|
||||||
|
uixt.WithIOSPcapOptions(pcapOptions...),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("failed to init ios device")
|
log.Fatal().Err(err).Msg("failed to init ios device")
|
||||||
@@ -50,10 +65,17 @@ var pcapCmd = &cobra.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var timeDuration int
|
var (
|
||||||
|
timeDuration int
|
||||||
|
pid int
|
||||||
|
procName string
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
pcapCmd.Flags().StringVarP(&udid, "udid", "u", "", "specify device by udid")
|
pcapCmd.Flags().StringVarP(&udid, "udid", "u", "", "specify device by udid")
|
||||||
|
pcapCmd.Flags().IntVarP(&pid, "pid", "p", 0, "specify process ID")
|
||||||
|
pcapCmd.Flags().StringVarP(&procName, "procName", "n", "", "specify process name")
|
||||||
|
pcapCmd.Flags().StringVarP(&bundleID, "bundleID", "b", "", "specify bundle ID")
|
||||||
pcapCmd.Flags().IntVarP(&timeDuration, "duration", "t", 10, "specify time duraion in seconds")
|
pcapCmd.Flags().IntVarP(&timeDuration, "duration", "t", 10, "specify time duraion in seconds")
|
||||||
iosRootCmd.AddCommand(pcapCmd)
|
iosRootCmd.AddCommand(pcapCmd)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
uuid "github.com/satori/go.uuid"
|
uuid "github.com/satori/go.uuid"
|
||||||
"howett.net/plist"
|
"howett.net/plist"
|
||||||
|
|
||||||
@@ -549,12 +550,38 @@ func (d *device) GetInterfaceOrientation() (orientation libimobiledevice.Orienta
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *device) PcapStart() (lines <-chan []byte, err error) {
|
func (d *device) PcapStart(opts ...PcapOption) (lines <-chan []byte, err error) {
|
||||||
|
pcapOptions := &PcapOptions{}
|
||||||
|
for _, fn := range opts {
|
||||||
|
fn(pcapOptions)
|
||||||
|
}
|
||||||
|
log.Info().Interface("options", pcapOptions).Msg("pcap start")
|
||||||
|
|
||||||
|
// wait until get pid for bundle id
|
||||||
|
if pcapOptions.BundleID != "" {
|
||||||
|
instruments, err := d.newInstrumentsService()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("get pid by bundle id failed: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
pid, err := instruments.getPidByBundleID(pcapOptions.BundleID)
|
||||||
|
if err != nil {
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pcapOptions.Pid = pid
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if d.pcapd == nil {
|
if d.pcapd == nil {
|
||||||
if _, err = d.lockdownService(); err != nil {
|
if _, err = d.lockdownService(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if d.pcapd, err = d.lockdown.PcapdService(); err != nil {
|
if d.pcapd, err = d.lockdown.PcapdService(
|
||||||
|
pcapOptions.Pid, pcapOptions.ProcName); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ type Device interface {
|
|||||||
Syslog() (lines <-chan string, err error)
|
Syslog() (lines <-chan string, err error)
|
||||||
SyslogStop()
|
SyslogStop()
|
||||||
|
|
||||||
PcapStart() (packet <-chan []byte, err error)
|
PcapStart(opts ...PcapOption) (packet <-chan []byte, err error)
|
||||||
PcapStop()
|
PcapStop()
|
||||||
|
|
||||||
Reboot() error
|
Reboot() error
|
||||||
|
|||||||
@@ -449,12 +449,12 @@ func (c *lockdown) SyslogRelayService() (syslogRelay SyslogRelay, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *lockdown) PcapdService() (pcapd Pcapd, err error) {
|
func (c *lockdown) PcapdService(targetPID int, targetProcName string) (pcapd Pcapd, err error) {
|
||||||
var innerConn InnerConn
|
var innerConn InnerConn
|
||||||
if innerConn, err = c._startService(libimobiledevice.PcapdServiceName, nil); err != nil {
|
if innerConn, err = c._startService(libimobiledevice.PcapdServiceName, nil); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
pcapdClient := libimobiledevice.NewPcapdClient(innerConn)
|
pcapdClient := libimobiledevice.NewPcapdClient(innerConn, targetPID, targetProcName)
|
||||||
return newPcapdClient(pcapdClient), nil
|
return newPcapdClient(pcapdClient), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,39 @@ import (
|
|||||||
"github.com/httprunner/httprunner/v4/hrp/pkg/gidevice/pkg/libimobiledevice"
|
"github.com/httprunner/httprunner/v4/hrp/pkg/gidevice/pkg/libimobiledevice"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type PcapOptions struct {
|
||||||
|
All bool // capture all packets
|
||||||
|
Pid int // capture packets from specific PID
|
||||||
|
ProcName string // capture packets from specific process name
|
||||||
|
BundleID string // convert to PID first, then capture packets from the PID
|
||||||
|
}
|
||||||
|
|
||||||
|
type PcapOption func(*PcapOptions)
|
||||||
|
|
||||||
|
func WithPcapAll(all bool) PcapOption {
|
||||||
|
return func(opt *PcapOptions) {
|
||||||
|
opt.All = all
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithPcapProcName(procName string) PcapOption {
|
||||||
|
return func(opt *PcapOptions) {
|
||||||
|
opt.ProcName = procName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithPcapPID(pid int) PcapOption {
|
||||||
|
return func(opt *PcapOptions) {
|
||||||
|
opt.Pid = pid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithPcapBundleID(bundleID string) PcapOption {
|
||||||
|
return func(opt *PcapOptions) {
|
||||||
|
opt.BundleID = bundleID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type pcapdClient struct {
|
type pcapdClient struct {
|
||||||
stop chan struct{}
|
stop chan struct{}
|
||||||
c *libimobiledevice.PcapdClient
|
c *libimobiledevice.PcapdClient
|
||||||
@@ -38,6 +71,10 @@ func (c *pcapdClient) Packet() <-chan []byte {
|
|||||||
close(packetCh)
|
close(packetCh)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if raw == nil {
|
||||||
|
// filtered packet
|
||||||
|
continue
|
||||||
|
}
|
||||||
res, err := c.c.CreatePacket(raw)
|
res, err := c.c.CreatePacket(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("failed to create packet")
|
log.Println("failed to create packet")
|
||||||
|
|||||||
66
hrp/pkg/gidevice/pcapd_test.go
Normal file
66
hrp/pkg/gidevice/pcapd_test.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
//go:build localtest
|
||||||
|
|
||||||
|
package gidevice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPcapWithPID(t *testing.T) {
|
||||||
|
setupLockdownSrv(t)
|
||||||
|
|
||||||
|
data, err := dev.PcapStart(WithPcapPID(1234))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
timer := time.NewTimer(time.Duration(time.Second * 10))
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
dev.PcapStop()
|
||||||
|
return
|
||||||
|
case d := <-data:
|
||||||
|
fmt.Println(string(d))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPcapWithProcName(t *testing.T) {
|
||||||
|
setupLockdownSrv(t)
|
||||||
|
|
||||||
|
data, err := dev.PcapStart(WithPcapProcName("Awe"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
timer := time.NewTimer(time.Duration(time.Second * 10))
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
dev.PcapStop()
|
||||||
|
return
|
||||||
|
case d := <-data:
|
||||||
|
fmt.Println(string(d))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPcapWithBundleID(t *testing.T) {
|
||||||
|
setupLockdownSrv(t)
|
||||||
|
|
||||||
|
data, err := dev.PcapStart(WithPcapBundleID("com.ss.iphone.ugc.Aweme"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
timer := time.NewTimer(time.Duration(time.Second * 10))
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
dev.PcapStop()
|
||||||
|
return
|
||||||
|
case d := <-data:
|
||||||
|
fmt.Println(string(d))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -159,22 +159,3 @@ func TestPerfAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPcap(t *testing.T) {
|
|
||||||
setupLockdownSrv(t)
|
|
||||||
|
|
||||||
data, err := dev.PcapStart()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
timer := time.NewTimer(time.Duration(time.Second * 10))
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-timer.C:
|
|
||||||
dev.PcapStop()
|
|
||||||
return
|
|
||||||
case d := <-data:
|
|
||||||
fmt.Println(string(d))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/lunixbochs/struc"
|
"github.com/lunixbochs/struc"
|
||||||
@@ -12,8 +14,23 @@ import (
|
|||||||
|
|
||||||
const PcapdServiceName = "com.apple.pcapd"
|
const PcapdServiceName = "com.apple.pcapd"
|
||||||
|
|
||||||
func NewPcapdClient(innerConn InnerConn) *PcapdClient {
|
func filterPacket(pid int, procName string) func(*IOSPacketHeader) bool {
|
||||||
|
return func(iph *IOSPacketHeader) bool {
|
||||||
|
if pid > 0 {
|
||||||
|
return iph.Pid == int32(pid) ||
|
||||||
|
iph.Pid2 == int32(pid)
|
||||||
|
}
|
||||||
|
if procName != "" {
|
||||||
|
return strings.HasPrefix(iph.ProcName, procName) ||
|
||||||
|
strings.HasPrefix(iph.ProcName2, procName)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPcapdClient(innerConn InnerConn, targetPID int, targetProcName string) *PcapdClient {
|
||||||
return &PcapdClient{
|
return &PcapdClient{
|
||||||
|
filter: filterPacket(targetPID, targetProcName),
|
||||||
client: newServicePacketClient(innerConn),
|
client: newServicePacketClient(innerConn),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,6 +65,11 @@ func (c *PcapdClient) ReceivePacket() (respPkt Packet, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
PacketHeaderSize = uint32(95)
|
||||||
|
)
|
||||||
|
|
||||||
|
// ref: https://github.com/danielpaulus/go-ios/blob/fc943b9d236571f9775f5c593e3d49bb5bd67afd/ios/pcap/pcap.go#L27
|
||||||
type IOSPacketHeader struct {
|
type IOSPacketHeader struct {
|
||||||
HdrSize uint32 `struc:"uint32,big"`
|
HdrSize uint32 `struc:"uint32,big"`
|
||||||
Version uint8 `struc:"uint8,big"`
|
Version uint8 `struc:"uint8,big"`
|
||||||
@@ -78,12 +100,24 @@ func (c *PcapdClient) GetPacket(buf []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// support ios 15 beta4
|
||||||
|
if iph.HdrSize > PacketHeaderSize {
|
||||||
|
buf := make([]byte, iph.HdrSize-PacketHeaderSize)
|
||||||
|
_, err := io.ReadFull(preader, buf)
|
||||||
|
if err != nil {
|
||||||
|
return []byte{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
packet, err := ioutil.ReadAll(preader)
|
packet, err := ioutil.ReadAll(preader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return packet, err
|
return packet, err
|
||||||
}
|
}
|
||||||
if iph.FramePreLength == 0 {
|
if iph.FramePreLength == 0 {
|
||||||
ext := []byte{0xbe, 0xfe, 0xbe, 0xfe, 0xbe, 0xfe, 0xbe, 0xfe, 0xbe, 0xfe, 0xbe, 0xfe, 0x08, 0x00}
|
ext := []byte{
|
||||||
|
0xbe, 0xfe, 0xbe, 0xfe, 0xbe, 0xfe, 0xbe, 0xfe,
|
||||||
|
0xbe, 0xfe, 0xbe, 0xfe, 0x08, 0x00,
|
||||||
|
}
|
||||||
return append(ext, packet...), nil
|
return append(ext, packet...), nil
|
||||||
}
|
}
|
||||||
return packet, nil
|
return packet, nil
|
||||||
|
|||||||
@@ -66,6 +66,15 @@ var (
|
|||||||
WithIOSPerfSystemAttributes = gidevice.WithPerfSystemAttributes
|
WithIOSPerfSystemAttributes = gidevice.WithPerfSystemAttributes
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type IOSPcapOption = gidevice.PcapOption
|
||||||
|
|
||||||
|
var (
|
||||||
|
WithIOSPcapAll = gidevice.WithPcapAll
|
||||||
|
WithIOSPcapPID = gidevice.WithPcapPID
|
||||||
|
WithIOSPcapProcName = gidevice.WithPcapProcName
|
||||||
|
WithIOSPcapBundleID = gidevice.WithPcapBundleID
|
||||||
|
)
|
||||||
|
|
||||||
type IOSDeviceOption func(*IOSDevice)
|
type IOSDeviceOption func(*IOSDevice)
|
||||||
|
|
||||||
func WithUDID(udid string) IOSDeviceOption {
|
func WithUDID(udid string) IOSDeviceOption {
|
||||||
@@ -131,9 +140,12 @@ func WithIOSPerfOptions(options ...gidevice.PerfOption) IOSDeviceOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithIOSPcapOn(pcapOn bool) IOSDeviceOption {
|
func WithIOSPcapOptions(options ...gidevice.PcapOption) IOSDeviceOption {
|
||||||
return func(device *IOSDevice) {
|
return func(device *IOSDevice) {
|
||||||
device.PcapOn = pcapOn
|
device.PcapOptions = &gidevice.PcapOptions{}
|
||||||
|
for _, option := range options {
|
||||||
|
option(device.PcapOptions)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,8 +195,8 @@ func GetIOSDeviceOptions(dev *IOSDevice) (deviceOptions []IOSDeviceOption) {
|
|||||||
if dev.PerfOptions != nil {
|
if dev.PerfOptions != nil {
|
||||||
deviceOptions = append(deviceOptions, WithIOSPerfOptions(dev.perfOpitons()...))
|
deviceOptions = append(deviceOptions, WithIOSPerfOptions(dev.perfOpitons()...))
|
||||||
}
|
}
|
||||||
if dev.PcapOn {
|
if dev.PcapOptions != nil {
|
||||||
deviceOptions = append(deviceOptions, WithIOSPcapOn(true))
|
deviceOptions = append(deviceOptions, WithIOSPcapOptions(dev.pcapOpitons()...))
|
||||||
}
|
}
|
||||||
if dev.XCTestBundleID != "" {
|
if dev.XCTestBundleID != "" {
|
||||||
deviceOptions = append(deviceOptions, WithXCTest(dev.XCTestBundleID))
|
deviceOptions = append(deviceOptions, WithXCTest(dev.XCTestBundleID))
|
||||||
@@ -249,11 +261,11 @@ func NewIOSDevice(options ...IOSDeviceOption) (device *IOSDevice, err error) {
|
|||||||
type IOSDevice struct {
|
type IOSDevice struct {
|
||||||
d gidevice.Device
|
d gidevice.Device
|
||||||
PerfOptions *gidevice.PerfOptions `json:"perf_options,omitempty" yaml:"perf_options,omitempty"`
|
PerfOptions *gidevice.PerfOptions `json:"perf_options,omitempty" yaml:"perf_options,omitempty"`
|
||||||
|
PcapOptions *gidevice.PcapOptions `json:"pcap_options,omitempty" yaml:"pcap_options,omitempty"`
|
||||||
UDID string `json:"udid,omitempty" yaml:"udid,omitempty"`
|
UDID string `json:"udid,omitempty" yaml:"udid,omitempty"`
|
||||||
Port int `json:"port,omitempty" yaml:"port,omitempty"` // WDA remote port
|
Port int `json:"port,omitempty" yaml:"port,omitempty"` // WDA remote port
|
||||||
MjpegPort int `json:"mjpeg_port,omitempty" yaml:"mjpeg_port,omitempty"` // WDA remote MJPEG port
|
MjpegPort int `json:"mjpeg_port,omitempty" yaml:"mjpeg_port,omitempty"` // WDA remote MJPEG port
|
||||||
LogOn bool `json:"log_on,omitempty" yaml:"log_on,omitempty"`
|
LogOn bool `json:"log_on,omitempty" yaml:"log_on,omitempty"`
|
||||||
PcapOn bool `json:"pcap_on,omitempty" yaml:"pcap_on,omitempty"`
|
|
||||||
XCTestBundleID string `json:"xctest_bundle_id,omitempty" yaml:"xctest_bundle_id,omitempty"`
|
XCTestBundleID string `json:"xctest_bundle_id,omitempty" yaml:"xctest_bundle_id,omitempty"`
|
||||||
|
|
||||||
// switch to iOS springboard before init WDA session
|
// switch to iOS springboard before init WDA session
|
||||||
@@ -334,7 +346,7 @@ func (dev *IOSDevice) NewDriver(capabilities Capabilities) (driverExt *DriverExt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if dev.PcapOn {
|
if dev.PcapOptions != nil {
|
||||||
if err := dev.StartPcap(); err != nil {
|
if err := dev.StartPcap(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -390,7 +402,7 @@ func (dev *IOSDevice) StopPerf() string {
|
|||||||
|
|
||||||
func (dev *IOSDevice) StartPcap() error {
|
func (dev *IOSDevice) StartPcap() error {
|
||||||
log.Info().Msg("start packet capture")
|
log.Info().Msg("start packet capture")
|
||||||
packets, err := dev.d.PcapStart()
|
packets, err := dev.d.PcapStart(dev.pcapOpitons()...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -536,6 +548,27 @@ func (dev *IOSDevice) perfOpitons() (perfOptions []gidevice.PerfOption) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dev *IOSDevice) pcapOpitons() (pcapOptions []gidevice.PcapOption) {
|
||||||
|
if dev.PcapOptions == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if dev.PcapOptions.All {
|
||||||
|
pcapOptions = append(pcapOptions, gidevice.WithPcapAll(true))
|
||||||
|
}
|
||||||
|
if dev.PcapOptions.Pid > 0 {
|
||||||
|
pcapOptions = append(pcapOptions, gidevice.WithPcapPID(dev.PcapOptions.Pid))
|
||||||
|
}
|
||||||
|
if dev.PcapOptions.ProcName != "" {
|
||||||
|
pcapOptions = append(pcapOptions, gidevice.WithPcapProcName(dev.PcapOptions.ProcName))
|
||||||
|
}
|
||||||
|
if dev.PcapOptions.BundleID != "" {
|
||||||
|
pcapOptions = append(pcapOptions, gidevice.WithPcapBundleID(dev.PcapOptions.BundleID))
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// NewHTTPDriver creates new remote HTTP client, this will also start a new session.
|
// NewHTTPDriver creates new remote HTTP client, this will also start a new session.
|
||||||
func (dev *IOSDevice) NewHTTPDriver(capabilities Capabilities) (driver WebDriver, err error) {
|
func (dev *IOSDevice) NewHTTPDriver(capabilities Capabilities) (driver WebDriver, err error) {
|
||||||
var localPort int
|
var localPort int
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ func (dExt *DriverExt) SwipeUntil(direction interface{}, findCondition Action, f
|
|||||||
time.Sleep(time.Duration(1000*interval) * time.Millisecond)
|
time.Sleep(time.Duration(1000*interval) * time.Millisecond)
|
||||||
}
|
}
|
||||||
return errors.Wrap(code.OCRTextNotFoundError,
|
return errors.Wrap(code.OCRTextNotFoundError,
|
||||||
fmt.Sprintf("swipe %s %d times, match condition failed", direction, maxRetryTimes))
|
fmt.Sprintf("swipe %v %d times, match condition failed", direction, maxRetryTimes))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dExt *DriverExt) LoopUntil(findAction, findCondition, foundAction Action, options ...DataOption) error {
|
func (dExt *DriverExt) LoopUntil(findAction, findCondition, foundAction Action, options ...DataOption) error {
|
||||||
|
|||||||
Reference in New Issue
Block a user