// Copyright 2017 Istio Authors
//
// 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 compiled

import (
	"testing"

	"istio.io/istio/mixer/pkg/config/descriptor"
	"istio.io/istio/mixer/pkg/il/testing"
)

func TestCompiledExpressions(t *testing.T) {
	for _, test := range ilt.TestData {
		if test.E == "" {
			// Skip tests that don't have expression.
			continue
		}

		if test.Fns != nil {
			// Skip tests that have extern functions defined. We cannot inject extern functions into the evaluator.
			// Compiler tests actually also do evaluation.
			continue
		}

		name := "Compiled/" + test.TestName()
		t.Run(name, func(tt *testing.T) {
			finder := descriptor.NewFinder(test.Conf())

			builder := NewBuilder(finder)
			compiled, err := builder.Compile(test.E)
			if test.CompileErr != "" {
				if err == nil {
					tt.Fatalf("expected compile error not found: '%v'", test.CompileErr)
					return
				}
				if err.Error() != test.CompileErr {
					tt.Fatalf("compile error mismatch: '%v' != '%v'", err, test.CompileErr)
				}
				return
			} else if err != nil {
				tt.Fatalf("unexpected compile error: '%v'", err)
				return
			}

			bag := ilt.NewFakeBag(test.I)
			r, err := compiled.Evaluate(bag)
			if e := test.CheckEvaluationResult(r, err); e != nil {
				tt.Fatalf(e.Error())
				return
			}

			// Depending on the type, try testing specialized methods as well.
			switch test.R.(type) {
			case bool:
				actual, err := compiled.EvaluateBoolean(bag)
				if e := test.CheckEvaluationResult(actual, err); e != nil {
					tt.Fatalf(e.Error())
					return
				}
			}
		})
	}
}
