Skip to content

Commit 6c71b33

Browse files
committed
Basic debug support for Gauge API via web server
0 parents  commit 6c71b33

File tree

17 files changed

+3544
-0
lines changed

17 files changed

+3544
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.idea/
2+
bin
3+
.DS_Store

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "gauge-proto"]
2+
path = gauge-proto
3+
url = https://github.com/getgauge/gauge-proto

LICENSE.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2017 Kashish Munjal
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
Spider [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
2+
======
3+
4+
Debugger for [Gauge](http://getgauge.io) API started by IDE's.
5+
6+
Installation
7+
------------
8+
9+
Download the zip file from the [releases](https://github.com/kashishm/spider/releases) and extract it.
10+
11+
Usage
12+
-----
13+
Run the binary extracted from the downloaded zip.
14+
15+
Build from Source
16+
-----------------
17+
18+
### Requirements
19+
* [Golang](http://golang.org/)
20+
21+
```
22+
go get github.com/kashishm/spider
23+
```
24+
25+
### Compiling
26+
27+
```
28+
go run spider.go
29+
```
30+
31+
### For cross-platform compilation and Creating distributable
32+
33+
```
34+
go run build/make.go
35+
```
36+
37+
License
38+
-------
39+
40+
Spider is an open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT).

build/make.go

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
"os/exec"
8+
"path/filepath"
9+
"runtime"
10+
"strings"
11+
12+
"github.com/getgauge/spider/version"
13+
)
14+
15+
const (
16+
CGO_ENABLED = "CGO_ENABLED"
17+
)
18+
19+
const (
20+
distros = "distros"
21+
GOARCH = "GOARCH"
22+
GOOS = "GOOS"
23+
X86 = "386"
24+
X86_64 = "amd64"
25+
DARWIN = "darwin"
26+
LINUX = "linux"
27+
WINDOWS = "windows"
28+
bin = "bin"
29+
spider = "spider"
30+
)
31+
32+
func main() {
33+
compileAcrossPlatforms()
34+
createPluginDistro()
35+
}
36+
37+
func createPluginDistro() {
38+
for _, platformEnv := range platformEnvs {
39+
setEnv(platformEnv)
40+
fmt.Printf("Creating distro for platform => OS:%s ARCH:%s \n", platformEnv[GOOS], platformEnv[GOARCH])
41+
createDistro()
42+
}
43+
log.Printf("Distributables created in directory => %s \n", filepath.Join(bin, distros))
44+
}
45+
46+
func createDistro() {
47+
packageName := fmt.Sprintf("%s-%s-%s.%s", spider, getPluginVersion(), getGOOS(), getArch())
48+
os.Mkdir(filepath.Join(bin, distros), 0755)
49+
createZipFromUtil(getBinDir(), packageName)
50+
}
51+
52+
func createZipFromUtil(dir, name string) {
53+
wd, err := os.Getwd()
54+
if err != nil {
55+
panic(err)
56+
}
57+
os.Chdir(dir)
58+
output, err := executeCommand("zip", "-r", filepath.Join("..", distros, name+".zip"), ".")
59+
fmt.Println(output)
60+
if err != nil {
61+
panic(fmt.Sprintf("Failed to zip: %s", err))
62+
}
63+
os.Chdir(wd)
64+
}
65+
66+
func runProcess(command string, arg ...string) {
67+
cmd := exec.Command(command, arg...)
68+
cmd.Stdout = os.Stdout
69+
cmd.Stderr = os.Stderr
70+
log.Printf("Execute %v\n", cmd.Args)
71+
err := cmd.Run()
72+
if err != nil {
73+
panic(err)
74+
}
75+
}
76+
77+
func executeCommand(command string, arg ...string) (string, error) {
78+
cmd := exec.Command(command, arg...)
79+
bytes, err := cmd.Output()
80+
return strings.TrimSpace(fmt.Sprintf("%s", bytes)), err
81+
}
82+
83+
func compileGoPackage() {
84+
runProcess("go", "get", "-d", "./...")
85+
runProcess("go", "build", "-o", getGaugeExecutablePath(spider))
86+
}
87+
88+
func getGaugeExecutablePath(file string) string {
89+
return filepath.Join(getBinDir(), getExecutableName(file))
90+
}
91+
92+
func getExecutableName(file string) string {
93+
if getGOOS() == "windows" {
94+
return file + ".exe"
95+
}
96+
return file
97+
}
98+
99+
func getBinDir() string {
100+
return filepath.Join(bin, fmt.Sprintf("%s_%s", getGOOS(), getGOARCH()))
101+
}
102+
103+
func getPluginVersion() string {
104+
return version.Version
105+
}
106+
107+
func setEnv(envVariables map[string]string) {
108+
for k, v := range envVariables {
109+
os.Setenv(k, v)
110+
}
111+
}
112+
113+
var (
114+
platformEnvs = []map[string]string{
115+
map[string]string{GOARCH: X86, GOOS: DARWIN, CGO_ENABLED: "0"},
116+
map[string]string{GOARCH: X86_64, GOOS: DARWIN, CGO_ENABLED: "0"},
117+
map[string]string{GOARCH: X86, GOOS: LINUX, CGO_ENABLED: "0"},
118+
map[string]string{GOARCH: X86_64, GOOS: LINUX, CGO_ENABLED: "0"},
119+
map[string]string{GOARCH: X86, GOOS: WINDOWS, CGO_ENABLED: "0"},
120+
map[string]string{GOARCH: X86_64, GOOS: WINDOWS, CGO_ENABLED: "0"},
121+
}
122+
)
123+
124+
func compileAcrossPlatforms() {
125+
for _, platformEnv := range platformEnvs {
126+
setEnv(platformEnv)
127+
fmt.Printf("Compiling for platform => OS:%s ARCH:%s \n", platformEnv[GOOS], platformEnv[GOARCH])
128+
compileGoPackage()
129+
}
130+
}
131+
132+
func getArch() string {
133+
if getGOARCH() == X86 {
134+
return "x86"
135+
}
136+
return "x86_64"
137+
}
138+
139+
func getGOARCH() string {
140+
goArch := os.Getenv(GOARCH)
141+
if goArch == "" {
142+
return runtime.GOARCH
143+
}
144+
return goArch
145+
}
146+
147+
func getGOOS() string {
148+
goOS := os.Getenv(GOOS)
149+
if goOS == "" {
150+
return runtime.GOOS
151+
}
152+
return goOS
153+
}

debug/api.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package debug
2+
3+
import (
4+
"fmt"
5+
"net"
6+
7+
"bytes"
8+
"time"
9+
10+
m "github.com/getgauge/spider/gauge_messages"
11+
"github.com/golang/protobuf/proto"
12+
)
13+
14+
type api struct {
15+
connection net.Conn
16+
}
17+
18+
func newAPI(host string, port string) (*api, error) {
19+
c, err := net.Dial("tcp", fmt.Sprintf("%s:%s", host, port))
20+
return &api{connection: c}, err
21+
}
22+
23+
func (a *api) getResponse(message *m.APIMessage) (*m.APIMessage, error) {
24+
messageId := time.Now().UnixNano()
25+
message.MessageId = messageId
26+
27+
data, err := proto.Marshal(message)
28+
if err != nil {
29+
return nil, err
30+
}
31+
responseBytes, err := a.writeDataAndGetResponse(data)
32+
if err != nil {
33+
return nil, err
34+
}
35+
responseMessage := &m.APIMessage{}
36+
if err := proto.Unmarshal(responseBytes, responseMessage); err != nil {
37+
return nil, err
38+
}
39+
return responseMessage, err
40+
}
41+
42+
func (a *api) writeDataAndGetResponse(messageBytes []byte) ([]byte, error) {
43+
if err := a.write(messageBytes); err != nil {
44+
return nil, err
45+
}
46+
47+
return a.readResponse()
48+
}
49+
50+
func (a *api) readResponse() ([]byte, error) {
51+
buffer := new(bytes.Buffer)
52+
data := make([]byte, 8192)
53+
for {
54+
n, err := a.connection.Read(data)
55+
if err != nil {
56+
a.connection.Close()
57+
return nil, fmt.Errorf("Connection closed [%s] cause: %s", a.connection.RemoteAddr(), err.Error())
58+
}
59+
60+
buffer.Write(data[0:n])
61+
62+
messageLength, bytesRead := proto.DecodeVarint(buffer.Bytes())
63+
if messageLength > 0 && messageLength < uint64(buffer.Len()) {
64+
return buffer.Bytes()[bytesRead : messageLength+uint64(bytesRead)], nil
65+
}
66+
}
67+
}
68+
69+
func (a *api) write(messageBytes []byte) error {
70+
messageLen := proto.EncodeVarint(uint64(len(messageBytes)))
71+
data := append(messageLen, messageBytes...)
72+
_, err := a.connection.Write(data)
73+
return err
74+
}
75+
76+
func (a *api) close() {
77+
a.connection.Close()
78+
}

0 commit comments

Comments
 (0)