Skip to content

Instantly share code, notes, and snippets.

@cyantarek
Created February 11, 2019 07:32
Show Gist options
  • Save cyantarek/d6c9085ac0afc859cebd89b666498078 to your computer and use it in GitHub Desktop.
Save cyantarek/d6c9085ac0afc859cebd89b666498078 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"github.com/gorilla/websocket"
"gopkg.in/yaml.v2"
"io/ioutil"
"log"
"net/http"
"os"
"time"
)
type TestDef struct {
Iterations int `yaml:"iterations"`
Users int `yaml:"users"`
RampUp int `yaml:"rampup"`
Actions []map[string]interface{} `yaml:"actions"`
}
type StatFrame struct {
Time int64 `json:"time"`
Latency int64 `json:"reqs"`
}
type HttpReqResult struct {
Latency int64
Size int
Status int
}
type HttpReqAction struct {
Method string `yaml:"method"`
URL string `yaml:"url"`
Accept string `yaml:"accept"`
}
func acceptResults(resChan chan HttpReqResult) {
for {
select {
case msg := <-resChan:
fmt.Println("received msg:", msg)
statFrame := StatFrame{
time.Since(SimStart).Nanoseconds(),
msg.Latency,
}
fmt.Println(statFrame)
default:
time.Sleep(100 * time.Millisecond)
//fmt.Println("no message received")
}
}
}
func runActions(t TestDef, resChan chan HttpReqResult) {
for i := 0; i < t.Iterations; i++ {
for _, e := range t.Actions {
for k, v := range e {
switch k {
case "sleep":
a := v.(map[interface{}]interface{})
duration := a["duration"].(int)
time.Sleep(time.Duration(duration) * time.Second)
break
case "type":
switch v {
case "http":
httpReq := HttpReqAction{e["method"].(string), e["url"].(string), e["accept"].(string)}
go doHttpRequest(httpReq, resChan, )
break
}
}
}
}
}
}
func doHttpRequest(httpAction HttpReqAction, resChan chan HttpReqResult) {
fmt.Println(httpAction)
req, err := http.NewRequest(httpAction.Method, httpAction.URL, nil)
if err != nil {
log.Fatal(err)
}
req.Header.Add("Accept", httpAction.Accept)
client := &http.Client{}
start := time.Now()
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
elapsed := time.Since(start)
respBody, err := ioutil.ReadAll(resp.Body)
contentLen := len(respBody)
status := resp.StatusCode
resp.Body.Close()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Status: %d Content-Lenghth: %d Latency %dms %s\n", status, contentLen, elapsed/1000000, httpAction.URL)
httpReqResult := HttpReqResult{
elapsed.Nanoseconds(),
contentLen,
status,
}
resChan <- httpReqResult
}
var SimStart time.Time
var wsChannels []*websocket.Conn
var upgrader = websocket.Upgrader{}
func startDataSimulation(ws *websocket.Conn) {
}
func broadcastStatFrame(statFrame StatFrame) {
}
func echo(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/start" {
http.Error(w, "not found", 404)
return
}
if r.Method != "GET" {
http.Error(w, "method not allowed", 405)
return
}
c, _ := upgrader.Upgrade(w, r, nil)
defer c.Close()
for {
mt, msg, _ := c.ReadMessage()
log.Printf("recv:%s", msg)
err := c.WriteMessage(mt, msg)
if err != nil {
log.Printf("write:%s", err)
break
}
}
}
func StartWsServer() {
http.HandleFunc("/start", echo)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "static/" + r.URL.Path[1:])
})
err := http.ListenAndServe(":8089", nil)
if err != nil {
panic("ListenAndServe: " + err.Error())
}
fmt.Println("Started WebSocket server")
}
func main() {
SimStart = time.Now()
currentDir, err := os.Getwd()
if err != nil {
log.Println(err)
}
data, err := ioutil.ReadFile(currentDir + "/test01.yml")
if err != nil {
log.Println(err)
}
var testData TestDef
err = yaml.Unmarshal(data, &testData)
if err != nil {
log.Println(err)
}
fmt.Println(testData)
resultChan := make(chan HttpReqResult, 1000)
go acceptResults(resultChan)
for i := 0; i < testData.Users; i++ {
go runActions(testData, resultChan)
}
StartWsServer()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment