/*
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 adapter

import (
	"fmt"
	"os"
	"testing"

	"github.com/apid/istioApigeeAdapter/adapter/config"
	"github.com/apid/istioApigeeAdapter/mock"
	"istio.io/mixer/pkg/adapter"
)

var mockServer *mock.MockServer
var mockEnv adapter.Env

func TestMain(m *testing.M) {
	var err error
	mockEnv = mock.NewMockEnvironment()
	mockServer, err = mock.StartMockServer(0)
	if err != nil {
		panic(err.Error())
	}

	result := m.Run()
	mockServer.Stop()
	os.Exit(result)
}

func TestMissingOrg(t *testing.T) {
	cfg := &config.VerifyKeyParams{
		Environment: "test",
	}
	builder := newKeyCheckBuilder()
	ce := builder.ValidateConfig(cfg)
	if ce == nil {
		t.Fatal("Config should have returned an error")
	}
	fmt.Printf("Errors: %s\n", ce.Multi)
}

func TestMissingEnv(t *testing.T) {
	cfg := &config.VerifyKeyParams{
		Organization: "test",
	}
	builder := newKeyCheckBuilder()
	ce := builder.ValidateConfig(cfg)
	if ce == nil {
		t.Fatal("Config should have returned an error")
	}
	fmt.Printf("Errors: %s\n", ce.Multi)
}

func TestInvalidURL(t *testing.T) {
	cfg := &config.VerifyKeyParams{
		Organization:    "foo",
		Environment:     "test",
		VerificationURL: ":",
	}
	builder := newKeyCheckBuilder()
	ce := builder.ValidateConfig(cfg)
	if ce == nil {
		t.Fatal("Config should have returned an error")
	}
	fmt.Printf("Errors: %s\n", ce.Multi)
}

func TestValidKey(t *testing.T) {
	cfg := &config.VerifyKeyParams{
		Organization:    "foo",
		Environment:     "test",
		VerificationURL: "http://" + mockServer.Address(),
	}

	builder := newKeyCheckBuilder()
	ce := builder.ValidateConfig(cfg)
	if ce != nil {
		t.Fatalf("Error validating config: %s", ce)
	}

	aspect, err := builder.NewListsAspect(mockEnv, cfg)
	if err != nil {
		t.Fatalf("Error creating aspect: %s", err)
	}
	defer aspect.Close()

	result, err := aspect.CheckList(mock.ValidAPIKey1)
	if err != nil {
		t.Fatalf("Error on list check: %s", err)
	}
	if !result {
		t.Fatal("List check returned false")
	}
}

func TestInvalidKey(t *testing.T) {
	cfg := &config.VerifyKeyParams{
		Organization:    "foo",
		Environment:     "test",
		VerificationURL: "http://" + mockServer.Address(),
	}

	builder := newKeyCheckBuilder()
	ce := builder.ValidateConfig(cfg)
	if ce != nil {
		t.Fatalf("Error validating config: %s", ce)
	}

	aspect, err := builder.NewListsAspect(mockEnv, cfg)
	if err != nil {
		t.Fatalf("Error creating aspect: %s", err)
	}
	defer aspect.Close()

	result, err := aspect.CheckList("99999")
	if err != nil {
		t.Fatalf("Error on list check: %s", err)
	}
	if result {
		t.Fatal("List check returned true and should have failed")
	}
}
