/*
 *
 * Copyright 2017 gRPC 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 primitives_test

import (
	"context"
	"testing"
	"time"
)

func BenchmarkCancelContextErrNoErr(b *testing.B) {
	ctx, cancel := context.WithCancel(context.Background())
	for i := 0; i < b.N; i++ {
		if err := ctx.Err(); err != nil {
			b.Fatal("error")
		}
	}
	cancel()
}

func BenchmarkCancelContextErrGotErr(b *testing.B) {
	ctx, cancel := context.WithCancel(context.Background())
	cancel()
	for i := 0; i < b.N; i++ {
		if err := ctx.Err(); err == nil {
			b.Fatal("error")
		}
	}
}

func BenchmarkCancelContextChannelNoErr(b *testing.B) {
	ctx, cancel := context.WithCancel(context.Background())
	for i := 0; i < b.N; i++ {
		select {
		case <-ctx.Done():
			b.Fatal("error: ctx.Done():", ctx.Err())
		default:
		}
	}
	cancel()
}

func BenchmarkCancelContextChannelGotErr(b *testing.B) {
	ctx, cancel := context.WithCancel(context.Background())
	cancel()
	for i := 0; i < b.N; i++ {
		select {
		case <-ctx.Done():
			if err := ctx.Err(); err == nil {
				b.Fatal("error")
			}
		default:
			b.Fatal("error: !ctx.Done()")
		}
	}
}

func BenchmarkTimerContextErrNoErr(b *testing.B) {
	ctx, cancel := context.WithTimeout(context.Background(), 24*time.Hour)
	for i := 0; i < b.N; i++ {
		if err := ctx.Err(); err != nil {
			b.Fatal("error")
		}
	}
	cancel()
}

func BenchmarkTimerContextErrGotErr(b *testing.B) {
	ctx, cancel := context.WithTimeout(context.Background(), time.Microsecond)
	cancel()
	for i := 0; i < b.N; i++ {
		if err := ctx.Err(); err == nil {
			b.Fatal("error")
		}
	}
}

func BenchmarkTimerContextChannelNoErr(b *testing.B) {
	ctx, cancel := context.WithTimeout(context.Background(), 24*time.Hour)
	for i := 0; i < b.N; i++ {
		select {
		case <-ctx.Done():
			b.Fatal("error: ctx.Done():", ctx.Err())
		default:
		}
	}
	cancel()
}

func BenchmarkTimerContextChannelGotErr(b *testing.B) {
	ctx, cancel := context.WithTimeout(context.Background(), time.Microsecond)
	cancel()
	for i := 0; i < b.N; i++ {
		select {
		case <-ctx.Done():
			if err := ctx.Err(); err == nil {
				b.Fatal("error")
			}
		default:
			b.Fatal("error: !ctx.Done()")
		}
	}
}
