package test import ( "bufio" "bytes" "context" "encoding/json" "errors" "fmt" "io" "io/ioutil" "mime/multipart" "net/http" "os" "strings" "testing" "time" "heruvym/app" "heruvym/model" "heruvym/service" "bitbucket.org/skeris/profile/jwt_adapter" "github.com/stretchr/testify/assert" "github.com/themakers/bdd" ) func TestTicket(t *testing.T) { fmt.Println("start test") ctx, cancel := context.WithCancel(context.Background()) defer cancel() bdd.Scenario(t, "SupportChat", func(t *testing.T, runID string) { go func() { time.Sleep(3 * time.Second) fmt.Println("start service") _, err := app.New(ctx, app.Options{ MongoURI: "mongodb://mongo:27017", NumberPortLocal: "1488", LoggerDevMode: false, MinioEndpoint: "minio:9000", MinioAccessKey: "minioadmin", MinioSecretKey: "minioadmin", MongoDbTable: "profile", MongoCollections: "profile,role", }) if err != nil { panic(err) } }() time.Sleep(time.Second * 5) bdd.Act(t, "client", func() { fmt.Println("client") var ( token string ticket service.CreateTicketResp msgs = make(chan []byte) ) bdd.Test(t, "CreateTicket", func() { buf, err := json.Marshal(service.CreateTicketReq{ Title: "TestTitle", Message: "test", }) if err != nil { panic(err) } req, err := http.NewRequestWithContext( ctx, "POST", "http://localhost:1488/support/create", bytes.NewBuffer(buf)) if err != nil { panic(err) } req.Header.Add(jwt_adapter.DefaultHeaderKey, "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJRCI6ImMxcDM0YjhqZHBmOG04Zm43cnIwIiwiU2Vzc2lvbiI6ImMxcDM0YjhqZHBmOG04Zm43cnJnIiwiVXNlciI6IiIsIlRhcmlmZiI6MCwiQ3JlYXRlZCI6MTYxODA5NjY4NTc4MCwiTGFzdFNlZW4iOjE2MTgwOTY2ODU3ODF9.ciJoJiOxzIPv0LY4h3rG8Tf3AsSBXXLcYEpyN9mIki0") resp, err := http.DefaultClient.Do(req) if err != nil { assert.NoError(t, err) } if resp.StatusCode != http.StatusOK { panic("NotAccepted") } token = resp.Header.Get(jwt_adapter.DefaultHeaderKey) assert.NoError(t, json.NewDecoder(resp.Body).Decode(&ticket)) }) bdd.Test(t, "subscribe for tiket", func() { client := &http.Client{} r, err := http.NewRequest("GET", "http://localhost:1488/support/ticket?Authorization="+token+"&ticket="+ticket.Ticket, nil) assert.NoError(t, err) r.Header.Set("Accept", "text/event-stream") r.Header.Set("Cache-Control", "no-cache") r.Header.Set("Connection", "keep-alive") resp, err := client.Do(r) assert.NoError(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode) sc := bufio.NewScanner(resp.Body) split := func(data []byte, atEOF bool) (int, []byte, error) { if atEOF && len(data) == 0 { return 0, nil, nil } if strings.Contains(string(data), ":ping") { return 0, nil, nil } if len(data) <= 6 { return 0, nil, errors.New(fmt.Sprintf("got bad body: %v", string(data))) } // Мы получили данные для обработки // Начинаем с 6 байта, чтобы убрать "data: " if i, nlen := containsDoubleNewline(data); i >= 0 { return i + nlen, data[6:i], nil } // Если получен EOF, то мы получили все что необходимо if atEOF { return len(data), data, nil } return 0, nil, nil } sc.Split(split) go func() { for sc.Scan() { body := sc.Bytes() msgs <- body fmt.Println("data from", string(body)) } if err = sc.Err(); err != nil { fmt.Println("scanner.Err()", err) if err != bufio.ErrTooLong { fmt.Println("toolong") } } }() }) bdd.Test(t, "send message", func() { buf, err := json.Marshal(service.ReqPutMessage{ Message: "test", TicketID: ticket.Ticket, Lang: "ru", }) if err != nil { panic(err) } req, err := http.NewRequestWithContext(ctx, http.MethodPost, "http://localhost:1488/support/send", bytes.NewBuffer(buf)) assert.NoError(t, err) req.Header.Add(jwt_adapter.DefaultHeaderKey, token) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode) var msg, channed model.Message assert.NoError(t, json.NewDecoder(resp.Body).Decode(&msg)) err = json.Unmarshal(<-msgs, &channed) assert.NoError(t, err) assert.Equal(t, "test", channed.Message) }) bdd.Test(t, "send file", func() { body := &bytes.Buffer{} writer := multipart.NewWriter(body) partf, _ := writer.CreateFormFile("f.go", "f.go") f, err := os.OpenFile("./main_test.go", os.O_RDWR, 0644) assert.NoError(t, err) io.Copy(partf, f) assert.NoError(t, writer.WriteField("ticket", ticket.Ticket)) writer.Close() req, err := http.NewRequestWithContext(ctx, http.MethodPost, "http://localhost:1488/support/sendFiles", body) req.Header.Set("Content-Type", "multipart/form-data; boundary="+writer.Boundary()) req.Header.Add(jwt_adapter.DefaultHeaderKey, token) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode) str, err := ioutil.ReadAll(resp.Body) fmt.Println("resp files", err, string(str)) }) }) }) } func containsDoubleNewline(data []byte) (int, int) { // Ищем все возможные переносы строки crcr := bytes.Index(data, []byte("\r\r")) lflf := bytes.Index(data, []byte("\n\n")) crlflf := bytes.Index(data, []byte("\r\n\n")) lfcrlf := bytes.Index(data, []byte("\n\r\n")) crlfcrlf := bytes.Index(data, []byte("\r\n\r\n")) // Находим первый двойной перенос строки minPos := minPosInt(crcr, minPosInt(lflf, minPosInt(crlflf, minPosInt(lfcrlf, crlfcrlf)))) // Определяем длину nlen := 2 if minPos == crlfcrlf { nlen = 4 } else if minPos == crlflf || minPos == lfcrlf { nlen = 3 } return minPos, nlen } func minPosInt(a, b int) int { if a < 0 { return b } if b < 0 { return a } if a > b { return b } return a }