package httpapi

import (
	"net/http/httptest"
	"testing"
)

// Сравнение меток слабое, звёздочка совпадает с любой существующей меткой, а
// мусор условия не выполняет — и это не отказ: клиент, приславший кривой
// заголовок, получает данные, а не `400`.
func TestУсловиеЗапроса(t *testing.T) {
	t.Parallel()

	const tag = `W/"metrics.gen-7"`
	cases := []struct {
		name   string
		header []string
		tag    string
		want   bool
	}{
		{"заголовка нет", nil, tag, false},
		{"пустая строка", []string{""}, tag, false},
		{"та же метка", []string{tag}, tag, true},
		{"та же метка без W/", []string{`"metrics.gen-7"`}, tag, true},
		{"чужая метка", []string{`W/"metrics.gen-8"`}, tag, false},
		{"метка другого ресурса", []string{`W/"points.gen-7"`}, tag, false},
		{"список, метка вторая", []string{`W/"metrics.gen-1", W/"metrics.gen-7"`}, tag, true},
		{"две строки заголовка", []string{`W/"metrics.gen-1"`, `W/"metrics.gen-7"`}, tag, true},
		{"запятая внутри метки", []string{`W/"points.a,b-7"`}, `W/"points.a,b-7"`, true},
		{"метка без закрывающей кавычки", []string{`W/"metrics.gen-7`}, tag, false},
		{"звёздочка", []string{"*"}, tag, true},
		{"звёздочка без метки", []string{"*"}, "", false},
		{"мусор", []string{"metrics.gen-7"}, tag, false},
		{"мусор со звёздочкой внутри", []string{`"*"`}, tag, false},
		{"метки нет", []string{tag}, "", false},
	}
	for _, c := range cases {
		if got := notModified(c.header, c.tag); got != c.want {
			t.Errorf("%s: %v, ждали %v", c.name, got, c.want)
		}
	}
}

// Пустая версия метки не даёт: подписать ответ нечем, и притворяться нельзя.
func TestМеткаИзВерсии(t *testing.T) {
	t.Parallel()

	if got := etag("metrics", ""); got != "" {
		t.Errorf("пустая версия дала метку %q", got)
	}
	if got := etag("metrics", "gen-7"); got != `W/"metrics.gen-7"` {
		t.Errorf("метка %q, ждали слабую с областью", got)
	}
	if etag("metrics", "gen-7") == etag("points", "gen-7") {
		t.Error("метки разных ресурсов совпали — 304 отдал бы чужие данные")
	}
}

// Подписать нечем — заголовка нет вовсе. Пустой `ETag:` синтаксически невалиден,
// и что с ним сделает посредник, не определено ничем.
func TestОтветБезВерсииНеНесётМетки(t *testing.T) {
	t.Parallel()

	rec := httptest.NewRecorder()
	setReadHeaders(rec, "")
	if _, ok := rec.Header()["Etag"]; ok {
		t.Errorf("ответ без версии несёт метку %q", rec.Header().Get("ETag"))
	}
	if got := rec.Header().Get("Cache-Control"); got != "private, no-cache" {
		t.Errorf("правило кеширования %q — оно не зависит от наличия метки", got)
	}
}
