blob: bebf2b5a95468a772433412c870aa3b027d7605a [file] [log] [blame]
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package mock
import (
"bytes"
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"io/ioutil"
"net/http"
"os"
"testing"
"time"
"github.com/SermoDigital/jose/jws"
"github.com/apid/istioApigeeAdapter/common"
)
var testMockServer *MockServer
func TestMain(m *testing.M) {
var err error
testMockServer, err = StartMockServer(0)
if err != nil {
panic(err.Error())
}
result := m.Run()
testMockServer.Stop()
os.Exit(result)
}
func TestServerSanity(t *testing.T) {
if mockKeyPEM == nil {
t.Fatal("Expected mock key to be generated")
}
if mockCertPEM == nil {
t.Fatal("Expected mock cert to be generated")
}
}
func TestPublicKey(t *testing.T) {
resp, err := http.Get(fmt.Sprintf("http://%s/publicKey", testMockServer.Address()))
if err != nil {
t.Fatalf("Network error: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
t.Fatalf("Got HTTP status code %d", resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf("Error reading body: %s", err)
}
pb, _ := pem.Decode(body)
if pb == nil {
t.Fatalf("Failed decoding public key body \"%s\"", string(body))
}
if pb.Type != "CERTIFICATE" {
t.Fatalf("Got back invalid PEM type %s", pb.Type)
}
cert, err := x509.ParseCertificate(pb.Bytes)
if err != nil {
t.Fatalf("Error decoding certificate: %s", err)
}
if cert.Subject.CommonName != "mockserver" {
t.Fatalf("Common name does not match \"mockserver\": \"%s\"", cert.Subject.CommonName)
}
}
func TestProducts(t *testing.T) {
resp, err := http.Get(fmt.Sprintf("http://%s/products", testMockServer.Address()))
if err != nil {
t.Fatalf("Network error: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
t.Fatalf("Got HTTP status code %d", resp.StatusCode)
}
if resp.Header.Get("content-type") != "application/json" {
t.Fatalf("Invalid content typs %s", resp.Header.Get("content-type"))
}
dec := json.NewDecoder(resp.Body)
var products []common.APIProduct
err = dec.Decode(&products)
if err != nil {
t.Fatalf("Error decoding response json: %s", err)
}
}
func TestAPIKeyWrongFormat(t *testing.T) {
req := common.VerifyAPIKeyRequest{}
requestBod, _ := json.Marshal(&req)
resp, err := http.DefaultClient.Post(
fmt.Sprintf("http://%s/verifyApiKey", testMockServer.Address()),
"text/plain",
bytes.NewBuffer(requestBod))
if err != nil {
t.Fatalf("Network error: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 404 {
t.Fatalf("Got HTTP status code %d -- expected 404", resp.StatusCode)
}
}
func TestAPIKeyNotJSON(t *testing.T) {
resp, err := http.DefaultClient.Post(
fmt.Sprintf("http://%s/verifyApiKey", testMockServer.Address()),
"application/json",
bytes.NewBuffer([]byte("Hello!")))
if err != nil {
t.Fatalf("Network error: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 500 {
t.Fatalf("Got HTTP status code %d -- expected 500", resp.StatusCode)
}
}
func TestAPIKeyNoKey(t *testing.T) {
req := common.VerifyAPIKeyRequest{}
requestBod, _ := json.Marshal(&req)
resp, err := http.DefaultClient.Post(
fmt.Sprintf("http://%s/verifyApiKey", testMockServer.Address()),
"application/json",
bytes.NewBuffer(requestBod))
if err != nil {
t.Fatalf("Network error: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 404 {
t.Fatalf("Got HTTP status code %d -- expected 404", resp.StatusCode)
}
}
func TestAPIKeyBadKey(t *testing.T) {
req := common.VerifyAPIKeyRequest{
Key: "foobar",
}
requestBod, _ := json.Marshal(&req)
resp, err := http.DefaultClient.Post(
fmt.Sprintf("http://%s/verifyApiKey", testMockServer.Address()),
"application/json",
bytes.NewBuffer(requestBod))
if err != nil {
t.Fatalf("Network error: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 404 {
t.Fatalf("Got HTTP status code %d -- expected 404", resp.StatusCode)
}
}
func TestAPIKeySuccess(t *testing.T) {
req := common.VerifyAPIKeyRequest{
Key: ValidAPIKey1,
}
requestBod, _ := json.Marshal(&req)
resp, err := http.DefaultClient.Post(
fmt.Sprintf("http://%s/verifyApiKey", testMockServer.Address()),
"application/json",
bytes.NewBuffer(requestBod))
if err != nil {
t.Fatalf("Network error: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
t.Fatalf("Got HTTP status code %d -- expected 200", resp.StatusCode)
}
var respBody common.VerifyAPIKeyResponse
dec := json.NewDecoder(resp.Body)
err = dec.Decode(&respBody)
if err != nil {
t.Fatalf("Error reading JSON response: %s", err)
}
_, err = jws.ParseJWT([]byte(respBody.Token))
if err != nil {
t.Fatalf("Error parsing JWT: %s", err)
}
}
func TestAxPublishBadJSON(t *testing.T) {
resp, err := sendAnalytics([]byte("NOTJSON"), "application/json",
ValidPublishKey, ValidPublishSecret)
if err != nil {
t.Fatalf("Network error sending request: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 500 {
t.Fatalf("Got status code %d and expected 500", resp.StatusCode)
}
}
func TestAxPublishNotJSON(t *testing.T) {
resp, err := sendAnalytics([]byte("{}"), "text/plain",
ValidPublishKey, ValidPublishSecret)
if err != nil {
t.Fatalf("Network error sending request: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
t.Fatalf("Got status code %d and expected 200", resp.StatusCode)
}
var respBody common.AnalyticsResponse
dec := json.NewDecoder(resp.Body)
err = dec.Decode(&respBody)
if err != nil {
t.Fatalf("Error reading JSON response: %s", err)
}
if respBody.Accepted != 0 {
t.Fatalf("%d records were accepted", respBody.Accepted)
}
if respBody.Rejected != 1 {
t.Fatalf("%d records were rejected", respBody.Rejected)
}
}
func TestAxPublishEmpty(t *testing.T) {
resp, err := sendAnalytics([]byte("{}"), "application/json",
ValidPublishKey, ValidPublishSecret)
if err != nil {
t.Fatalf("Network error sending request: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
t.Fatalf("Got status code %d and expected 200", resp.StatusCode)
}
var respBody common.AnalyticsResponse
dec := json.NewDecoder(resp.Body)
err = dec.Decode(&respBody)
if err != nil {
t.Fatalf("Error reading JSON response: %s", err)
}
if respBody.Accepted != 0 {
t.Fatalf("%d records were accepted", respBody.Accepted)
}
if respBody.Rejected != 0 {
t.Fatalf("%d records were rejected", respBody.Rejected)
}
}
func TestAxPublishWrongUser(t *testing.T) {
resp, err := sendAnalytics([]byte("{}"), "application/json",
"NOTVALID", ValidPublishSecret)
if err != nil {
t.Fatalf("Network error sending request: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 401 {
t.Fatalf("Got status code %d and expected 401", resp.StatusCode)
}
}
func TestAxPublishWrongPW(t *testing.T) {
resp, err := sendAnalytics([]byte("{}"), "application/json",
ValidPublishKey, "NOPE")
if err != nil {
t.Fatalf("Network error sending request: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 401 {
t.Fatalf("Got status code %d and expected 401", resp.StatusCode)
}
}
func TestAxPublishNoAuth(t *testing.T) {
resp, err := http.Post(
fmt.Sprintf("http://%s/axpublisher/organization/foo/environment/test", testMockServer.Address()),
"application/json", bytes.NewReader([]byte("{}")))
if err != nil {
t.Fatalf("Network error sending request: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 401 {
t.Fatalf("Got status code %d and expected 401", resp.StatusCode)
}
}
func TestAxPublishSuccess(t *testing.T) {
now := time.Now().UnixNano() / 1000
req := common.AnalyticsRequest{
Records: []common.AnalyticsRecord{
{
ClientReceivedStartTimestamp: now,
ClientReceivedEndTimestamp: now + 1,
ClientSentStartTimestamp: now + 10,
ClientSentEndTimestamp: now + 11,
RecordType: "APIAnalytics",
APIProxy: "helloworld",
RequestURI: "http://hello/world",
RequestPath: "/world",
RequestVerb: "GET",
ClientIP: "192.168.201.100",
UserAgent: "Testing",
APIProxyRevision: 1,
ResponseStatusCode: 200,
},
},
}
requestBod, err := json.Marshal(&req)
if err != nil {
t.Fatalf("Error making JSON: %s", err)
}
resp, err := sendAnalytics(requestBod, "application/json",
ValidPublishKey, ValidPublishSecret)
if err != nil {
t.Fatalf("Network error sending request: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
t.Fatalf("Got status code %d", resp.StatusCode)
}
var respBody common.AnalyticsResponse
dec := json.NewDecoder(resp.Body)
err = dec.Decode(&respBody)
if err != nil {
t.Fatalf("Error reading JSON response: %s", err)
}
if respBody.Accepted != 1 {
t.Fatalf("Only %d record accepted", respBody.Accepted)
}
if respBody.Rejected != 0 {
t.Fatalf("%d records were rejected", respBody.Rejected)
}
}
func sendAnalytics(body []byte, contentType, user, pw string) (*http.Response, error) {
req, err := http.NewRequest(
"POST",
fmt.Sprintf("http://%s/axpublisher/organization/foo/environment/test", testMockServer.Address()),
bytes.NewBuffer(body))
if err != nil {
return nil, err
}
req.Header.Set("content-type", contentType)
req.SetBasicAuth(user, pw)
return http.DefaultClient.Do(req)
}