Skip to content

Commit

Permalink
simplify api using post and delete
Browse files Browse the repository at this point in the history
  • Loading branch information
aluedeke committed Oct 10, 2024
1 parent ed7ff7a commit 6f087dc
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 25 deletions.
4 changes: 3 additions & 1 deletion restapi/api/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ func simpleDeviceRoutes(device *gin.RouterGroup) {
device.PUT("/setlocation", SetLocation)
device.GET("/syslog", streamingMiddleWare, Syslog)

device.POST("/wda", RunWda)
device.POST("/wda", CreateWdaSession)
device.GET("/wda/:sessionId", ReadWdaSession)
device.DELETE("/wda/:sessionId", DeleteWdaSession)
}

func appRoutes(group *gin.RouterGroup) {
Expand Down
140 changes: 119 additions & 21 deletions restapi/api/wda.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package api

import (
"io"
"context"
"net/http"
"os"
"sync"

"github.com/danielpaulus/go-ios/ios"
"github.com/danielpaulus/go-ios/ios/testmanagerd"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
log "github.com/sirupsen/logrus"
)

Expand All @@ -19,42 +21,138 @@ type WdaConfig struct {
Env map[string]interface{} `json:"env"`
}

type ChannelWriter struct {
Channel chan []byte
type WdaSessionKey struct {
udid string
sessionID string
}

func (w *ChannelWriter) Write(p []byte) (n int, err error) {
log.Debugf("writing %s", string(p))
w.Channel <- p
type WdaSession struct {
Config WdaConfig `json:"config" binding:"required"`
SessionId string `json:"sessionId" binding:"required"`
Udid string `json:"udid" binding:"required"`
stopWda context.CancelFunc
}

func (session *WdaSession) Write(p []byte) (n int, err error) {
log.
WithField("udid", session.Udid).
WithField("sessionId", session.SessionId).
Debugf("WDA_LOG %s", p)

return len(p), nil
}

func RunWda(c *gin.Context) {
var globalSessions = sync.Map{}

func CreateWdaSession(c *gin.Context) {
device := c.MustGet(IOS_KEY).(ios.DeviceEntry)
log.WithField("udid", device.Properties.SerialNumber).Printf("Running WDA on device %t", device.UserspaceTUN)
log.
WithField("udid", device.Properties.SerialNumber).
Debugf("Creating WDA session")

var config WdaConfig
if err := c.ShouldBindJSON(&config); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

logStream := make(chan []byte, 10)
w := ChannelWriter{Channel: logStream}
sessionKey := WdaSessionKey{
udid: device.Properties.SerialNumber,
sessionID: uuid.New().String(),
}

wdaCtx, stopWda := context.WithCancel(context.Background())

session := WdaSession{
Udid: sessionKey.udid,
SessionId: sessionKey.sessionID,
Config: config,
stopWda: stopWda,
}

go func() {
defer close(logStream)
_, err := testmanagerd.RunXCUIWithBundleIdsCtx(c, config.BundleID, config.TestbundleID, config.XCTestConfig, device, config.Args, config.Env, nil, nil, testmanagerd.NewTestListener(&w, &w, os.TempDir()), false)
_, err := testmanagerd.RunXCUIWithBundleIdsCtx(wdaCtx, config.BundleID, config.TestbundleID, config.XCTestConfig, device, config.Args, config.Env, nil, nil, testmanagerd.NewTestListener(&session, &session, os.TempDir()), false)
if err != nil {
log.WithError(err).Error("Failed running WDA")
// return true
log.
WithField("udid", sessionKey.udid).
WithField("sessionId", sessionKey.sessionID).
WithError(err).
Error("Failed running WDA")
}

stopWda()
globalSessions.Delete(sessionKey)

log.
WithField("udid", sessionKey.udid).
WithField("sessionId", sessionKey.sessionID).
Debug("Deleted WDA session")
}()

c.Stream(func(w io.Writer) bool {
if msg, ok := <-logStream; ok {
c.SSEvent("log", msg)
return true
}
return false
})
globalSessions.Store(sessionKey, session)

log.
WithField("udid", sessionKey.udid).
WithField("sessionId", sessionKey.sessionID).
Debugf("Requested to start WDA session")

c.JSON(http.StatusOK, session)
}

func ReadWdaSession(c *gin.Context) {
device := c.MustGet(IOS_KEY).(ios.DeviceEntry)

sessionID := c.Param("sessionId")
if sessionID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "sessionId is required"})
return
}

sessionKey := WdaSessionKey{
udid: device.Properties.SerialNumber,
sessionID: sessionID,
}

session, loaded := globalSessions.Load(sessionKey)
if !loaded {
c.JSON(http.StatusNotFound, gin.H{"error": "session not found"})
return
}

c.JSON(http.StatusOK, session)
}

func DeleteWdaSession(c *gin.Context) {
device := c.MustGet(IOS_KEY).(ios.DeviceEntry)

sessionID := c.Param("sessionId")
if sessionID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "sessionId is required"})
return
}

sessionKey := WdaSessionKey{
udid: device.Properties.SerialNumber,
sessionID: sessionID,
}

session, loaded := globalSessions.Load(sessionKey)
if !loaded {
c.JSON(http.StatusNotFound, gin.H{"error": "session not found"})
return
}

wdaSession, ok := session.(WdaSession)
if !ok {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to cast session"})
return
}
wdaSession.stopWda()

log.
WithField("udid", sessionKey.udid).
WithField("sessionId", sessionKey.sessionID).
Debug("Requested to stop WDA")

c.JSON(http.StatusOK, session)
}
4 changes: 1 addition & 3 deletions restapi/go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
module github.com/danielpaulus/go-ios/restapi

go 1.22.0

toolchain go1.22.5
go 1.21

require (
github.com/danielpaulus/go-ios v1.0.91
Expand Down

0 comments on commit 6f087dc

Please sign in to comment.