// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package binarylib

import (
	"bytes"
	"crypto/sha256"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"testing"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/naming"
	"v.io/v23/services/repository"
	"v.io/x/lib/vlog"

	"v.io/x/ref/test"
	"v.io/x/ref/test/testutil"
)

//go:generate v23 test generate

const (
	v23Prefix = "vanadium_binary_repository"
)

func setupRepository(t *testing.T, ctx *context.T) (string, func()) {
	// Setup the root of the binary repository.
	rootDir, err := ioutil.TempDir("", v23Prefix)
	if err != nil {
		t.Fatalf("TempDir() failed: %v", err)
	}
	path, perm := filepath.Join(rootDir, VersionFile), os.FileMode(0600)
	if err := ioutil.WriteFile(path, []byte(Version), perm); err != nil {
		vlog.Fatalf("WriteFile(%v, %v, %v) failed: %v", path, Version, perm, err)
	}
	// Setup and start the binary repository server.
	server, err := v23.NewServer(ctx)
	if err != nil {
		t.Fatalf("NewServer() failed: %v", err)
	}
	depth := 2
	state, err := NewState(rootDir, "http://test-root-url", depth)
	if err != nil {
		t.Fatalf("NewState(%v, %v) failed: %v", rootDir, depth, err)
	}

	dispatcher, err := NewDispatcher(v23.GetPrincipal(ctx), state)
	if err != nil {
		t.Fatalf("NewDispatcher() failed: %v\n", err)
	}
	l := v23.GetListenSpec(ctx)
	endpoints, err := server.Listen(l)
	if err != nil {
		t.Fatalf("Listen(%s) failed: %v", l, err)
	}
	suffix := ""
	if err := server.ServeDispatcher(suffix, dispatcher); err != nil {
		t.Fatalf("Serve(%v, %v) failed: %v", suffix, dispatcher, err)
	}
	von := naming.JoinAddressName(endpoints[0].String(), "test")
	return von, func() {
		if err := os.Remove(path); err != nil {
			t.Fatalf("Remove(%v) failed: %v", path, err)
		}
		// Check that any directories and files that were created to
		// represent the binary objects have been garbage collected.
		if err := os.RemoveAll(rootDir); err != nil {
			t.Fatalf("Remove(%v) failed: %v", rootDir, err)
		}
		// Shutdown the binary repository server.
		if err := server.Stop(); err != nil {
			t.Fatalf("Stop() failed: %v", err)
		}
	}
}

// TestBufferAPI tests the binary repository client-side library
// interface using buffers.
func TestBufferAPI(t *testing.T) {
	ctx, shutdown := test.V23Init()
	defer shutdown()

	v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))

	von, cleanup := setupRepository(t, ctx)
	defer cleanup()
	data := testutil.RandomBytes(testutil.Intn(10 << 20))
	mediaInfo := repository.MediaInfo{Type: "application/octet-stream"}
	sig, err := Upload(ctx, von, data, mediaInfo)
	if err != nil {
		t.Fatalf("Upload(%v) failed: %v", von, err)
	}
	p := v23.GetPrincipal(ctx)
	if sig != nil {
		// verify the principal signature
		h := sha256.Sum256(data)
		if !sig.Verify(p.PublicKey(), h[:]) {
			t.Fatalf("Failed to verify upload signature(%v)", sig)
		}
		// verify that Sign called directly also produces a working signature
		reader := bytes.NewReader(data)
		sig2, err := Sign(ctx, reader)
		if err != nil {
			t.Fatalf("Sign failed: %v", err)
		}
		if !sig2.Verify(p.PublicKey(), h[:]) {
			t.Fatalf("Failed to verify signature from Sign(%v, %v)", sig, sig2)
		}
	} else {
		t.Fatalf("Upload(%v) failed to generate principal(%v) signature", von, p)
	}
	output, outInfo, err := Download(ctx, von)
	if err != nil {
		t.Fatalf("Download(%v) failed: %v", von, err)
	}
	if bytes.Compare(data, output) != 0 {
		t.Errorf("Data mismatch:\nexpected %v %v\ngot %v %v", len(data), data[:100], len(output), output[:100])
	}
	if err := Delete(ctx, von); err != nil {
		t.Errorf("Delete(%v) failed: %v", von, err)
	}
	if _, _, err := Download(ctx, von); err == nil {
		t.Errorf("Download(%v) did not fail", von)
	}
	if !reflect.DeepEqual(mediaInfo, outInfo) {
		t.Errorf("unexpected media info: expected %v, got %v", mediaInfo, outInfo)
	}
}

// TestFileAPI tests the binary repository client-side library
// interface using files.
func TestFileAPI(t *testing.T) {
	ctx, shutdown := test.V23Init()
	defer shutdown()

	v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))

	von, cleanup := setupRepository(t, ctx)
	defer cleanup()
	// Create up to 10MB of random bytes.
	data := testutil.RandomBytes(testutil.Intn(10 << 20))
	dir, prefix := "", ""
	src, err := ioutil.TempFile(dir, prefix)
	if err != nil {
		t.Fatalf("TempFile(%v, %v) failed: %v", dir, prefix, err)
	}
	defer os.Remove(src.Name())
	defer src.Close()
	dstdir, err := ioutil.TempDir(dir, prefix)
	if err != nil {
		t.Fatalf("TempDir(%v, %v) failed: %v", dir, prefix, err)
	}
	defer os.RemoveAll(dstdir)
	dst, err := ioutil.TempFile(dstdir, prefix)
	if err != nil {
		t.Fatalf("TempFile(%v, %v) failed: %v", dstdir, prefix, err)
	}
	defer dst.Close()
	if _, err := src.Write(data); err != nil {
		t.Fatalf("Write() failed: %v", err)
	}
	if _, err := UploadFromFile(ctx, von, src.Name()); err != nil {
		t.Fatalf("UploadFromFile(%v, %v) failed: %v", von, src.Name(), err)
	}
	if err := DownloadToFile(ctx, von, dst.Name()); err != nil {
		t.Fatalf("DownloadToFile(%v, %v) failed: %v", von, dst.Name(), err)
	}
	output, err := ioutil.ReadFile(dst.Name())
	if err != nil {
		t.Errorf("ReadFile(%v) failed: %v", dst.Name(), err)
	}
	if bytes.Compare(data, output) != 0 {
		t.Errorf("Data mismatch:\nexpected %v %v\ngot %v %v", len(data), data[:100], len(output), output[:100])
	}
	jMediaInfo, err := ioutil.ReadFile(dst.Name() + ".__info")
	if err != nil {
		t.Errorf("ReadFile(%v) failed: %v", dst.Name()+".__info", err)
	}
	if expected := `{"Type":"application/octet-stream","Encoding":""}`; string(jMediaInfo) != expected {
		t.Errorf("unexpected media info: expected %q, got %q", expected, string(jMediaInfo))
	}
	if err := Delete(ctx, von); err != nil {
		t.Errorf("Delete(%v) failed: %v", von, err)
	}
}

// TestDownloadUrl tests the binary repository client-side library
// DownloadUrl method.
func TestDownloadUrl(t *testing.T) {
	ctx, shutdown := test.V23Init()
	defer shutdown()

	v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))

	von, cleanup := setupRepository(t, ctx)
	defer cleanup()
	url, _, err := DownloadUrl(ctx, von)
	if err != nil {
		t.Fatalf("DownloadUrl(%v) failed: %v", von, err)
	}
	if got, want := url, "http://test-root-url/test"; got != want {
		t.Fatalf("unexpect output: got %v, want %v", got, want)
	}
}
