示例#1
0
func TestImportImportRequestResponsePairs_CanImportAMultiplePairs(t *testing.T) {
	RegisterTestingT(t)

	cache := cache.NewInMemoryCache()
	cfg := Configuration{Webserver: false}
	requestMatcher := matching.RequestMatcher{RequestCache: cache, Webserver: &cfg.Webserver}
	hv := Hoverfly{RequestCache: cache, Cfg: &cfg, RequestMatcher: requestMatcher}

	RegisterTestingT(t)

	originalPair1 := v1.RequestResponsePairView{
		Response: v1.ResponseDetailsView{
			Status:      200,
			Body:        "hello_world",
			EncodedBody: false,
			Headers:     map[string][]string{"Hoverfly": []string{"testing"}},
		},
		Request: v1.RequestDetailsView{
			Path:        StringToPointer("/"),
			Method:      StringToPointer("GET"),
			Destination: StringToPointer("/"),
			Scheme:      StringToPointer("scheme"),
			Query:       StringToPointer(""),
			Body:        StringToPointer(""),
			Headers:     map[string][]string{"Hoverfly": []string{"testing"}}}}

	originalPair2 := originalPair1
	originalPair2.Request.Path = StringToPointer("/new/path")

	originalPair3 := originalPair1
	originalPair3.Request.Path = StringToPointer("/newer/path")

	hv.ImportRequestResponsePairViews([]interfaces.RequestResponsePair{originalPair1, originalPair2, originalPair3})

	pairBytes, err := cache.Get([]byte("9b114df98da7f7e2afdc975883dab4f2"))
	Expect(err).To(BeNil())
	decodedPair1, err := models.NewRequestResponsePairFromBytes(pairBytes)
	Expect(err).To(BeNil())
	Expect(*decodedPair1).To(Equal(models.NewRequestResponsePairFromRequestResponsePairView(originalPair1)))

	pairBytes, err = cache.Get([]byte("9c03e4af1f30542ff079a712bddad602"))
	Expect(err).To(BeNil())
	decodedPair2, err := models.NewRequestResponsePairFromBytes(pairBytes)
	Expect(err).To(BeNil())
	Expect(*decodedPair2).To(Equal(models.NewRequestResponsePairFromRequestResponsePairView(originalPair2)))

	pairBytes, err = cache.Get([]byte("fd099332afee48101edb7441b098cd4a"))
	Expect(err).To(BeNil())
	decodedPair3, err := models.NewRequestResponsePairFromBytes(pairBytes)
	Expect(err).To(BeNil())
	Expect(*decodedPair3).To(Equal(models.NewRequestResponsePairFromRequestResponsePairView(originalPair3)))
}
示例#2
0
// TestRequestBodyCaptured tests whether request body is recorded
func TestRequestBodyCaptured(t *testing.T) {
	RegisterTestingT(t)

	server, dbClient := testTools(200, `{'message': 'here'}`)
	defer server.Close()

	requestBody := []byte("fizz=buzz")

	body := ioutil.NopCloser(bytes.NewBuffer(requestBody))

	req, err := http.NewRequest("POST", "http://capture_body.com", body)
	Expect(err).To(BeNil())

	_, err = dbClient.captureRequest(req)
	Expect(err).To(BeNil())

	fp := matching.GetRequestFingerprint(req, requestBody, false)

	pairBytes, err := dbClient.RequestCache.Get([]byte(fp))
	Expect(err).To(BeNil())

	pair, err := models.NewRequestResponsePairFromBytes(pairBytes)
	Expect(err).To(BeNil())
	Expect(pair.Request.Body).To(Equal("fizz=buzz"))
}
示例#3
0
func TestDecodeRandomBytes(t *testing.T) {
	RegisterTestingT(t)

	bytes := []byte("some random stuff here")
	_, err := models.NewRequestResponsePairFromBytes(bytes)
	Expect(err).ToNot(BeNil())
}
示例#4
0
func rebuildHashes(db cache.Cache, webserver bool) {
	log.Info("Checking if keys in cache need rehashing")

	entries, err := db.GetAllEntries()
	if err != nil {
		log.Fatal("Unable to read from BoltDB cache")
	}

	for key, bytes := range entries {
		pair, err := models.NewRequestResponsePairFromBytes(bytes)
		if err != nil {
			log.WithFields(log.Fields{
				"error": err.Error(),
				"value": string(bytes),
				"key":   key,
			}).Error("Failed to decode payload")
		}
		var newKey string
		if webserver {
			newKey = pair.IdWithoutHost()
		} else {
			newKey = pair.Id()
		}

		if key != newKey {
			db.Delete([]byte(key))
			db.Set([]byte(newKey), bytes)
		}
	}
}
示例#5
0
func (hf Hoverfly) GetRecords() ([]v1.RequestResponsePairView, error) {
	records, err := hf.RequestCache.GetAllEntries()
	if err != nil {
		return nil, err
	}

	var pairViews []v1.RequestResponsePairView

	for _, v := range records {
		if pair, err := models.NewRequestResponsePairFromBytes(v); err == nil {
			pairView := pair.ConvertToV1RequestResponsePairView()
			pairViews = append(pairViews, *pairView)
		} else {
			log.Error(err)
			return nil, err
		}
	}

	for _, v := range hf.RequestMatcher.TemplateStore {
		pairView := v.ConvertToV1RequestResponsePairView()
		pairViews = append(pairViews, pairView)
	}

	return pairViews, nil

}
示例#6
0
func TestGetMultipleRecords(t *testing.T) {
	RegisterTestingT(t)

	server, dbClient := testTools(201, `{'message': 'here'}`)
	defer server.Close()
	defer dbClient.RequestCache.DeleteData()

	// inserting some payloads
	for i := 0; i < 5; i++ {
		req, err := http.NewRequest("GET", fmt.Sprintf("http://example.com/q=%d", i), nil)
		Expect(err).To(BeNil())
		dbClient.captureRequest(req)
	}

	// getting requests
	values, err := dbClient.RequestCache.GetAllValues()
	Expect(err).To(BeNil())

	for _, value := range values {
		if pair, err := models.NewRequestResponsePairFromBytes(value); err == nil {
			Expect(pair.Request.Method).To(Equal("GET"))
			Expect(pair.Response.Status).To(Equal(201))
		} else {
			t.Error(err)
		}
	}
}
示例#7
0
func TestRequestResponsePairEncodeEmpty(t *testing.T) {
	RegisterTestingT(t)

	pair := models.RequestResponsePair{}

	pairBytes, err := pair.Encode()
	Expect(err).To(BeNil())

	_, err = models.NewRequestResponsePairFromBytes(pairBytes)
	Expect(err).To(BeNil())
}
示例#8
0
func TestImportRequestResponsePairs_CanImportASinglePair(t *testing.T) {
	RegisterTestingT(t)

	cache := cache.NewInMemoryCache()
	cfg := Configuration{Webserver: false}
	requestMatcher := matching.RequestMatcher{RequestCache: cache, Webserver: &cfg.Webserver}
	hv := Hoverfly{RequestCache: cache, Cfg: &cfg, RequestMatcher: requestMatcher}

	RegisterTestingT(t)

	originalPair := v1.RequestResponsePairView{
		Response: v1.ResponseDetailsView{
			Status:      200,
			Body:        "hello_world",
			EncodedBody: false,
			Headers:     map[string][]string{"Content-Type": []string{"text/plain"}}},
		Request: v1.RequestDetailsView{
			Path:        StringToPointer("/"),
			Method:      StringToPointer("GET"),
			Destination: StringToPointer("/"),
			Scheme:      StringToPointer("scheme"),
			Query:       StringToPointer(""),
			Body:        StringToPointer(""),
			Headers:     map[string][]string{"Hoverfly": []string{"testing"}}}}

	hv.ImportRequestResponsePairViews([]interfaces.RequestResponsePair{originalPair})
	value, _ := cache.Get([]byte("9b114df98da7f7e2afdc975883dab4f2"))
	decodedPair, _ := models.NewRequestResponsePairFromBytes(value)
	Expect(*decodedPair).To(Equal(models.RequestResponsePair{
		Response: models.ResponseDetails{
			Status:  200,
			Body:    "hello_world",
			Headers: map[string][]string{"Content-Type": []string{"text/plain"}},
		},
		Request: models.RequestDetails{
			Path:        "/",
			Method:      "GET",
			Destination: "/",
			Scheme:      "scheme",
			Query:       "", Body: "",
			Headers: map[string][]string{
				"Content-Type": []string{"text/plain; charset=utf-8"},
				"Hoverfly":     []string{"testing"},
			},
		},
	}))
}
示例#9
0
func TestRequestResponsePairEncodeDecode(t *testing.T) {
	RegisterTestingT(t)

	resp := models.ResponseDetails{
		Status: 200,
		Body:   "body here",
	}

	pair := models.RequestResponsePair{Response: resp}

	pairBytes, err := pair.Encode()
	Expect(err).To(BeNil())

	pairFromBytes, err := models.NewRequestResponsePairFromBytes(pairBytes)
	Expect(err).To(BeNil())
	Expect(pairFromBytes.Response.Body).To(Equal(resp.Body))
	Expect(pairFromBytes.Response.Status).To(Equal(resp.Status))
}
示例#10
0
func TestImportImportRequestResponsePairs_CanImportASingleBase64EncodedPair(t *testing.T) {
	cache := cache.NewInMemoryCache()
	cfg := Configuration{Webserver: false}
	requestMatcher := matching.RequestMatcher{RequestCache: cache, Webserver: &cfg.Webserver}
	hv := Hoverfly{RequestCache: cache, Cfg: &cfg, RequestMatcher: requestMatcher}

	RegisterTestingT(t)

	encodedPair := views.RequestResponsePairView{
		Response: views.ResponseDetailsView{
			Status:      200,
			Body:        base64String("hello_world"),
			EncodedBody: true,
			Headers:     map[string][]string{"Content-Encoding": []string{"gzip"}}},
		Request: views.RequestDetailsView{
			Path:        "/",
			Method:      "GET",
			Destination: "/",
			Scheme:      "scheme",
			Query:       "", Body: "",
			Headers: map[string][]string{"Hoverfly": []string{"testing"}}}}

	hv.ImportRequestResponsePairViews([]views.RequestResponsePairView{encodedPair})

	value, err := cache.Get([]byte("9b114df98da7f7e2afdc975883dab4f2"))
	Expect(err).To(BeNil())

	decodedPair, err := models.NewRequestResponsePairFromBytes(value)
	Expect(err).To(BeNil())

	Expect(decodedPair).ToNot(Equal(models.RequestResponsePair{
		Response: models.ResponseDetails{
			Status:  200,
			Body:    "hello_world",
			Headers: map[string][]string{"Content-Encoding": []string{"gzip"}}},
		Request: models.RequestDetails{
			Path:        "/",
			Method:      "GET",
			Destination: "/",
			Scheme:      "scheme",
			Query:       "", Body: "",
			Headers: map[string][]string{"Hoverfly": []string{"testing"}}}}))
}
示例#11
0
// AllRecordsHandler returns JSON content type http response
func (d *Hoverfly) AllRecordsHandler(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	records, err := d.RequestCache.GetAllValues()

	if err != nil {
		log.WithFields(log.Fields{
			"Error": err.Error(),
		}).Error("Failed to get data from cache!")

		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(500) // can't process this entity
		return
	}

	var pairViews []views.RequestResponsePairView

	for _, v := range records {
		if pair, err := models.NewRequestResponsePairFromBytes(v); err == nil {
			pairView := pair.ConvertToRequestResponsePairView()
			pairViews = append(pairViews, *pairView)
		} else {
			log.Error(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}

	w.Header().Set("Content-Type", "application/json")

	var response views.RequestResponsePairPayload
	response.Data = pairViews
	b, err := json.Marshal(response)

	if err != nil {
		log.Error(err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	w.Write(b)
	return
}
示例#12
0
func (hf Hoverfly) GetSimulation() (v2.SimulationView, error) {
	records, err := hf.RequestCache.GetAllEntries()
	if err != nil {
		return v2.SimulationView{}, err
	}

	pairViews := make([]v2.RequestResponsePairView, 0)

	for _, v := range records {
		if pair, err := models.NewRequestResponsePairFromBytes(v); err == nil {
			pairView := pair.ConvertToRequestResponsePairView()
			pairViews = append(pairViews, pairView)
		} else {
			log.Error(err)
			return v2.SimulationView{}, err
		}
	}

	for _, v := range hf.RequestMatcher.TemplateStore {
		pairViews = append(pairViews, v.ConvertToRequestResponsePairView())
	}

	responseDelays := hf.ResponseDelays.ConvertToResponseDelayPayloadView()

	return v2.SimulationView{
		MetaView: v2.MetaView{
			HoverflyVersion: "v0.9.2",
			SchemaVersion:   "v1",
			TimeExported:    time.Now().Format(time.RFC3339),
		},
		DataView: v2.DataView{
			RequestResponsePairs: pairViews,
			GlobalActions: v2.GlobalActionsView{
				Delays: responseDelays.Data,
			},
		},
	}, nil
}
示例#13
0
// getResponse returns stored response from cache
func (this *RequestMatcher) GetResponse(req *models.RequestDetails) (*models.ResponseDetails, *MatchingError) {

	var key string

	if *this.Webserver {
		key = req.HashWithoutHost()
	} else {
		key = req.Hash()
	}

	pairBytes, err := this.RequestCache.Get([]byte(key))

	if err != nil {
		log.WithFields(log.Fields{
			"key":         key,
			"error":       err.Error(),
			"query":       req.Query,
			"path":        req.Path,
			"destination": req.Destination,
			"method":      req.Method,
		}).Warn("Failed to retrieve response from cache")

		response, err := this.TemplateStore.GetResponse(*req, *this.Webserver)
		if err != nil {
			log.WithFields(log.Fields{
				"key":         key,
				"error":       err.Error(),
				"query":       req.Query,
				"path":        req.Path,
				"destination": req.Destination,
				"method":      req.Method,
			}).Warn("Failed to find matching request template from template store")

			return nil, &MatchingError{
				StatusCode:  412,
				Description: "Could not find recorded request, please record it first!",
			}
		}
		log.WithFields(log.Fields{
			"key":         key,
			"query":       req.Query,
			"path":        req.Path,
			"destination": req.Destination,
			"method":      req.Method,
		}).Info("Found template matching request from template store")
		return response, nil
	}

	// getting cache response
	pair, err := models.NewRequestResponsePairFromBytes(pairBytes)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
			"value": string(pairBytes),
			"key":   key,
		}).Error("Failed to decode payload")
		return nil, &MatchingError{
			StatusCode:  500,
			Description: "Failed to decode payload",
		}
	}

	log.WithFields(log.Fields{
		"key":         key,
		"path":        req.Path,
		"rawQuery":    req.Query,
		"method":      req.Method,
		"destination": req.Destination,
		"status":      pair.Response.Status,
	}).Info("Payload found from cache")

	return &pair.Response, nil
}
示例#14
0
func TestImportImportRequestResponsePairs_CanImportARequestResponsePair_AndRequestTemplateResponsePair(t *testing.T) {
	RegisterTestingT(t)

	cache := cache.NewInMemoryCache()
	cfg := Configuration{Webserver: false}
	requestMatcher := matching.RequestMatcher{RequestCache: cache, Webserver: &cfg.Webserver}
	hv := Hoverfly{RequestCache: cache, Cfg: &cfg, RequestMatcher: requestMatcher}

	RegisterTestingT(t)

	requestTemplate := v1.RequestDetailsView{
		RequestType: StringToPointer("template"),
		Method:      StringToPointer("GET"),
	}

	requestView := v1.RequestDetailsView{
		Method:      StringToPointer("GET"),
		Path:        StringToPointer("/"),
		Destination: StringToPointer("test.com"),
		Scheme:      StringToPointer("http"),
	}

	responseView := v1.ResponseDetailsView{
		Status:      200,
		Body:        "hello_world",
		EncodedBody: false,
		Headers:     map[string][]string{"Hoverfly": []string{"testing"}},
	}

	templatePair := v1.RequestResponsePairView{
		Request:  requestTemplate,
		Response: responseView,
	}

	ordinaryPair := v1.RequestResponsePairView{
		Request:  requestView,
		Response: responseView,
	}

	hv.ImportRequestResponsePairViews([]interfaces.RequestResponsePair{templatePair, ordinaryPair})

	cacheCount, err := hv.RequestCache.RecordsCount()
	Expect(cacheCount).To(Equal(1))
	Expect(err).To(BeNil())

	Expect(len(hv.RequestMatcher.TemplateStore)).To(Equal(1))

	request := models.NewRequestDetailsFromRequest(requestTemplate)
	response := models.NewResponseDetailsFromResponse(responseView)

	pairBytes, err := hv.RequestCache.Get([]byte("76cf08e38439f083de2658b0971df9bf"))
	Expect(err).To(BeNil())

	savedPair, err := models.NewRequestResponsePairFromBytes(pairBytes)
	Expect(err).To(BeNil())

	Expect(savedPair.Response).To(Equal(response))

	responseFromCache, err := hv.RequestMatcher.TemplateStore.GetResponse(request, false)
	Expect(err).To(BeNil())
	Expect(*responseFromCache).To(Equal(response))

}