2022-02-20 08:15:04 +00:00
|
|
|
package databag
|
|
|
|
|
|
|
|
import (
|
|
|
|
"time"
|
|
|
|
"errors"
|
2022-02-21 23:00:26 +00:00
|
|
|
"strconv"
|
2022-02-20 08:15:04 +00:00
|
|
|
"sync"
|
|
|
|
"encoding/json"
|
2022-02-21 22:42:49 +00:00
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
2022-02-20 08:15:04 +00:00
|
|
|
"github.com/gorilla/websocket"
|
2022-02-21 22:42:49 +00:00
|
|
|
"github.com/gorilla/mux"
|
2022-02-20 08:15:04 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const TEST_TIMEOUT = 5
|
|
|
|
|
|
|
|
type TestCondition struct {
|
|
|
|
check func(*TestApp) bool
|
|
|
|
channel chan bool
|
|
|
|
}
|
|
|
|
|
|
|
|
type TestChannel struct {
|
|
|
|
channel Channel
|
|
|
|
topics map[string]Topic
|
|
|
|
}
|
|
|
|
|
|
|
|
type TestContactData struct {
|
|
|
|
card Card
|
2022-02-21 22:42:49 +00:00
|
|
|
viewRevision int64
|
|
|
|
articleRevision int64
|
|
|
|
channelRevision int64
|
2022-02-20 08:15:04 +00:00
|
|
|
articles map[string]Article
|
|
|
|
channels map[string]TestChannel
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewTestApp() *TestApp {
|
|
|
|
return &TestApp{
|
|
|
|
articles: make(map[string]Article),
|
|
|
|
channels: make(map[string]TestChannel),
|
|
|
|
contacts: make(map[string]TestContactData),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type TestApp struct {
|
|
|
|
name string
|
|
|
|
revision Revision
|
|
|
|
profile Profile
|
|
|
|
articles map[string]Article
|
|
|
|
channels map[string]TestChannel
|
|
|
|
contacts map[string]TestContactData
|
|
|
|
|
|
|
|
token string
|
|
|
|
|
|
|
|
mutex sync.Mutex
|
|
|
|
condition *TestCondition
|
|
|
|
}
|
|
|
|
|
2022-02-21 22:42:49 +00:00
|
|
|
func (a *TestApp) UpdateProfile() (err error) {
|
|
|
|
params := &TestApiParams{ query: "/profile", tokenType: APP_TOKENAPP, token: a.token }
|
|
|
|
response := &TestApiResponse{ data: &a.profile }
|
|
|
|
err = TestApiRequest(GetProfile, params, response)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *TestApp) UpdateArticle() (err error) {
|
2022-02-21 23:00:26 +00:00
|
|
|
var articles []Article
|
|
|
|
if a.revision.Article == 0 {
|
|
|
|
params := &TestApiParams{ query: "/articles", tokenType: APP_TOKENAPP, token: a.token }
|
|
|
|
response := &TestApiResponse{ data: &articles }
|
|
|
|
if err = TestApiRequest(GetArticles, params, response); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
revision := strconv.FormatInt(a.revision.Article, 10)
|
|
|
|
params := &TestApiParams{ query: "/articles?revision=" + revision, tokenType: APP_TOKENAPP, token: a.token }
|
|
|
|
response := &TestApiResponse{ data: &articles }
|
|
|
|
if err = TestApiRequest(GetArticles, params, response); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, article := range articles {
|
|
|
|
if article.Data == nil {
|
|
|
|
delete(a.articles, article.Id)
|
|
|
|
} else {
|
|
|
|
a.articles[article.Id] = article
|
|
|
|
}
|
|
|
|
}
|
2022-02-21 22:42:49 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *TestApp) UpdateGroup() (err error) {
|
|
|
|
PrintMsg("update group")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *TestApp) UpdateChannel() (err error) {
|
|
|
|
PrintMsg("update channel")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *TestApp) UpdateCard() (err error) {
|
|
|
|
PrintMsg("update card")
|
|
|
|
return
|
2022-02-20 08:15:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (a *TestApp) UpdateApp(rev *Revision) {
|
|
|
|
a.mutex.Lock()
|
|
|
|
defer a.mutex.Unlock()
|
|
|
|
|
|
|
|
if rev.Profile != a.revision.Profile {
|
|
|
|
if err := a.UpdateProfile(); err != nil {
|
|
|
|
PrintMsg(err)
|
|
|
|
} else {
|
|
|
|
a.revision.Profile = rev.Profile
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-21 22:42:49 +00:00
|
|
|
if rev.Article != a.revision.Article {
|
|
|
|
if err := a.UpdateArticle(); err != nil {
|
|
|
|
PrintMsg(err)
|
|
|
|
} else {
|
|
|
|
a.revision.Article = rev.Article
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if rev.Group != a.revision.Group {
|
|
|
|
if err := a.UpdateGroup(); err != nil {
|
|
|
|
PrintMsg(err)
|
|
|
|
} else {
|
|
|
|
a.revision.Group = rev.Group
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if rev.Channel != a.revision.Channel {
|
|
|
|
if err := a.UpdateChannel(); err != nil {
|
|
|
|
PrintMsg(err)
|
|
|
|
} else {
|
|
|
|
a.revision.Channel = rev.Channel
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if rev.Card != a.revision.Card {
|
|
|
|
if err := a.UpdateCard(); err != nil {
|
|
|
|
PrintMsg(err)
|
|
|
|
} else {
|
|
|
|
a.revision.Card = rev.Card
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-20 08:15:04 +00:00
|
|
|
if a.condition != nil {
|
|
|
|
if a.condition.check(a) {
|
|
|
|
a.condition.channel <- true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *TestApp) Connect(token string) error {
|
|
|
|
var revision Revision
|
|
|
|
var data []byte
|
|
|
|
var dataType int
|
|
|
|
|
|
|
|
a.token = token
|
|
|
|
|
|
|
|
// connect websocket
|
|
|
|
ws, err := StatusConnection(token, &revision)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
a.UpdateApp(&revision)
|
|
|
|
|
|
|
|
// reset any timeout
|
|
|
|
ws.SetReadDeadline(time.Time{})
|
|
|
|
|
|
|
|
// read revision update
|
|
|
|
for ;; {
|
|
|
|
if dataType, data, err = ws.ReadMessage(); err != nil {
|
|
|
|
return errors.New("failed to read status conenction")
|
|
|
|
}
|
|
|
|
if dataType != websocket.TextMessage {
|
|
|
|
return errors.New("invalid status data type")
|
|
|
|
}
|
|
|
|
rev := &Revision{}
|
|
|
|
if err = json.Unmarshal(data, rev); err != nil {
|
|
|
|
return errors.New("invalid status data")
|
|
|
|
}
|
|
|
|
a.UpdateApp(rev)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *TestApp) setCondition(test *TestCondition) {
|
|
|
|
a.mutex.Lock()
|
|
|
|
if test.check(a) {
|
|
|
|
test.channel <- true
|
|
|
|
} else {
|
|
|
|
a.condition = test
|
|
|
|
}
|
|
|
|
a.mutex.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *TestApp) clearCondition() {
|
|
|
|
a.mutex.Lock()
|
|
|
|
a.condition = nil
|
|
|
|
a.mutex.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *TestApp) WaitFor(check func(*TestApp) bool) error {
|
|
|
|
var done = make(chan bool, 1)
|
|
|
|
var wake = make(chan bool, 1)
|
|
|
|
a.setCondition(&TestCondition{channel: done, check: check, })
|
|
|
|
go func(){
|
|
|
|
time.Sleep(TEST_TIMEOUT * time.Second)
|
|
|
|
wake <- true
|
|
|
|
}()
|
|
|
|
select {
|
|
|
|
case <-done:
|
|
|
|
a.clearCondition()
|
|
|
|
return nil
|
|
|
|
case <-wake:
|
|
|
|
a.clearCondition()
|
|
|
|
return errors.New("timeout waiting for condition")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-21 22:42:49 +00:00
|
|
|
/*** endpoint test function ***/
|
|
|
|
|
|
|
|
type TestApiParams struct {
|
|
|
|
restType string
|
|
|
|
path map[string]string
|
|
|
|
query string
|
|
|
|
body interface{}
|
|
|
|
tokenType string
|
|
|
|
token string
|
|
|
|
}
|
|
|
|
|
|
|
|
type TestApiResponse struct {
|
|
|
|
code int
|
|
|
|
data interface{}
|
|
|
|
header map[string][]string
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestApiRequest(endpoint func(http.ResponseWriter, *http.Request), params *TestApiParams, resp *TestApiResponse) (err error) {
|
|
|
|
|
|
|
|
var r *http.Request
|
|
|
|
var w *httptest.ResponseRecorder
|
|
|
|
rest := params.restType
|
|
|
|
if rest == "" {
|
|
|
|
rest = "GET"
|
|
|
|
}
|
|
|
|
if r, w, err = NewRequest(rest, params.query, params.body); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
r = mux.SetURLVars(r, params.path)
|
|
|
|
if params.tokenType != "" {
|
|
|
|
r.Header.Add("TokenType", params.tokenType)
|
|
|
|
}
|
|
|
|
if params.token != "" {
|
|
|
|
SetBearerAuth(r, params.token)
|
|
|
|
}
|
|
|
|
endpoint(w, r)
|
|
|
|
|
|
|
|
res := w.Result()
|
|
|
|
if res.StatusCode != 200 && res.StatusCode != 410 {
|
|
|
|
err = errors.New("response failed");
|
|
|
|
return
|
|
|
|
}
|
|
|
|
resp.header = res.Header
|
|
|
|
if resp.data != nil {
|
|
|
|
dec := json.NewDecoder(res.Body)
|
|
|
|
if err = dec.Decode(resp.data); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2022-02-20 08:15:04 +00:00
|
|
|
|