databag/net/server/internal/testApp.go

908 lines
29 KiB
Go
Raw Normal View History

2022-02-20 08:15:04 +00:00
package databag
import (
"time"
"errors"
2022-03-20 06:01:18 +00:00
"strings"
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
}
2022-03-04 21:44:11 +00:00
type TestTopic struct {
topic Topic
tags map[string]*Tag
}
2022-02-20 08:15:04 +00:00
type TestChannel struct {
channel Channel
2022-03-04 21:44:11 +00:00
topics map[string]*TestTopic
2022-02-20 08:15:04 +00:00
}
type TestContactData struct {
2022-02-23 23:00:11 +00:00
token string
2022-02-20 08:15:04 +00:00
card Card
2022-02-23 23:00:11 +00:00
profileRevision int64
2022-02-21 22:42:49 +00:00
viewRevision int64
articleRevision int64
channelRevision int64
2022-02-23 23:00:11 +00:00
cardDetailRevision int64
cardProfileRevision int64
2022-03-03 19:34:07 +00:00
articles map[string]*Article
channels map[string]*TestChannel
2022-02-22 23:02:31 +00:00
offsync bool
}
func (c *TestContactData) UpdateContact() (err error) {
2022-02-23 23:00:11 +00:00
if c.cardDetailRevision != c.card.Data.DetailRevision {
2022-02-23 06:11:56 +00:00
if err = c.UpdateContactCardDetail(); err != nil {
2022-02-22 23:02:31 +00:00
return
} else {
2022-02-23 23:00:11 +00:00
c.cardDetailRevision = c.card.Data.DetailRevision
2022-02-22 23:02:31 +00:00
}
}
2022-02-23 23:00:11 +00:00
if c.cardProfileRevision != c.card.Data.ProfileRevision {
2022-02-23 06:11:56 +00:00
if err = c.UpdateContactCardProfile(); err != nil {
return
} else {
2022-02-23 23:00:11 +00:00
c.cardProfileRevision = c.card.Data.ProfileRevision
2022-02-23 06:11:56 +00:00
}
}
2022-02-22 23:02:31 +00:00
// sync rest only if connected
if c.card.Data.CardDetail.Status != APP_CARDCONNECTED {
return
}
if c.profileRevision != c.card.Data.NotifiedProfile {
if err = c.UpdateContactProfile(); err != nil {
return
} else {
c.profileRevision = c.card.Data.NotifiedProfile
}
}
if c.viewRevision != c.card.Data.NotifiedView {
if err = c.UpdateContactArticle(); err != nil {
return
2022-03-04 19:44:55 +00:00
} else if err = c.UpdateContactChannels(); err != nil {
2022-02-22 23:02:31 +00:00
return
} else {
c.articleRevision = c.card.Data.NotifiedArticle
c.channelRevision = c.card.Data.NotifiedChannel
c.viewRevision = c.card.Data.NotifiedView
}
}
if c.articleRevision != c.card.Data.NotifiedArticle {
if err = c.UpdateContactArticle(); err != nil {
return
} else {
c.articleRevision = c.card.Data.NotifiedArticle
}
}
if c.channelRevision != c.card.Data.NotifiedChannel {
2022-03-04 19:44:55 +00:00
if err = c.UpdateContactChannels(); err != nil {
2022-02-22 23:02:31 +00:00
return
} else {
c.channelRevision = c.card.Data.NotifiedChannel
}
}
return
}
func (c *TestContactData) UpdateContactProfile() (err error) {
2022-02-23 23:00:11 +00:00
var msg DataMessage
token := c.card.Data.CardProfile.Guid + "." + c.card.Data.CardDetail.Token
params := &TestApiParams{ query: "/profile/message", tokenType: APP_TOKENCONTACT, token: token }
response := &TestApiResponse{ data: &msg }
if err = TestApiRequest(GetProfileMessage, params, response); err != nil {
return
}
params = &TestApiParams{ restType: "PUT", query: "/contact/cards/{cardId}/profile", tokenType: APP_TOKENAPP, token: c.token,
path: map[string]string{ "cardId": c.card.Id }, body: &msg }
response = &TestApiResponse{}
if err = TestApiRequest(SetCardProfile, params, response); err != nil {
return
}
return
2022-02-22 23:02:31 +00:00
}
func (c *TestContactData) UpdateContactArticle() (err error) {
var articles []Article
if c.articleRevision == 0 || c.viewRevision != c.card.Data.NotifiedView {
token := c.card.Data.CardProfile.Guid + "." + c.card.Data.CardDetail.Token
params := &TestApiParams{ query: "/articles", tokenType: APP_TOKENCONTACT, token: token }
response := &TestApiResponse{ data: &articles }
if err = TestApiRequest(GetArticles, params, response); err != nil {
return
}
2022-03-03 19:34:07 +00:00
c.articles = make(map[string]*Article)
2022-02-22 23:02:31 +00:00
} else {
token := c.card.Data.CardProfile.Guid + "." + c.card.Data.CardDetail.Token
viewRevision := strconv.FormatInt(c.viewRevision, 10)
articleRevision := strconv.FormatInt(c.articleRevision, 10)
params := &TestApiParams{ query: "/articles?articleRevision=" + articleRevision + "&viewRevision=" + viewRevision,
tokenType: APP_TOKENCONTACT, token: token }
response := &TestApiResponse{ data: &articles }
if err = TestApiRequest(GetArticles, params, response); err != nil {
return
}
}
for _, article := range articles {
if article.Data == nil {
delete(c.articles, article.Id)
} else {
2022-03-03 19:34:07 +00:00
c.articles[article.Id] = &article
2022-02-22 23:02:31 +00:00
}
}
return nil
}
2022-03-04 19:44:55 +00:00
func (c *TestContactData) UpdateContactChannels() (err error) {
var channels []Channel
if c.channelRevision == 0 || c.viewRevision != c.card.Data.NotifiedView {
token := c.card.Data.CardProfile.Guid + "." + c.card.Data.CardDetail.Token
params := &TestApiParams{ query: "/channels", tokenType: APP_TOKENCONTACT, token: token }
response := &TestApiResponse{ data: &channels }
if err = TestApiRequest(GetChannels, params, response); err != nil {
return
}
} else {
token := c.card.Data.CardProfile.Guid + "." + c.card.Data.CardDetail.Token
viewRevision := strconv.FormatInt(c.viewRevision, 10)
channelRevision := strconv.FormatInt(c.channelRevision, 10)
params := &TestApiParams{ query: "/channels?channelRevision=" + channelRevision + "&viewRevision=" + viewRevision,
tokenType: APP_TOKENCONTACT, token: token }
response := &TestApiResponse{ data: &channels }
if err = TestApiRequest(GetChannels, params, response); err != nil {
return
}
}
for _, channel := range channels {
if channel.Data == nil {
delete(c.channels, channel.Id)
} else {
tc, set := c.channels[channel.Id]
if set {
if channel.Revision != tc.channel.Revision {
if err = c.UpdateContactChannel(tc, &channel); err != nil {
return
}
tc.channel.Revision = channel.Revision
}
} else {
2022-03-04 20:43:46 +00:00
tc := &TestChannel{ channel: Channel{ Id: channel.Id, Data: &ChannelData{} } }
2022-03-04 19:44:55 +00:00
c.channels[channel.Id] = tc
if err = c.UpdateContactChannel(tc, &channel); err != nil {
return
}
tc.channel.Revision = channel.Revision
}
}
}
2022-03-04 20:43:46 +00:00
return
2022-03-04 19:44:55 +00:00
}
2022-03-04 20:43:46 +00:00
func (c *TestContactData) UpdateContactChannel(storeChannel *TestChannel, channel *Channel) (err error) {
if storeChannel.channel.Revision != channel.Revision {
if storeChannel.channel.Data.TopicRevision != channel.Data.TopicRevision {
if err = c.UpdateContactChannelTopics(storeChannel); err != nil {
return
}
storeChannel.channel.Data.TopicRevision = channel.Data.TopicRevision
}
2022-03-04 19:44:55 +00:00
if channel.Data.ChannelDetail != nil {
2022-03-04 20:43:46 +00:00
storeChannel.channel.Data.ChannelDetail = channel.Data.ChannelDetail
storeChannel.channel.Data.DetailRevision = channel.Data.DetailRevision
} else if storeChannel.channel.Data.DetailRevision != channel.Data.DetailRevision {
2022-03-04 19:44:55 +00:00
token := c.card.Data.CardProfile.Guid + "." + c.card.Data.CardDetail.Token
2022-03-04 20:43:46 +00:00
params := &TestApiParams{ query: "/channel/{channelId}", path: map[string]string{ "channelId": channel.Id },
tokenType: APP_TOKENCONTACT, token: token }
2022-03-04 19:44:55 +00:00
channel := Channel{}
response := &TestApiResponse{ data: &channel }
if err = TestApiRequest(GetChannel, params, response); err != nil {
return
}
if channel.Data == nil {
2022-03-04 20:43:46 +00:00
err = errors.New("channel removed during update")
return
2022-03-04 19:44:55 +00:00
}
2022-03-04 20:43:46 +00:00
storeChannel.channel.Data.ChannelDetail = channel.Data.ChannelDetail
storeChannel.channel.Data.DetailRevision = channel.Data.DetailRevision
2022-03-04 19:44:55 +00:00
}
}
return
}
2022-03-04 21:44:11 +00:00
func (c *TestContactData) UpdateContactChannelTopics(storeChannel *TestChannel) (err error) {
2022-03-04 19:44:55 +00:00
var topics []Topic
2022-03-04 21:44:11 +00:00
if storeChannel.channel.Revision == 0 {
2022-03-04 19:44:55 +00:00
token := c.card.Data.CardProfile.Guid + "." + c.card.Data.CardDetail.Token
params := &TestApiParams{ query: "/channels/{channelId}/topics",
2022-03-04 21:44:11 +00:00
path: map[string]string{ "channelId": storeChannel.channel.Id }, tokenType: APP_TOKENCONTACT, token: token }
2022-03-04 19:44:55 +00:00
response := &TestApiResponse{ data: &topics }
if err = TestApiRequest(GetChannelTopics, params, response); err != nil {
return
}
2022-03-04 21:44:11 +00:00
storeChannel.topics = make(map[string]*TestTopic)
2022-03-04 19:44:55 +00:00
} else {
token := c.card.Data.CardProfile.Guid + "." + c.card.Data.CardDetail.Token
2022-03-04 21:44:11 +00:00
revision := strconv.FormatInt(storeChannel.channel.Revision, 10)
2022-03-04 19:44:55 +00:00
params := &TestApiParams{ query: "/channels/{channelId}/topics?revision=" + revision,
2022-03-04 21:44:11 +00:00
path: map[string]string{ "channelId": storeChannel.channel.Id }, tokenType: APP_TOKENCONTACT, token: token }
2022-03-04 19:44:55 +00:00
response := &TestApiResponse{ data: &topics }
if err = TestApiRequest(GetChannelTopics, params, response); err != nil {
return
}
}
2022-03-04 21:44:11 +00:00
2022-03-04 19:44:55 +00:00
for _, topic := range topics {
2022-03-04 21:44:11 +00:00
if topic.Data == nil {
delete(storeChannel.topics, topic.Id)
2022-03-04 19:44:55 +00:00
} else {
2022-03-04 21:44:11 +00:00
storeTopic, set := storeChannel.topics[topic.Id]
if set {
if topic.Revision != storeTopic.topic.Revision {
if err = c.UpdateContactChannelTopic(storeChannel, storeTopic, &topic); err != nil {
return
}
storeTopic.topic.Revision = topic.Revision
}
} else {
storeTopic := &TestTopic{ topic: Topic{ Id: topic.Id, Data: &TopicData{} } }
storeChannel.topics[topic.Id] = storeTopic
if err = c.UpdateContactChannelTopic(storeChannel, storeTopic, &topic); err != nil {
return
}
storeTopic.topic.Revision = topic.Revision
}
}
}
return
}
func (c *TestContactData) UpdateContactChannelTopic(storeChannel *TestChannel, storeTopic *TestTopic, topic *Topic) (err error) {
if storeTopic.topic.Revision != topic.Revision {
if storeTopic.topic.Data.TagRevision != topic.Data.TagRevision {
if err = c.UpdateContactChannelTopicTags(storeChannel, storeTopic); err != nil {
return
}
storeTopic.topic.Data.TagRevision = topic.Data.TagRevision
}
if topic.Data.TopicDetail != nil {
storeTopic.topic.Data.TopicDetail = topic.Data.TopicDetail
storeTopic.topic.Data.DetailRevision = topic.Data.DetailRevision
} else if storeTopic.topic.Data.DetailRevision != topic.Data.DetailRevision {
token := c.card.Data.CardProfile.Guid + "." + c.card.Data.CardDetail.Token
params := &TestApiParams{ query: "/channels/{channelId}/topics/{topicId}",
path: map[string]string{ "channelId": storeChannel.channel.Id, "topicId": topic.Id },
tokenType: APP_TOKENCONTACT, token: token }
topic := Topic{}
response := &TestApiResponse{ data: &topic }
if err = TestApiRequest(GetChannelTopic, params, response); err != nil {
return
}
if topic.Data == nil {
err = errors.New("topic removed during update")
return
}
storeTopic.topic.Data.TopicDetail = topic.Data.TopicDetail
storeTopic.topic.Data.DetailRevision = topic.Data.DetailRevision
}
}
return
}
func (c *TestContactData) UpdateContactChannelTopicTags(storeChannel *TestChannel, storeTopic *TestTopic) (err error) {
var tags []Tag
if storeTopic.topic.Revision == 0 {
token := c.card.Data.CardProfile.Guid + "." + c.card.Data.CardDetail.Token
params := &TestApiParams{ query: "/channels/{channelId}/topics/{topicId}/tags",
path: map[string]string{ "channelId": storeChannel.channel.Id, "topicId": storeTopic.topic.Id },
tokenType: APP_TOKENCONTACT, token: token }
response := &TestApiResponse{ data: &tags }
if err = TestApiRequest(GetChannelTopicTags, params, response); err != nil {
return
}
storeTopic.tags = make(map[string]*Tag)
} else {
revision := strconv.FormatInt(storeTopic.topic.Revision, 10)
token := c.card.Data.CardProfile.Guid + "." + c.card.Data.CardDetail.Token
params := &TestApiParams{ query: "/channels/{channelId}/topics/{topicId}/tags?revision=" + revision,
path: map[string]string{ "channelId": storeChannel.channel.Id, "topicId": storeTopic.topic.Id },
tokenType: APP_TOKENCONTACT, token: token }
response := &TestApiResponse{ data: &tags }
if err = TestApiRequest(GetChannelTopicTags, params, response); err != nil {
return
}
}
for _, tag := range tags {
if tag.Data == nil {
delete(storeTopic.tags, tag.Id)
} else {
storeTopic.tags[tag.Id] = &tag
2022-03-04 19:44:55 +00:00
}
}
2022-03-04 20:43:46 +00:00
return
2022-02-22 23:02:31 +00:00
}
2022-02-23 06:11:56 +00:00
func (c *TestContactData) UpdateContactCardDetail() (err error) {
2022-02-23 23:00:11 +00:00
var cardDetail CardDetail
params := &TestApiParams{ query: "/contact/cards/{cardId}/detail", tokenType: APP_TOKENAPP, token: c.token,
path: map[string]string{ "cardId": c.card.Id } }
response := &TestApiResponse{ data: &cardDetail }
if err = TestApiRequest(GetCardDetail, params, response); err != nil {
return
}
c.card.Data.CardDetail = &cardDetail
return
2022-02-23 06:11:56 +00:00
}
func (c *TestContactData) UpdateContactCardProfile() (err error) {
2022-02-23 23:00:11 +00:00
var cardProfile CardProfile
params := &TestApiParams{ query: "/contact/cards/{cardId}/profile", tokenType: APP_TOKENAPP, token: c.token,
path: map[string]string{ "cardId": c.card.Id } }
response := &TestApiResponse{ data: &cardProfile }
if err = TestApiRequest(GetCardProfile, params, response); err != nil {
return
}
c.card.Data.CardProfile = &cardProfile
return
2022-02-20 08:15:04 +00:00
}
func NewTestApp() *TestApp {
return &TestApp{
2022-03-03 19:34:07 +00:00
groups: make(map[string]*Group),
articles: make(map[string]*Article),
channels: make(map[string]*TestChannel),
2022-02-22 23:02:31 +00:00
contacts: make(map[string]*TestContactData),
2022-02-20 08:15:04 +00:00
}
}
type TestApp struct {
name string
revision Revision
profile Profile
2022-03-03 19:34:07 +00:00
groups map[string]*Group
articles map[string]*Article
channels map[string]*TestChannel
2022-02-22 23:02:31 +00:00
contacts map[string]*TestContactData
2022-02-20 08:15:04 +00:00
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
}
2022-03-03 19:34:07 +00:00
func (a *TestApp) UpdateGroups() (err error) {
2022-02-22 06:47:23 +00:00
var groups []Group
if a.revision.Group == 0 {
params := &TestApiParams{ query: "/groups", tokenType: APP_TOKENAPP, token: a.token }
response := &TestApiResponse{ data: &groups }
if err = TestApiRequest(GetGroups, params, response); err != nil {
return
}
} else {
revision := strconv.FormatInt(a.revision.Group, 10)
params := &TestApiParams{ query: "/groups?revision=" + revision, tokenType: APP_TOKENAPP, token: a.token }
response := &TestApiResponse{ data: &groups }
if err = TestApiRequest(GetGroups, params, response); err != nil {
return
}
}
for _, group := range groups {
if group.Data == nil {
delete(a.groups, group.Id)
} else {
2022-03-03 19:34:07 +00:00
a.groups[group.Id] = &group
2022-02-22 06:47:23 +00:00
}
}
return
}
2022-03-03 19:34:07 +00:00
func (a *TestApp) UpdateArticles() (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)
2022-02-22 05:52:49 +00:00
params := &TestApiParams{ query: "/articles?articleRevision=" + revision, tokenType: APP_TOKENAPP, token: a.token }
2022-02-21 23:00:26 +00:00
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 {
2022-03-03 19:34:07 +00:00
a.articles[article.Id] = &article
2022-02-21 23:00:26 +00:00
}
}
2022-02-21 22:42:49 +00:00
return
}
2022-03-03 19:34:07 +00:00
func (a *TestApp) UpdateChannels() (err error) {
var channels []Channel
if a.revision.Channel == 0 {
params := &TestApiParams{ query: "/channels", tokenType: APP_TOKENAPP, token: a.token }
response := &TestApiResponse{ data: &channels }
if err = TestApiRequest(GetChannels, params, response); err != nil {
return
}
} else {
revision := strconv.FormatInt(a.revision.Channel, 10)
params := &TestApiParams{ query: "/channels?channelRevision=" + revision, tokenType: APP_TOKENAPP, token: a.token }
response := &TestApiResponse{ data: &channels }
if err = TestApiRequest(GetChannels, params, response); err != nil {
return
}
}
for _, channel := range channels {
if channel.Data == nil {
delete(a.channels, channel.Id)
} else {
2022-03-04 20:43:46 +00:00
storeChannel, set := a.channels[channel.Id]
2022-03-03 19:34:07 +00:00
if set {
2022-03-04 20:43:46 +00:00
if channel.Revision != storeChannel.channel.Revision {
if err = a.UpdateChannel(storeChannel, &channel); err != nil {
2022-03-03 19:34:07 +00:00
return
}
2022-03-04 20:43:46 +00:00
storeChannel.channel.Revision = channel.Revision
2022-03-03 19:34:07 +00:00
}
} else {
2022-03-04 20:43:46 +00:00
storeChannel := &TestChannel{ channel: Channel{ Id: channel.Id, Data: &ChannelData{} } }
a.channels[channel.Id] = storeChannel
if err = a.UpdateChannel(storeChannel, &channel); err != nil {
2022-03-03 19:34:07 +00:00
return
}
2022-03-04 20:43:46 +00:00
storeChannel.channel.Revision = channel.Revision
2022-03-03 19:34:07 +00:00
}
}
}
return
}
2022-03-04 20:43:46 +00:00
func (a *TestApp) UpdateChannel(storeChannel *TestChannel, channel *Channel) (err error) {
if storeChannel.channel.Revision != channel.Revision {
if storeChannel.channel.Data.TopicRevision != channel.Data.TopicRevision {
if err = a.UpdateChannelTopics(storeChannel); err != nil {
return
}
storeChannel.channel.Data.TopicRevision = channel.Data.TopicRevision
}
2022-03-03 19:34:07 +00:00
if channel.Data.ChannelDetail != nil {
2022-03-04 20:43:46 +00:00
storeChannel.channel.Data.ChannelDetail = channel.Data.ChannelDetail
storeChannel.channel.Data.DetailRevision = channel.Data.DetailRevision
} else if storeChannel.channel.Data.DetailRevision != channel.Data.DetailRevision {
params := &TestApiParams{ query: "/channel/{channelId}", path: map[string]string{ "channelId": channel.Id },
tokenType: APP_TOKENAPP, token: a.token }
channel := Channel{}
response := &TestApiResponse{ data: &channel }
2022-03-03 19:34:07 +00:00
if err = TestApiRequest(GetChannel, params, response); err != nil {
return
}
2022-03-04 20:43:46 +00:00
if channel.Data == nil {
err = errors.New("channel removed during update")
return
2022-03-03 19:34:07 +00:00
}
2022-03-04 20:43:46 +00:00
storeChannel.channel.Data.ChannelDetail = channel.Data.ChannelDetail
storeChannel.channel.Data.DetailRevision = channel.Data.DetailRevision
2022-03-03 19:34:07 +00:00
}
}
2022-02-21 22:42:49 +00:00
return
}
2022-03-04 21:44:11 +00:00
func (a *TestApp) UpdateChannelTopics(storeChannel *TestChannel) (err error) {
2022-03-04 19:44:55 +00:00
var topics []Topic
2022-03-04 21:44:11 +00:00
if storeChannel.channel.Revision == 0 {
2022-03-04 19:44:55 +00:00
params := &TestApiParams{ query: "/channels/{channelId}/topics",
2022-03-04 21:44:11 +00:00
path: map[string]string{ "channelId": storeChannel.channel.Id }, tokenType: APP_TOKENAPP, token: a.token }
2022-03-04 19:44:55 +00:00
response := &TestApiResponse{ data: &topics }
if err = TestApiRequest(GetChannelTopics, params, response); err != nil {
return
}
2022-03-04 21:44:11 +00:00
storeChannel.topics = make(map[string]*TestTopic)
2022-03-04 19:44:55 +00:00
} else {
2022-03-04 21:44:11 +00:00
revision := strconv.FormatInt(storeChannel.channel.Revision, 10)
2022-03-04 19:44:55 +00:00
params := &TestApiParams{ query: "/channels/{channelId}/topics?revision=" + revision,
2022-03-04 21:44:11 +00:00
path: map[string]string{ "channelId": storeChannel.channel.Id }, tokenType: APP_TOKENAPP, token: a.token }
2022-03-04 19:44:55 +00:00
response := &TestApiResponse{ data: &topics }
if err = TestApiRequest(GetChannelTopics, params, response); err != nil {
return
}
}
2022-03-04 21:44:11 +00:00
2022-03-04 19:44:55 +00:00
for _, topic := range topics {
2022-03-04 21:44:11 +00:00
if topic.Data == nil {
delete(storeChannel.topics, topic.Id)
} else {
storeTopic, set := storeChannel.topics[topic.Id]
if set {
if topic.Revision != storeTopic.topic.Revision {
if err = a.UpdateChannelTopic(storeChannel, storeTopic, &topic); err != nil {
return
}
storeTopic.topic.Revision = topic.Revision
}
} else {
storeTopic := &TestTopic{ topic: Topic{ Id: topic.Id, Data: &TopicData{} } }
storeChannel.topics[topic.Id] = storeTopic
if err = a.UpdateChannelTopic(storeChannel, storeTopic, &topic); err != nil {
return
}
storeTopic.topic.Revision = topic.Revision
}
}
}
return
}
func (a *TestApp) UpdateChannelTopic(storeChannel *TestChannel, storeTopic *TestTopic, topic *Topic) (err error) {
if storeTopic.topic.Revision != topic.Revision {
if storeTopic.topic.Data.TagRevision != topic.Data.TagRevision {
if err = a.UpdateChannelTopicTags(storeChannel, storeTopic); err != nil {
return
}
storeTopic.topic.Data.TagRevision = topic.Data.TagRevision
}
if topic.Data.TopicDetail != nil {
storeTopic.topic.Data.TopicDetail = topic.Data.TopicDetail
storeTopic.topic.Data.DetailRevision = topic.Data.DetailRevision
} else if storeTopic.topic.Data.DetailRevision != topic.Data.DetailRevision {
params := &TestApiParams{ query: "/channels/{channelId}/topics/{topicId}",
path: map[string]string{ "channelId": storeChannel.channel.Id, "topicId": topic.Id },
tokenType: APP_TOKENAPP, token: a.token }
topic := Topic{}
response := &TestApiResponse{ data: &topic }
if err = TestApiRequest(GetChannelTopic, params, response); err != nil {
return
}
if topic.Data == nil {
err = errors.New("topic removed during update")
return
}
storeTopic.topic.Data.TopicDetail = topic.Data.TopicDetail
storeTopic.topic.Data.DetailRevision = topic.Data.DetailRevision
}
}
return
}
func (a *TestApp) UpdateChannelTopicTags(storeChannel *TestChannel, storeTopic *TestTopic) (err error) {
var tags []Tag
if storeTopic.topic.Revision == 0 {
params := &TestApiParams{ query: "/channels/{channelId}/topics/{topicId}/tags",
path: map[string]string{ "channelId": storeChannel.channel.Id, "topicId": storeTopic.topic.Id },
tokenType: APP_TOKENAPP, token: a.token }
response := &TestApiResponse{ data: &tags }
if err = TestApiRequest(GetChannelTopicTags, params, response); err != nil {
return
}
storeTopic.tags = make(map[string]*Tag)
} else {
revision := strconv.FormatInt(storeTopic.topic.Revision, 10)
params := &TestApiParams{ query: "/channels/{channelId}/topics/{topicId}/tags?revision=" + revision,
path: map[string]string{ "channelId": storeChannel.channel.Id, "topicId": storeTopic.topic.Id },
tokenType: APP_TOKENAPP, token: a.token }
response := &TestApiResponse{ data: &tags }
if err = TestApiRequest(GetChannelTopicTags, params, response); err != nil {
return
}
}
for _, tag := range tags {
if tag.Data == nil {
delete(storeTopic.tags, tag.Id)
2022-03-04 19:44:55 +00:00
} else {
2022-03-04 21:44:11 +00:00
storeTopic.tags[tag.Id] = &tag
2022-03-04 19:44:55 +00:00
}
}
2022-03-04 20:43:46 +00:00
return
2022-03-04 19:44:55 +00:00
}
2022-03-03 19:34:07 +00:00
func (a *TestApp) UpdateCards() (err error) {
2022-02-22 23:02:31 +00:00
var cards []Card
if a.revision.Card == 0 {
params := &TestApiParams{ query: "/cards", tokenType: APP_TOKENAPP, token: a.token }
response := &TestApiResponse{ data: &cards }
if err = TestApiRequest(GetCards, params, response); err != nil {
return
}
for _, card := range cards {
if card.Data == nil {
delete(a.contacts, card.Id)
} else {
// set new card
2022-03-03 19:34:07 +00:00
contactData := &TestContactData{ card: card, articles: make(map[string]*Article), channels: make(map[string]*TestChannel),
2022-02-23 23:00:11 +00:00
cardDetailRevision: card.Data.DetailRevision, cardProfileRevision: card.Data.ProfileRevision,
profileRevision: card.Data.ProfileRevision, token: a.token }
2022-02-22 23:02:31 +00:00
a.contacts[card.Id] = contactData
if err = contactData.UpdateContact(); err != nil {
contactData.offsync = true
PrintMsg(err)
}
}
}
} else {
revision := strconv.FormatInt(a.revision.Card, 10)
params := &TestApiParams{ query: "/cards?revision=" + revision, tokenType: APP_TOKENAPP, token: a.token }
response := &TestApiResponse{ data: &cards }
if err = TestApiRequest(GetCards, params, response); err != nil {
return
}
for _, card := range cards {
if card.Data == nil {
delete(a.contacts, card.Id)
} else {
contactData, set := a.contacts[card.Id]
if !set {
// download new card
params := &TestApiParams{ query: "/cards/{cardId}", path: map[string]string{ "cardId": card.Id },
tokenType: APP_TOKENAPP, token: a.token }
response := &TestApiResponse{ data: &card }
if err = TestApiRequest(GetCard, params, response); err != nil {
return
}
2022-03-03 19:34:07 +00:00
contactData := &TestContactData{ card: card, articles: make(map[string]*Article), channels: make(map[string]*TestChannel),
2022-02-23 23:00:11 +00:00
cardDetailRevision: card.Data.DetailRevision, cardProfileRevision: card.Data.ProfileRevision,
profileRevision: card.Data.ProfileRevision, token: a.token }
2022-02-22 23:02:31 +00:00
a.contacts[card.Id] = contactData
if err = contactData.UpdateContact(); err != nil {
contactData.offsync = true
PrintMsg(err)
}
} else {
// update existing card revisions
contactData.card.Data.NotifiedProfile = card.Data.NotifiedProfile
contactData.card.Data.NotifiedArticle = card.Data.NotifiedArticle
contactData.card.Data.NotifiedChannel = card.Data.NotifiedChannel
contactData.card.Data.NotifiedView = card.Data.NotifiedView
contactData.card.Data.DetailRevision = card.Data.DetailRevision
contactData.card.Data.ProfileRevision = card.Data.ProfileRevision
if err = contactData.UpdateContact(); err != nil {
contactData.offsync = true
PrintMsg(err)
}
}
}
}
}
2022-02-21 22:42:49 +00:00
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.Group != a.revision.Group {
2022-03-03 19:34:07 +00:00
if err := a.UpdateGroups(); err != nil {
2022-02-21 22:42:49 +00:00
PrintMsg(err)
} else {
a.revision.Group = rev.Group
}
}
2022-02-22 06:47:23 +00:00
if rev.Article != a.revision.Article {
2022-03-03 19:34:07 +00:00
if err := a.UpdateArticles(); err != nil {
2022-02-21 22:42:49 +00:00
PrintMsg(err)
} else {
2022-02-22 06:47:23 +00:00
a.revision.Article = rev.Article
2022-02-21 22:42:49 +00:00
}
}
if rev.Card != a.revision.Card {
2022-03-03 19:34:07 +00:00
if err := a.UpdateCards(); err != nil {
2022-02-21 22:42:49 +00:00
PrintMsg(err)
} else {
a.revision.Card = rev.Card
}
}
2022-02-22 06:47:23 +00:00
if rev.Channel != a.revision.Channel {
2022-03-03 19:34:07 +00:00
if err := a.UpdateChannels(); err != nil {
2022-02-22 06:47:23 +00:00
PrintMsg(err)
} else {
a.revision.Channel = rev.Channel
}
}
2022-02-20 08:15:04 +00:00
if a.condition != nil {
if a.condition.check(a) {
2022-02-23 06:11:56 +00:00
select {
case a.condition.channel <- true:
default:
}
2022-02-20 08:15:04 +00:00
}
}
}
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
2022-03-08 21:31:04 +00:00
authorization string
credentials string
2022-02-21 22:42:49 +00:00
}
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"
}
2022-03-20 06:01:18 +00:00
if params.tokenType == APP_TOKENAPP {
if !strings.Contains(params.query, "?") {
params.query += "?"
} else {
params.query += "&"
}
params.query += "agent=" + params.token
} else if params.tokenType == APP_TOKENCONTACT {
if !strings.Contains(params.query, "?") {
params.query += "?"
} else {
params.query += "&"
}
params.query += "contact=" + params.token
}
2022-02-21 22:42:49 +00:00
if r, w, err = NewRequest(rest, params.query, params.body); err != nil {
return
}
r = mux.SetURLVars(r, params.path)
2022-03-20 06:01:18 +00:00
2022-02-21 22:42:49 +00:00
if params.tokenType != "" {
r.Header.Add("TokenType", params.tokenType)
}
if params.token != "" {
SetBearerAuth(r, params.token)
}
2022-03-20 06:01:18 +00:00
2022-03-08 21:31:04 +00:00
if params.authorization != "" {
SetBasicAuth(r, params.authorization)
}
if params.credentials != "" {
SetCredentials(r, params.credentials)
}
2022-03-20 06:01:18 +00:00
2022-02-21 22:42:49 +00:00
endpoint(w, r)
res := w.Result()
if res.StatusCode != 200 && res.StatusCode != 410 {
err = errors.New("response failed");
return
}
2022-03-08 21:31:04 +00:00
if resp != nil {
resp.header = res.Header
if resp.data != nil {
dec := json.NewDecoder(res.Body)
if err = dec.Decode(resp.data); err != nil {
return
}
2022-02-21 22:42:49 +00:00
}
}
return
}
2022-02-20 08:15:04 +00:00