summary refs log blame commit diff stats
path: root/registry/user_test.go
blob: f0c9622102d1fd21035a256fccbd1f37b0f44705 (plain) (tree)




























































































































































































































































































































































                                                                                                                
/*
Copyright (c) 2019 Ben Morrison (gbmor)

This file is part of Registry.

Registry is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Registry is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Registry.  If not, see <https://www.gnu.org/licenses/>.
*/

package registry // import "git.sr.ht/~gbmor/getwtxt/registry"

import (
	"bufio"
	"fmt"
	"net/http"
	"os"
	"reflect"
	"testing"
)

var addUserCases = []struct {
	name      string
	nick      string
	url       string
	wantErr   bool
	localOnly bool
}{
	{
		name:      "Legitimate User (Local Only)",
		nick:      "testuser1",
		url:       "http://localhost:8080/twtxt.txt",
		wantErr:   false,
		localOnly: true,
	},
	{
		name:      "Empty Query",
		nick:      "",
		url:       "",
		wantErr:   true,
		localOnly: false,
	},
	{
		name:      "Invalid URL",
		nick:      "foo",
		url:       "foobarringtons",
		wantErr:   true,
		localOnly: false,
	},
	{
		name:      "Garbage Data",
		nick:      "",
		url:       "",
		wantErr:   true,
		localOnly: false,
	},
}

// Tests if we can successfully add a user to the registry
func Test_Registry_AddUser(t *testing.T) {
	registry := initTestEnv()
	if !addUserCases[0].localOnly {
		http.Handle("/twtxt.txt", http.HandlerFunc(twtxtHandler))
		go fmt.Println(http.ListenAndServe(":8080", nil))
	}
	var buf = make([]byte, 256)
	// read random data into case 5
	rando, _ := os.Open("/dev/random")
	reader := bufio.NewReader(rando)
	n, err := reader.Read(buf)
	if err != nil || n == 0 {
		t.Errorf("Couldn't set up test: %v\n", err)
	}
	addUserCases[3].nick = string(buf)
	addUserCases[3].url = string(buf)

	statuses, err := registry.GetStatuses()
	if err != nil {
		t.Errorf("Error setting up test: %v\n", err)
	}

	for n, tt := range addUserCases {
		t.Run(tt.name, func(t *testing.T) {
			if tt.localOnly {
				t.Skipf("Local-only test. Skipping ... ")
			}

			err := registry.AddUser(tt.nick, tt.url, nil, statuses)

			// only run some checks if we don't want an error
			if !tt.wantErr {
				if err != nil {
					t.Errorf("Got error: %v\n", err)
				}

				// make sure we have *something* in the registry
				if reflect.ValueOf(registry.Users[tt.url]).IsNil() {
					t.Errorf("Failed to add user %v registry.\n", tt.url)
				}

				// see if the nick in the registry is the same
				// as the test case. verifies the URL and the nick
				// since the URL is used as the key
				data := registry.Users[tt.url]
				if data.Nick != tt.nick {
					t.Errorf("Incorrect user data added to registry for user %v.\n", tt.url)
				}
			}
			// check for the cases that should throw an error
			if tt.wantErr && err == nil {
				t.Errorf("Expected error for case %v, got nil\n", n)
			}
		})
	}
}
func Benchmark_Registry_AddUser(b *testing.B) {
	registry := initTestEnv()
	statuses, err := registry.GetStatuses()
	if err != nil {
		b.Errorf("Error setting up test: %v\n", err)
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for _, tt := range addUserCases {
			err := registry.AddUser(tt.nick, tt.url, nil, statuses)
			if err != nil {
				continue
			}
			registry.Users[tt.url] = &User{}
		}
	}
}

var delUserCases = []struct {
	name    string
	url     string
	wantErr bool
}{
	{
		name:    "Valid User",
		url:     "https://example.com/twtxt.txt",
		wantErr: false,
	},
	{
		name:    "Valid User",
		url:     "https://example3.com/twtxt.txt",
		wantErr: false,
	},
	{
		name:    "Already Deleted User",
		url:     "https://example3.com/twtxt.txt",
		wantErr: true,
	},
	{
		name:    "Empty Query",
		url:     "",
		wantErr: true,
	},
	{
		name:    "Garbage Data",
		url:     "",
		wantErr: true,
	},
}

// Tests if we can successfully delete a user from the registry
func Test_Registry_DelUser(t *testing.T) {
	registry := initTestEnv()
	var buf = make([]byte, 256)
	// read random data into case 5
	rando, _ := os.Open("/dev/random")
	reader := bufio.NewReader(rando)
	n, err := reader.Read(buf)
	if err != nil || n == 0 {
		t.Errorf("Couldn't set up test: %v\n", err)
	}
	delUserCases[4].url = string(buf)

	for n, tt := range delUserCases {
		t.Run(tt.name, func(t *testing.T) {

			err := registry.DelUser(tt.url)
			if !reflect.ValueOf(registry.Users[tt.url]).IsNil() {
				t.Errorf("Failed to delete user %v from registry.\n", tt.url)
			}
			if tt.wantErr && err == nil {
				t.Errorf("Expected error but did not receive. Case %v\n", n)
			}
			if !tt.wantErr && err != nil {
				t.Errorf("Unexpected error for case %v: %v\n", n, err)
			}
		})
	}
}
func Benchmark_Registry_DelUser(b *testing.B) {
	registry := initTestEnv()

	data1 := &User{
		Nick:   registry.Users[delUserCases[0].url].Nick,
		Date:   registry.Users[delUserCases[0].url].Date,
		Status: registry.Users[delUserCases[0].url].Status,
	}

	data2 := &User{
		Nick:   registry.Users[delUserCases[1].url].Nick,
		Date:   registry.Users[delUserCases[1].url].Date,
		Status: registry.Users[delUserCases[1].url].Status,
	}
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		for _, tt := range delUserCases {
			err := registry.DelUser(tt.url)
			if err != nil {
				continue
			}
		}

		registry.Users[delUserCases[0].url] = data1
		registry.Users[delUserCases[1].url] = data2
	}
}

var getUserStatusCases = []struct {
	name    string
	url     string
	wantErr bool
}{
	{
		name:    "Valid User",
		url:     "https://example.com/twtxt.txt",
		wantErr: false,
	},
	{
		name:    "Valid User",
		url:     "https://example3.com/twtxt.txt",
		wantErr: false,
	},
	{
		name:    "Nonexistent User",
		url:     "https://doesn't.exist/twtxt.txt",
		wantErr: true,
	},
	{
		name:    "Empty Query",
		url:     "",
		wantErr: true,
	},
	{
		name:    "Garbage Data",
		url:     "",
		wantErr: true,
	},
}

// Checks if we can retrieve a single user's statuses
func Test_Registry_GetUserStatuses(t *testing.T) {
	registry := initTestEnv()
	var buf = make([]byte, 256)
	// read random data into case 5
	rando, _ := os.Open("/dev/random")
	reader := bufio.NewReader(rando)
	n, err := reader.Read(buf)
	if err != nil || n == 0 {
		t.Errorf("Couldn't set up test: %v\n", err)
	}
	getUserStatusCases[4].url = string(buf)

	for n, tt := range getUserStatusCases {
		t.Run(tt.name, func(t *testing.T) {

			statuses, err := registry.GetUserStatuses(tt.url)

			if !tt.wantErr {
				if reflect.ValueOf(statuses).IsNil() {
					t.Errorf("Failed to pull statuses for user %v\n", tt.url)
				}
				// see if the function returns the same data
				// that we already have
				data := registry.Users[tt.url]
				if !reflect.DeepEqual(data.Status, statuses) {
					t.Errorf("Incorrect data retrieved as statuses for user %v.\n", tt.url)
				}
			}

			if tt.wantErr && err == nil {
				t.Errorf("Expected error, received nil for case %v: %v\n", n, tt.url)
			}
		})
	}
}
func Benchmark_Registry_GetUserStatuses(b *testing.B) {
	registry := initTestEnv()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		for _, tt := range getUserStatusCases {
			_, err := registry.GetUserStatuses(tt.url)
			if err != nil {
				continue
			}
		}
	}
}

// Tests if we can retrieve all user statuses at once
func Test_Registry_GetStatuses(t *testing.T) {
	registry := initTestEnv()
	t.Run("Registry.GetStatuses()", func(t *testing.T) {

		statuses, err := registry.GetStatuses()
		if reflect.ValueOf(statuses).IsNil() || err != nil {
			t.Errorf("Failed to pull all statuses. %v\n", err)
		}

		// Now do the same query manually to see
		// if we get the same result
		unionmap := NewTimeMap()
		for _, v := range registry.Users {
			for i, e := range v.Status {
				unionmap[i] = e
			}
		}
		if !reflect.DeepEqual(statuses, unionmap) {
			t.Errorf("Incorrect data retrieved as statuses.\n")
		}
	})
}
func Benchmark_Registry_GetStatuses(b *testing.B) {
	registry := initTestEnv()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		_, err := registry.GetStatuses()
		if err != nil {
			continue
		}
	}
}