Beispiel #1
0
// 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)
}
Beispiel #2
0
// 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)
}
Beispiel #3
0
// 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)
}
Beispiel #4
0
// 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)
}
Beispiel #5
0
// 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)
}
Beispiel #6
0
// 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{}
}
Beispiel #7
0
// 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)
}
Beispiel #8
0
// 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)
}
Beispiel #9
0
// 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)
}
Beispiel #10
0
// 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)
}
Beispiel #11
0
// 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)
}
Beispiel #12
0
// 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
}