<commit_before>// Copyright 2020 Google LLC
//
// 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 redirect_test

import (
	"context"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"path/filepath"
	"testing"

	"github.com/google/exposure-notifications-verification-server/internal/project"
	"github.com/google/exposure-notifications-verification-server/internal/routes"
	"github.com/google/exposure-notifications-verification-server/pkg/cache"
	"github.com/google/exposure-notifications-verification-server/pkg/config"
	"github.com/google/exposure-notifications-verification-server/pkg/database"
)

func TestIndex(t *testing.T) {
	t.Parallel()

	ctx := context.Background()

	// Create cacher.
	cacher, err := cache.NewInMemory(nil)
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() {
		if err := cacher.Close(); err != nil {
			t.Fatal(err)
		}
	})

	// Create database.
	testDatabaseInstance := database.MustTestInstance()
	t.Cleanup(func() {
		if err := testDatabaseInstance.Close(); err != nil {
			t.Fatal(err)
		}
	})
	db, _ := testDatabaseInstance.NewDatabase(t, cacher)

	// Create config.
	cfg := &config.RedirectConfig{
		AssetsPath: filepath.Join(project.Root(), "cmd", "enx-redirect", "assets"),
		DevMode:    true,
		HostnameConfig: map[string]string{
			"bad":  "nope",
			"okay": "bb",
		},
	}

	// Set realm to resolve.
	realm1, err := db.FindRealm(1)
	if err != nil {
		t.Fatal(err)
	}
	realm1.RegionCode = "aa"
	if err := db.SaveRealm(realm1, database.SystemTest); err != nil {
		t.Fatal(err)
	}

	// Create another realm with apps.
	realm2 := database.NewRealmWithDefaults("okay")
	realm2.RegionCode = "bb"
	if err := db.SaveRealm(realm2, database.SystemTest); err != nil {
		t.Fatal(err)
	}

	// Create iOS app
	iosApp := &database.MobileApp{
		Name:    "app1",
		RealmID: realm2.ID,
		URL:     "https://app1.example.com/",
		OS:      database.OSTypeIOS,
		AppID:   "com.example.app1",
	}
	if err := db.SaveMobileApp(iosApp, database.SystemTest); err != nil {
		t.Fatal(err)
	}

	// Create Android app
	app2 := &database.MobileApp{
		Name:    "app2",
		RealmID: realm2.ID,
		URL:     "https://app2.example.com/",
		OS:      database.OSTypeAndroid,
		AppID:   "com.example.app2",
		SHA:     "AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA",
	}
	if err := db.SaveMobileApp(app2, database.SystemTest); err != nil {
		t.Fatal(err)
	}

	// Build routes.
	mux, err := routes.ENXRedirect(ctx, cfg, db, cacher)
	if err != nil {
		t.Fatal(err)
	}

	// Start server.
	srv := httptest.NewServer(mux)
	t.Cleanup(func() {
		srv.Close()
	})
	client := srv.Client()

	// Don't follow redirects.
	client.CheckRedirect = func(r *http.Request, via []*http.Request) error {
		return http.ErrUseLastResponse
	}

	// No matching region returns a 404
	t.Run("no_matching_region", func(t *testing.T) {
		t.Parallel()

		req, err := http.NewRequest("GET", srv.URL, nil)
		req.Host = "not-real"
		if err != nil {
			t.Fatal(err)
		}
		resp, err := client.Do(req)
		if err != nil {
			t.Fatal(err)
		}
		defer resp.Body.Close()

		if got, want := resp.StatusCode, 404; got != want {
			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {<commit_msg>Show bad path 404s (#1424)<commit_after>// Copyright 2020 Google LLC
//
// 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 redirect_test

import (
	"context"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"path/filepath"
	"testing"

	"github.com/google/exposure-notifications-verification-server/internal/project"
	"github.com/google/exposure-notifications-verification-server/internal/routes"
	"github.com/google/exposure-notifications-verification-server/pkg/cache"
	"github.com/google/exposure-notifications-verification-server/pkg/config"
	"github.com/google/exposure-notifications-verification-server/pkg/database"
)

func TestIndex(t *testing.T) {
	t.Parallel()

	ctx := context.Background()

	// Create cacher.
	cacher, err := cache.NewInMemory(nil)
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() {
		if err := cacher.Close(); err != nil {
			t.Fatal(err)
		}
	})

	// Create database.
	testDatabaseInstance := database.MustTestInstance()
	t.Cleanup(func() {
		if err := testDatabaseInstance.Close(); err != nil {
			t.Fatal(err)
		}
	})
	db, _ := testDatabaseInstance.NewDatabase(t, cacher)

	// Create config.
	cfg := &config.RedirectConfig{
		AssetsPath: filepath.Join(project.Root(), "cmd", "enx-redirect", "assets"),
		DevMode:    true,
		HostnameConfig: map[string]string{
			"bad":  "nope",
			"okay": "bb",
		},
	}

	// Set realm to resolve.
	realm1, err := db.FindRealm(1)
	if err != nil {
		t.Fatal(err)
	}
	realm1.RegionCode = "aa"
	if err := db.SaveRealm(realm1, database.SystemTest); err != nil {
		t.Fatal(err)
	}

	// Create another realm with apps.
	realm2 := database.NewRealmWithDefaults("okay")
	realm2.RegionCode = "bb"
	if err := db.SaveRealm(realm2, database.SystemTest); err != nil {
		t.Fatal(err)
	}

	// Create iOS app
	iosApp := &database.MobileApp{
		Name:    "app1",
		RealmID: realm2.ID,
		URL:     "https://app1.example.com/",
		OS:      database.OSTypeIOS,
		AppID:   "com.example.app1",
	}
	if err := db.SaveMobileApp(iosApp, database.SystemTest); err != nil {
		t.Fatal(err)
	}

	// Create Android app
	app2 := &database.MobileApp{
		Name:    "app2",
		RealmID: realm2.ID,
		URL:     "https://app2.example.com/",
		OS:      database.OSTypeAndroid,
		AppID:   "com.example.app2",
		SHA:     "AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA",
	}
	if err := db.SaveMobileApp(app2, database.SystemTest); err != nil {
		t.Fatal(err)
	}

	// Build routes.
	mux, err := routes.ENXRedirect(ctx, cfg, db, cacher)
	if err != nil {
		t.Fatal(err)
	}

	// Start server.
	srv := httptest.NewServer(mux)
	t.Cleanup(func() {
		srv.Close()
	})
	client := srv.Client()

	// Don't follow redirects.
	client.CheckRedirect = func(r *http.Request, via []*http.Request) error {
		return http.ErrUseLastResponse
	}

	// Bad path
	t.Run("bad_path", func(t *testing.T) {
		t.Parallel()

		req, err := http.NewRequest("GET", srv.URL+"/css/view/main/gift.css", nil)
		if err != nil {
			t.Fatal(err)
		}
		resp, err := client.Do(req)
		if err != nil {
			t.Fatal(err)
		}
		defer resp.Body.Close()

		if got, want := resp.StatusCode, 404; got != want {
			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				t.Fatal(err)
			}
			t.Errorf("expected %d to be %d: %s", got, want, body)
		}
	})

	// No matching region returns a 404
	t.Run("no_matching_region", func(t *testing.T) {
		t.Parallel()

		req, err := http.NewRequest("GET", srv.URL, nil)
		req.Host = "not-real"
		if err != nil {
			t.Fatal(err)
		}
		resp, err := client.Do(req)
		if err != nil {
			t.Fatal(err)
		}
		defer resp.Body.Close()

		if got, want := resp.StatusCode, 404; got != want {
			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
{'fraction_non_alphanumeric': 0.1599141739240187, 'fraction_numerical': 0.009087466868610375, 'mean_word_length': 3.43921568627451, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6255042', 'n_tokens_mistral': 3159, 'n_tokens_neox': 2919, 'n_words': 663}