mirror of
https://github.com/httprunner/httprunner.git
synced 2026-07-12 16:01:27 +08:00
feat: 新增监听安装
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
package builtin
|
package builtin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
@@ -583,7 +585,69 @@ func RunCommand(cmdName string, args ...string) error {
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
stderrStr := stderr.String()
|
||||||
|
log.Error().Msg("failed to exec command. msg: " + stderrStr)
|
||||||
log.Info().Msg("exec command output: " + stdout.String())
|
log.Info().Msg("exec command output: " + stdout.String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LineCallback func(line string) bool
|
||||||
|
|
||||||
|
// RunCommandWithCallback 运行命令并根据回调判断是否成功
|
||||||
|
func RunCommandWithCallback(cmdName string, args []string, callback LineCallback) error {
|
||||||
|
cmd := exec.Command(cmdName, args...)
|
||||||
|
log.Info().Str("command", cmd.String()).Msg("exec command")
|
||||||
|
|
||||||
|
// 使用管道获取标准输出
|
||||||
|
stdoutPipe, err := cmd.StdoutPipe()
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("failed to get stdout pipe")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var stderr bytes.Buffer
|
||||||
|
cmd.Stderr = &stderr
|
||||||
|
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
log.Error().Err(err).Msg("failed to start command")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建一个用于标识成功的通道
|
||||||
|
done := make(chan struct{})
|
||||||
|
defer close(done)
|
||||||
|
|
||||||
|
// 逐行读取 stdout
|
||||||
|
go func() {
|
||||||
|
stdoutScanner := bufio.NewScanner(stdoutPipe)
|
||||||
|
for stdoutScanner.Scan() {
|
||||||
|
line := stdoutScanner.Text()
|
||||||
|
log.Info().Msg("stdout: " + line)
|
||||||
|
if callback(line) {
|
||||||
|
done <- struct{}{}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 等待命令执行完成
|
||||||
|
err = cmd.Wait()
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Msg("failed to exec command. msg: " + stderr.String())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置一个1秒的超时上下文
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
return nil
|
||||||
|
case <-ctx.Done():
|
||||||
|
// 超时,判断失败
|
||||||
|
log.Error().Msg("failed to exec command. msg: " + stderr.String())
|
||||||
|
err = errors.New("command execution failed: callback failed while exec command")
|
||||||
|
log.Error().Err(err).Msg("failed to find keyword in time")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@@ -474,7 +475,15 @@ func (dev *IOSDevice) StopPcap() string {
|
|||||||
|
|
||||||
func (dev *IOSDevice) Install(appPath string, opts *InstallOptions) (err error) {
|
func (dev *IOSDevice) Install(appPath string, opts *InstallOptions) (err error) {
|
||||||
for i := 0; i <= opts.RetryTime; i++ {
|
for i := 0; i <= opts.RetryTime; i++ {
|
||||||
err = builtin.RunCommand("ideviceinstaller", "-u", dev.UDID, "-i", appPath)
|
err = builtin.RunCommandWithCallback("ideviceinstaller", []string{"-u", dev.UDID, "-i", appPath}, func(line string) bool {
|
||||||
|
if strings.Contains(line, "Complete") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if strings.Contains(line, "90%") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -483,7 +492,15 @@ func (dev *IOSDevice) Install(appPath string, opts *InstallOptions) (err error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (dev *IOSDevice) Uninstall(bundleId string) error {
|
func (dev *IOSDevice) Uninstall(bundleId string) error {
|
||||||
return builtin.RunCommand("ideviceinstaller", "-u", dev.UDID, "-U", bundleId)
|
return builtin.RunCommandWithCallback("ideviceinstaller", []string{"-u", dev.UDID, "-U", bundleId}, func(line string) bool {
|
||||||
|
if strings.Contains(line, "Complete") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if strings.Contains(line, "90%") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dev *IOSDevice) forward(localPort, remotePort int) error {
|
func (dev *IOSDevice) forward(localPort, remotePort int) error {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -39,7 +41,8 @@ func TestViaUSB(t *testing.T) {
|
|||||||
|
|
||||||
func TestInstall(t *testing.T) {
|
func TestInstall(t *testing.T) {
|
||||||
setup(t)
|
setup(t)
|
||||||
err := iOSDriverExt.Install("/Users/bytedance/workcode/httprunner/hrp/pkg/uixt/1722942152176906000", NewInstallOptions(WithRetryTime(5)))
|
err := iOSDriverExt.Install("/Users/bytedance/Downloads/com.yueyou.cyreader_1387717110_7.54.20.ipa", NewInstallOptions(WithRetryTime(5)))
|
||||||
|
log.Error().Err(err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user