// Creates new transaction // Ex: var t = user.Do("GET", "/") func (t JSTransaction) Do(call otto.FunctionCall) otto.Value { if len(call.ArgumentList) != 2 { panic(errors.New("Do function takes exactly 2 parameters.")) } verb, err := call.Argument(0).ToString() utils.UnlessNilThenPanic(err) path, err := call.Argument(1).ToString() utils.UnlessNilThenPanic(err) t.transaction = &Transaction{ conquest: t.jsconquest.conquest, Verb: verb, Path: path, Headers: map[string]interface{}{}, Cookies: map[string]interface{}{}, ResConditions: map[string]interface{}{}, Body: map[string]interface{}{}, } if t.ctx.Transactions == nil { t.ctx.Transactions = []*Transaction{} } t.Response.transaction = t.transaction t.ctx.Transactions = append(t.ctx.Transactions, t.transaction) return toOttoValueOrPanic(t.jsconquest.vm, t) }
// conquest.prototype.Cookies // Sets total user count and calls user defined functions with JSTransactionCtx // Ex: conquest.Users(100, function(user){}) func (c JSConquest) Users(call otto.FunctionCall) otto.Value { if len(call.ArgumentList) != 2 { panic(errors.New("conquest.Users method takes exactly 2 arguments.")) } uc, err := call.Argument(0).ToInteger() utils.UnlessNilThenPanic(err) if uc <= 0 { panic(errors.New("Total users can not be equal zero or lesser.")) } c.conquest.TotalUsers = uint64(uc) fn := call.Argument(1) if !fn.IsFunction() { panic(errors.New("Users function argument 2 must be a function.")) } ctx := NewJSTransactionCtx(&c) ctxObj := toOttoValueOrPanic(c.vm, *ctx) _, err = fn.Call(fn, ctxObj) utils.UnlessNilThenPanic(err) return toOttoValueOrPanic(c.vm, c) }
// conquest.prototype.Duration // Sets the duration of tests // Ex: // conquest.Duration("10m") func (c JSConquest) Duration(call otto.FunctionCall) otto.Value { durationStr, err := call.Argument(0).ToString() utils.UnlessNilThenPanic(err) duration, err := time.ParseDuration(durationStr) utils.UnlessNilThenPanic(err) c.conquest.Duration = duration return toOttoValueOrPanic(c.vm, c) }
// conquest.prototype.Host(host) // Sets Host info ( and header ) // Ex: conquest.Host("mydomain.local:3434"); func (c JSConquest) Host(call otto.FunctionCall) otto.Value { host_str, err := call.Argument(0).ToString() utils.UnlessNilThenPanic(err) hostUrl, err := url.Parse(host_str) utils.UnlessNilThenPanic(err) c.conquest.Host = hostUrl.Host c.conquest.scheme = hostUrl.Scheme return toOttoValueOrPanic(c.vm, c) }
// Inserts a map as like "Contains":[substr] into transactions response // conditions // Ex: t.Response.Contains("<h1>Fancy Header</h1>") func (r JSTransactionResponse) Contains(call otto.FunctionCall) otto.Value { substr, err := call.Argument(0).ToString() utils.UnlessNilThenPanic(err) r.transaction.ResConditions["Contains"] = substr return toOttoValueOrPanic(r.jsconquest.vm, r) }
// conquest.prototype.Dump // Prints configuration by javascript and panics // Useful for debugging // Ex: // conquest.Dump() func (c JSConquest) Dump(call otto.FunctionCall) otto.Value { jbyte, err := json.MarshalIndent(c.conquest, "", "\t") utils.UnlessNilThenPanic(err) panic(string(jbyte)) return otto.Value{} }
// Inserts a map as like "StatusCode":[code] into transactions response // conditions // Ex: t.Response.StatusCode(200) func (r JSTransactionResponse) StatusCode(call otto.FunctionCall) otto.Value { code, err := call.Argument(0).ToInteger() utils.UnlessNilThenPanic(err) r.transaction.ResConditions["StatusCode"] = code return toOttoValueOrPanic(r.jsconquest.vm, r) }
// Sets additional cookies and headers func setAdditionals(kind string, call *otto.FunctionCall, t *JSTransaction) otto.Value { t.unlessAllocatedThenPanic() if len(call.ArgumentList) != 2 { panic(errors.New("Set" + kind + " function takes exactly 2 arguments.")) } key, err := call.Argument(0).ToString() utils.UnlessNilThenPanic(err) var addVal interface{} val := call.Argument(1) if val.IsFunction() { fetcher := &JSFetch{ jsconquest: t.jsconquest, } jsfetcher := toOttoValueOrPanic(t.jsconquest.vm, *fetcher) retv, err := val.Call(val, jsfetcher) utils.UnlessNilThenPanic(err) retn, err := retv.Export() utils.UnlessNilThenPanic(err) addVal, err = mapToFetchNotation(retn.(map[string]interface{})) utils.UnlessNilThenPanic(err) goto ADD_TO_ADDITIONAL_MAP } addVal, err = val.ToString() utils.UnlessNilThenPanic(err) ADD_TO_ADDITIONAL_MAP: var hMap map[string]interface{} switch kind { case "Header": hMap = t.transaction.Headers case "Cookie": hMap = t.transaction.Cookies } hMap[key] = addVal return toOttoValueOrPanic(t.jsconquest.vm, *t) }
// conquest.prototype.Proto // Sets HTTP protocol // Ex: conquest.Proto("HTTP/1.1"); func (c JSConquest) Proto(call otto.FunctionCall) otto.Value { proto, err := call.Argument(0).ToString() utils.UnlessNilThenPanic(err) if proto != "HTTP/1.1" && proto != "HTTP/1.0" { panic("Only HTTP/1.1 and HTTP/1.0 protocols are available.") } c.conquest.Proto = proto return toOttoValueOrPanic(c.vm, c) }
// Inserts a map as like [name]:[expected] into kind map of // transactions response conditions. if conditions[kind] is not allocated, // allocates first. func expectedAdditionals(kind string, call *otto.FunctionCall, r *JSTransactionResponse) otto.Value { if len(call.ArgumentList) != 2 { panic(errors.New("Response." + kind + " function takes exactly 2 arguments.")) } name, err := call.Argument(0).ToString() utils.UnlessNilThenPanic(err) expected, err := call.Argument(1).ToString() utils.UnlessNilThenPanic(err) if _, exists := r.transaction.ResConditions[kind]; !exists { r.transaction.ResConditions[kind] = map[string]string{} } r.transaction.ResConditions[kind].(map[string]string)[name] = expected return toOttoValueOrPanic(r.jsconquest.vm, *r) }
// Adds or gets context from Conquest.Track // If wanted ctx type is Finally, function goes to last of Track and // uses it if its type is Finally, otherwise adds a new Finally type ctx // if wanted ctx type is Every/Cases/Then, function goes to last of Track // and adds a new ctx if the last ctx is not Finally, otherwise breaks the link // of it then links it to new ctx. // And finally, calls user-defined function with JSTransaction parameters in the // new ctx. func ctxResolve(ctxType uint8, jsctx *JSTransactionCtx, call *otto.FunctionCall) otto.Value { fn := call.Argument(0) if !fn.IsFunction() { panic(errors.New("Context functions argument 1 must be a function.")) } track := jsctx.jsconquest.conquest.Track var ctx *TransactionContext if track == nil || track.CtxType == CTX_FINALLY { ctx = &TransactionContext{ CtxType: ctxType, } if track != nil { ctx.Next = track } jsctx.jsconquest.conquest.Track = ctx goto CALL_UD_FN } for ; track.Next != nil && track.Next.CtxType != CTX_FINALLY; track = track.Next { } switch ctxType { case CTX_FINALLY: if track.Next != nil { ctx = track.Next break } ctx = &TransactionContext{ CtxType: CTX_FINALLY, } track.Next = ctx case CTX_EVERY: fallthrough case CTX_THEN: ctx = &TransactionContext{ CtxType: ctxType, } if track.Next != nil { ctx.Next = track.Next } track.Next = ctx } CALL_UD_FN: jstact := &JSTransaction{ jsconquest: jsctx.jsconquest, ctx: ctx, Response: JSTransactionResponse{ jsconquest: jsctx.jsconquest, }, } jstact_obj := toOttoValueOrPanic(jsctx.jsconquest.vm, *jstact) _, err := fn.Call(fn, jstact_obj) utils.UnlessNilThenPanic(err) return toOttoValueOrPanic(jsctx.jsconquest.vm, *jsctx) }
// Returns t as otto.Value or panics func toOttoValueOrPanic(vm *otto.Otto, t interface{}) otto.Value { obj, err := vm.ToValue(t) utils.UnlessNilThenPanic(err) return obj }