func hereNow(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() channel := q.Get("ch") uuid := q.Get("uuid") hereNowShowUUID := q.Get("showUUID") hereNowIncludeUserState := q.Get("includeUserState") disableUUID := false includeUserState := false if hereNowShowUUID == "1" { disableUUID = true } if hereNowIncludeUserState == "1" { includeUserState = true } errorChannel := make(chan []byte) successChannel := make(chan []byte) //c := context.NewContext(r) c := createContext(r) pubInstance := messaging.New(c, uuid, w, r, publishKey, subscribeKey, secretKey, "", false) go pubInstance.HereNow(c, w, r, channel, disableUUID, includeUserState, successChannel, errorChannel) handleResult(c, w, r, uuid, successChannel, errorChannel, messaging.GetNonSubscribeTimeout(), "HereNow") }
// TestSuccessCodeAndInfo sends out a message to the pubnub channel // The response is parsed and should match the 'sent' status. // _publishSuccessMessage is defined in the common.go file func TestSuccessCodeAndInfo(t *testing.T) { context, err := aetest.NewContext(nil) if err != nil { t.Fatal(err) } defer context.Close() uuid := "" w, req := InitAppEngineContext(t) pubnubInstance := messaging.New(context, uuid, w, req, PubKey, SubKey, "", "", false) //pubnubInstance := messaging.NewPubnub(PubKey, SubKey, "", "", false, "") channel := "testChannel" message := "Pubnub API Usage Example" returnChannel := make(chan []byte) errorChannel := make(chan []byte) responseChannel := make(chan string) waitChannel := make(chan string) //go pubnubInstance.Publish(channel, message, returnChannel, errorChannel) go pubnubInstance.Publish(context, w, req, channel, message, returnChannel, errorChannel) go ParsePublishResponse(returnChannel, channel, publishSuccessMessage, "SuccessCodeAndInfo", responseChannel) go ParseErrorResponse(errorChannel, responseChannel) go WaitForCompletion(responseChannel, waitChannel) ParseWaitResponse(waitChannel, t, "SuccessCodeAndInfo") time.Sleep(2 * time.Second) }
// TestSuccessCodeAndInfoForComplexMessage sends out a complex message to the pubnub channel // The response is parsed and should match the 'sent' status. // _publishSuccessMessage and customstruct is defined in the common.go file func TestSuccessCodeAndInfoForComplexMessage(t *testing.T) { context, err := aetest.NewContext(nil) if err != nil { t.Fatal(err) } defer context.Close() uuid := "" w, req := InitAppEngineContext(t) pubnubInstance := messaging.New(context, uuid, w, req, PubKey, SubKey, "", "", false) //pubnubInstance := messaging.NewPubnub(PubKey, SubKey, "", "", false, "", "", false) channel := "testChannel" customStruct := CustomStruct{ Foo: "hi!", Bar: []int{1, 2, 3, 4, 5}, } returnChannel := make(chan []byte) errorChannel := make(chan []byte) responseChannel := make(chan string) waitChannel := make(chan string) //go pubnubInstance.Publish(channel, customStruct, returnChannel, errorChannel) go pubnubInstance.Publish(context, w, req, channel, customStruct, returnChannel, errorChannel) go ParsePublishResponse(returnChannel, channel, publishSuccessMessage, "SuccessCodeAndInfoForComplexMessage", responseChannel) go ParseErrorResponse(errorChannel, responseChannel) go WaitForCompletion(responseChannel, waitChannel) ParseWaitResponse(waitChannel, t, "SuccessCodeAndInfoForComplexMessage") time.Sleep(2 * time.Second) }
// TestNullMessage sends out a null message to a pubnub channel. The response should // be an "Invalid Message". func TestNullMessage(t *testing.T) { context, err := aetest.NewContext(nil) if err != nil { t.Fatal(err) } defer context.Close() uuid := "" w, req := InitAppEngineContext(t) pubnubInstance := messaging.New(context, uuid, w, req, PubKey, SubKey, "", "", false) //pubnubInstance := messaging.NewPubnub(PubKey, SubKey, "", "", false, "") channel := "testChannel" var message interface{} message = nil returnChannel := make(chan []byte) errorChannel := make(chan []byte) responseChannel := make(chan string) waitChannel := make(chan string) //go pubnubInstance.Publish(channel, message, returnChannel, errorChannel) go pubnubInstance.Publish(context, w, req, channel, message, returnChannel, errorChannel) //go ParsePublishResponse(returnChannel, channel, "Invalid Message", "NullMessage", responseChannel) go ParseResponseDummy(returnChannel) go ParseErrorResponseForTestSuccess("Invalid Message", errorChannel, responseChannel) //go ParseErrorResponse(errorChannel, responseChannel) go WaitForCompletion(responseChannel, waitChannel) ParseWaitResponse(waitChannel, t, "NullMessage") }
// TestServerTime calls the GetTime method of the messaging to test the time func TestServerTime(t *testing.T) { /*context, err := aetest.NewContext(nil) if err != nil { t.Fatal(err) } defer context.Close()*/ inst, err := aetest.NewInstance(&aetest.Options{"", true}) context := CreateContext(inst) if err != nil { t.Fatal(err) } defer inst.Close() uuid := "" w, req := InitAppEngineContext(t) pubnubInstance := messaging.New(context, uuid, w, req, PubKey, SubKey, "", "", false) //pubnubInstance := messaging.NewPubnub(PubKey, SubKey, "", "", false, "") returnTimeChannel := make(chan []byte) errorChannel := make(chan []byte) responseChannel := make(chan string) waitChannel := make(chan string) //go pubnubInstance.GetTime(returnTimeChannel, errorChannel) go pubnubInstance.GetTime(context, w, req, returnTimeChannel, errorChannel) go ParseTimeResponse(returnTimeChannel, responseChannel) go ParseErrorResponse(errorChannel, responseChannel) go WaitForCompletion(responseChannel, waitChannel) ParseWaitResponse(waitChannel, t, "Time") }
func grantSubscribe(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() ch := q.Get("ch") read := q.Get("r") write := q.Get("w") ttl := q.Get("ttl") bRead := false if read == "1" { bRead = true } bWrite := false if write == "1" { bWrite = true } iTTL := 1440 if ival, err := strconv.Atoi(ttl); err == nil { iTTL = ival } uuid := q.Get("uuid") c := appengine.NewContext(r) pubInstance := messaging.New(c, uuid, w, r, publishKey, subscribeKey, secretKey, "", false) errorChannel := make(chan []byte) successChannel := make(chan []byte) go pubInstance.GrantSubscribe(c, w, r, ch, bRead, bWrite, iTTL, successChannel, errorChannel) handleResult(c, w, r, uuid, successChannel, errorChannel, messaging.GetNonSubscribeTimeout(), "Revoke Subscribe") }
func getAuthKey(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() uuid := q.Get("uuid") c := appengine.NewContext(r) pubInstance := messaging.New(c, uuid, w, r, publishKey, subscribeKey, secretKey, "", false) sendResponseToChannel(w, "Auth key: "+pubInstance.GetAuthenticationKey(), r, uuid) }
func revokeSubscribe(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() ch := q.Get("ch") uuid := q.Get("uuid") c := appengine.NewContext(r) pubInstance := messaging.New(c, uuid, w, r, publishKey, subscribeKey, secretKey, "", false) errorChannel := make(chan []byte) successChannel := make(chan []byte) go pubInstance.GrantSubscribe(c, w, r, ch, false, false, 0, successChannel, errorChannel) handleResult(c, w, r, uuid, successChannel, errorChannel, messaging.GetNonSubscribeTimeout(), "Revoke Subscribe") }
func setAuthKey(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() authKey := q.Get("authkey") uuid := q.Get("uuid") //c := context.NewContext(r) c := createContext(r) pubInstance := messaging.New(c, uuid, w, r, publishKey, subscribeKey, secretKey, "", false) pubInstance.SetAuthenticationKey(c, w, r, authKey) sendResponseToChannel(w, "Auth key set", r, uuid) }
func auditPresence(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() ch := q.Get("ch") uuid := q.Get("uuid") //c := context.NewContext(r) c := createContext(r) pubInstance := messaging.New(c, uuid, w, r, publishKey, subscribeKey, secretKey, "", false) errorChannel := make(chan []byte) successChannel := make(chan []byte) go pubInstance.AuditPresence(c, w, r, ch, "", successChannel, errorChannel) handleResult(c, w, r, uuid, successChannel, errorChannel, messaging.GetNonSubscribeTimeout(), "Audit Presence") }
func whereNow(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() whereNowUUID := q.Get("whereNowUUID") uuid := q.Get("uuid") errorChannel := make(chan []byte) successChannel := make(chan []byte) c := appengine.NewContext(r) pubInstance := messaging.New(c, uuid, w, r, publishKey, subscribeKey, secretKey, "", false) go pubInstance.WhereNow(c, w, r, whereNowUUID, successChannel, errorChannel) handleResult(c, w, r, uuid, successChannel, errorChannel, messaging.GetNonSubscribeTimeout(), "WhereNow") }
func deleteUserState(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() ch := q.Get("ch") key := q.Get("k") uuid := q.Get("uuid") c := appengine.NewContext(r) pubInstance := messaging.New(c, uuid, w, r, publishKey, subscribeKey, secretKey, "", false) errorChannel := make(chan []byte) successChannel := make(chan []byte) go pubInstance.SetUserStateKeyVal(c, w, r, ch, key, "", successChannel, errorChannel) handleResult(c, w, r, uuid, successChannel, errorChannel, messaging.GetNonSubscribeTimeout(), "Del User State") }
// DetailedHistoryFor10Messages is a common method used by both TestDetailedHistoryFor10EncryptedMessages // and TestDetailedHistoryFor10Messages to publish's 10 messages to a pubnub channel, and after that // call the history method of the messaging package to fetch last 10 messages. These received // messages are compared to the messages sent and if all match test is successful. func DetailedHistoryFor10Messages(t *testing.T, cipherKey string, testName string) { numberOfMessages := 10 startMessagesFrom := 0 /*context, err := aetest.NewContext(nil) if err != nil { t.Fatal(err) } defer context.Close() w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/", nil)*/ //context, err := aetest.NewContext(nil) //req, _ := http.NewRequest("GET", "/", nil) inst, err := aetest.NewInstance(&aetest.Options{"", true}) context := CreateContext(inst) if err != nil { t.Fatal(err) } //defer context.Close() defer inst.Close() uuid := "" w, req := InitAppEngineContext(t) //pubnubInstance := messaging.NewPubnub(PubKey, SubKey, SecKey, cipherKey, false, "") pubnubInstance := messaging.New(context, uuid, w, req, PubKey, SubKey, SecKey, "", false) message := "Test Message " r := GenRandom() channel := fmt.Sprintf("testChannel_dh_%d", r.Intn(20)) messagesSent := PublishMessages(context, w, req, pubnubInstance, channel, t, startMessagesFrom, numberOfMessages, message) if messagesSent { returnHistoryChannel := make(chan []byte) errorChannel := make(chan []byte) responseChannel := make(chan string) waitChannel := make(chan string) //go pubnubInstance.History(channel, numberOfMessages, 0, 0, false, returnHistoryChannel, errorChannel) go pubnubInstance.History(context, w, req, channel, numberOfMessages, 0, 0, false, returnHistoryChannel, errorChannel) go ParseHistoryResponseForMultipleMessages(returnHistoryChannel, channel, message, testName, startMessagesFrom, numberOfMessages, cipherKey, responseChannel) go ParseErrorResponse(errorChannel, responseChannel) go WaitForCompletion(responseChannel, waitChannel) ParseWaitResponse(waitChannel, t, testName) } else { t.Error("Test '" + testName + "': failed.") } }
func detailedHistory(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() ch := q.Get("ch") uuid := q.Get("uuid") start := q.Get("start") var iStart int64 if strings.TrimSpace(start) != "" { bi := big.NewInt(0) if _, ok := bi.SetString(start, 10); !ok { iStart = 0 } else { iStart = bi.Int64() } } end := q.Get("end") var iEnd int64 if strings.TrimSpace(end) != "" { bi := big.NewInt(0) if _, ok := bi.SetString(end, 10); !ok { iEnd = 0 } else { iEnd = bi.Int64() } } limit := q.Get("limit") reverse := q.Get("reverse") iLimit := 100 if ival, err := strconv.Atoi(limit); err == nil { iLimit = ival } bReverse := false if reverse == "1" { bReverse = true } // ctx := context.NewContext(r) ctx := createContext(r) pubInstance := messaging.New(ctx, uuid, w, r, publishKey, subscribeKey, secretKey, "", false) errorChannel := make(chan []byte) successChannel := make(chan []byte) go pubInstance.History(ctx, w, r, ch, iLimit, iStart, iEnd, bReverse, successChannel, errorChannel) handleResult(ctx, w, r, uuid, successChannel, errorChannel, messaging.GetNonSubscribeTimeout(), "Detailed History") }
func publish(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() message := q.Get("m") uuid := q.Get("uuid") ch := q.Get("ch") fire := q.Get("fire") //meta, _ := url.QueryUnescape(q.Get("meta")) metaKey := q.Get("metakey") metaVal := q.Get("metaval") storeInHistory := q.Get("storeInHistory") storeInHistoryBool := false if storeInHistory == "1" { storeInHistoryBool = true } errorChannel := make(chan []byte) successChannel := make(chan []byte) meta := make(map[string]string) if strings.TrimSpace(metaKey) != "" && strings.TrimSpace(metaVal) != "" { meta[metaKey] = metaVal } else { meta = nil } //c := context.NewContext(r) c := createContext(r) /*message1 := make(map[string]string) message1["author"] = "user-a" message1["status"] = "I am reading about Advanced Channel Groups!" message1["timestamp"] = time.Now().String()*/ pubInstance := messaging.New(c, uuid, w, r, publishKey, subscribeKey, secretKey, "", false) //go pubInstance.Publish(c, w, r, "my_channel", message1, successChannel, errorChannel) if fire == "1" { go pubInstance.Fire(c, w, r, ch, message, false, successChannel, errorChannel) } else if meta != nil { log.Infof(c, fmt.Sprintf("Meta: %s", meta)) go pubInstance.PublishExtendedWithMeta(c, w, r, ch, message, meta, storeInHistoryBool, false, successChannel, errorChannel) } else if storeInHistoryBool { go pubInstance.PublishExtended(c, w, r, ch, message, storeInHistoryBool, false, successChannel, errorChannel) } else { go pubInstance.Publish(c, w, r, ch, message, successChannel, errorChannel) } handleResult(c, w, r, uuid, successChannel, errorChannel, messaging.GetNonSubscribeTimeout(), "Publish") }
// Publish a message using a PubNub client func Publish(c appengine.Context, w http.ResponseWriter, r *http.Request, ch string, m *PubMessage) { uuid := "Server" // Will make custom UUID if empty string message, err := json.Marshal(m) if err != nil { c.Infof("Bad JSON!") return } errorChannel := make(chan []byte) successChannel := make(chan []byte) timeoutChannel := make(chan bool, 1) // Boolean channel of size 1 // func New(context, uuid, writer, request, publishKey, subscribeKey, secretKey, cipher, ssl bool) *Pubnub pubInstance := messaging.New(c, uuid, w, r, publishKey, subscribeKey, secretKey, "", false) go pubInstance.Publish(c, w, r, ch, message, successChannel, errorChannel) go func() { time.Sleep(1 * time.Second) // Quit after 1 seconds timeoutChannel <- true }() for { select { case success, ok := <-successChannel: if !ok { c.Infof("success!OK") break } if string(success) != "[]" { c.Infof("success:", string(success)) } return case failure, ok := <-errorChannel: if !ok { c.Infof("fail1:", string("failure")) break } if string(failure) != "[]" { c.Infof("fail:", string(failure)) } return case <-timeoutChannel: c.Infof("timeout:", string("NonSubscribeTimeout")) return } } }
func setUserState(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() ch := q.Get("ch") k := q.Get("k") v := q.Get("v") uuid := q.Get("uuid") //c := context.NewContext(r) c := createContext(r) pubInstance := messaging.New(c, uuid, w, r, publishKey, subscribeKey, secretKey, "", false) errorChannel := make(chan []byte) successChannel := make(chan []byte) //setUserState go pubInstance.SetUserStateKeyVal(c, w, r, ch, k, v, successChannel, errorChannel) handleResult(c, w, r, uuid, successChannel, errorChannel, messaging.GetNonSubscribeTimeout(), "Set User State") }
func handler(w http.ResponseWriter, r *http.Request) { c := createContext(r) log.Infof(c, "IN handler") uuid := "" pubInstance := messaging.New(c, uuid, w, r, publishKey, subscribeKey, secretKey, "", false) if pubInstance == nil { log.Errorf(c, "Couldn't create pubnub instance") http.Error(w, "Couldn't create pubnub instance", http.StatusInternalServerError) return } nuuid := pubInstance.GetUUID() session, err := store.Get(r, "example-session") if err != nil { log.Errorf(c, "Session store error %s", err.Error()) http.Error(w, "Session store error", http.StatusInternalServerError) return } //Enhancement: can be kept in memcache tok, err := channel.Create(c, nuuid) if err != nil { http.Error(w, "Couldn't create Channel", http.StatusInternalServerError) log.Errorf(c, "channel.Create: %v", err) return } session.Values["token"] = tok err1 := mainTemplate.Execute(w, map[string]string{ "token": tok, "uuid": nuuid, "subscribeKey": subscribeKey, "publishKey": publishKey, "secretKey": secretKey, }) if err1 != nil { log.Errorf(c, "mainTemplate: %v", err1) } }
// TestSuccessCodeAndInfoForComplexMessage2WithSecretAndEncryption sends out an // encypted and secret keyed complex message to the pubnub channel // The response is parsed and should match the 'sent' status. // _publishSuccessMessage and InitComplexMessage is defined in the common.go file func TestSuccessCodeAndInfoForComplexMessage2WithSecretAndEncryption(t *testing.T) { /*context, err := aetest.NewContext(nil) if err != nil { t.Fatal(err) } defer context.Close()*/ inst, err := aetest.NewInstance(&aetest.Options{"", true}) context := CreateContext(inst) if err != nil { t.Fatal(err) } defer inst.Close() uuid := "" w, req := InitAppEngineContext(t) pubnubInstance := messaging.New(context, uuid, w, req, PubKey, SubKey, SecKey, "enigma", false) //pubnubInstance := messaging.NewPubnub(PubKey, SubKey, "secret", "enigma", false, "", "", false) channel := "testChannel" customComplexMessage := InitComplexMessage() returnChannel := make(chan []byte) errorChannel := make(chan []byte) responseChannel := make(chan string) waitChannel := make(chan string) //go pubnubInstance.Publish(channel, customComplexMessage, returnChannel, errorChannel) go pubnubInstance.Publish(context, w, req, channel, customComplexMessage, returnChannel, errorChannel) go ParsePublishResponse(returnChannel, channel, publishSuccessMessage, "SuccessCodeAndInfoForComplexMessage2WithSecretAndEncryption", responseChannel) go ParseErrorResponse(errorChannel, responseChannel) go WaitForCompletion(responseChannel, waitChannel) ParseWaitResponse(waitChannel, t, "SuccessCodeAndInfoForComplexMessage2WithSecretAndEncryption") time.Sleep(2 * time.Second) }
func getUserState(w http.ResponseWriter, r *http.Request) { /*successChannel := make(chan []byte) errorChannel := make(chan []byte) c := createContext(r) pubInstance := messaging.New(c, "", w, r, publishKey, subscribeKey, secretKey, "", false) go pubInstance.ChannelGroupAddChannel(c, w, r, "cg-user-a-friends", "ch-user-a-present", successChannel, errorChannel) select { case response := <-successChannel: log.Infof(c, "success:", string(response)) case err := <-errorChannel: log.Infof(c, "success:", string(err)) } go pubInstance.ChannelGroupAddChannel(c, w, r, "cg-user-a-status-feed", "ch-user-a-present", successChannel, errorChannel) select { case response := <-successChannel: log.Infof(c, "1success:", string(response)) case err := <-errorChannel: log.Infof(c, "1success:", string(err)) }*/ q := r.URL.Query() ch := q.Get("ch") uuid := q.Get("uuid") //c := context.NewContext(r) c := createContext(r) pubInstance := messaging.New(c, uuid, w, r, publishKey, subscribeKey, secretKey, "", false) errorChannel := make(chan []byte) successChannel := make(chan []byte) go pubInstance.GetUserState(c, w, r, ch, successChannel, errorChannel) handleResult(c, w, r, uuid, successChannel, errorChannel, messaging.GetNonSubscribeTimeout(), "Get User State") }
// DetailedHistoryFor10Messages is a common method used by both TestDetailedHistoryFor10EncryptedMessages // and TestDetailedHistoryFor10Messages to publish's 10 messages to a pubnub channel, and after that // call the history method of the messaging package to fetch last 10 messages with time parameters // between which the messages were sent. These received message is compared to the messages sent and // if all match test is successful. func DetailedHistoryParamsFor10Messages(t *testing.T, cipherKey string, secretKey string, testName string) { numberOfMessages := 5 /*context, err := aetest.NewContext(nil) if err != nil { t.Fatal(err) } defer context.Close()*/ //context := CreateContext() inst, err := aetest.NewInstance(&aetest.Options{"", true}) context := CreateContext(inst) if err != nil { t.Fatal(err) } defer inst.Close() uuid := "" w, req := InitAppEngineContext(t) //pubnubInstance := messaging.NewPubnub(PubKey, SubKey, SecKey, cipherKey, false, "") pubnubInstance := messaging.New(context, uuid, w, req, PubKey, SubKey, SecKey, "", false) message := "Test Message " r := GenRandom() channel := fmt.Sprintf("testChannel_dh_%d", r.Intn(20)) startTime := GetServerTime(context, w, req, pubnubInstance, t, testName) startMessagesFrom := 0 //messagesSent := PublishMessages(pubnubInstance, channel, t, startMessagesFrom, numberOfMessages, message) messagesSent := PublishMessages(context, w, req, pubnubInstance, channel, t, startMessagesFrom, numberOfMessages, message) midTime := GetServerTime(context, w, req, pubnubInstance, t, testName) startMessagesFrom = 5 //messagesSent2 := PublishMessages(pubnubInstance, channel, t, startMessagesFrom, numberOfMessages, message) messagesSent2 := PublishMessages(context, w, req, pubnubInstance, channel, t, startMessagesFrom, numberOfMessages, message) endTime := GetServerTime(context, w, req, pubnubInstance, t, testName) startMessagesFrom = 0 if messagesSent { returnHistoryChannel := make(chan []byte) responseChannel := make(chan string) errorChannel := make(chan []byte) waitChannel := make(chan string) //go pubnubInstance.History(channel, numberOfMessages, startTime, midTime, false, returnHistoryChannel, errorChannel) go pubnubInstance.History(context, w, req, channel, numberOfMessages, startTime, midTime, false, returnHistoryChannel, errorChannel) go ParseHistoryResponseForMultipleMessages(returnHistoryChannel, channel, message, testName, startMessagesFrom, numberOfMessages, cipherKey, responseChannel) go ParseErrorResponse(errorChannel, responseChannel) go WaitForCompletion(responseChannel, waitChannel) ParseWaitResponse(waitChannel, t, testName) } else { t.Error("Test '" + testName + "': failed.") } startMessagesFrom = 5 if messagesSent2 { returnHistoryChannel2 := make(chan []byte) errorChannel2 := make(chan []byte) responseChannel2 := make(chan string) waitChannel2 := make(chan string) //go pubnubInstance.History(channel, numberOfMessages, midTime, endTime, false, returnHistoryChannel2, errorChannel2) go pubnubInstance.History(context, w, req, channel, numberOfMessages, midTime, endTime, false, returnHistoryChannel2, errorChannel2) go ParseHistoryResponseForMultipleMessages(returnHistoryChannel2, channel, message, testName, startMessagesFrom, numberOfMessages, cipherKey, responseChannel2) go ParseErrorResponse(errorChannel2, responseChannel2) go WaitForCompletion(responseChannel2, waitChannel2) ParseWaitResponse(waitChannel2, t, testName) } else { t.Error("Test '" + testName + "': failed.") } }