<commit_before>package main

import (
	"io"
	"strings"
	"testing"
	"time"
)

const pubkeyRsa4096 = "<KEY>" +
	"<KEY>" +
	"<KEY>" +
	"<KEY>" +
	"<KEY>" +
	"<KEY>" +
	"<KEY> +
	"<KEY>" +
	"<KEY>" +
	"BK29GkF/mJGYEqRV1dvMTEO7PjIGegX237qegIdrKoIMKD1x0t2m7/r/+IFpu3Ztjl3y" +
	"aRdw0cIrz7o/Vow6PyTHgEc74L2vE1ZtR2F8O1Vw=="
const fingerprintRsa4096 = "3c:a1:90:94:fd:56:ea:92:d2:d8:3f:12:27:47:96:d3"
const fingerprintSHA256Rsa4096 = "ijtgEqybuFNrfP777QRpiuQzhbjUaSbeqcEPXsJFqnc"

const pubkeyRsa2048 = "<KEY> +
	"<KEY>" +
	"<KEY>" +
	"<KEY>" +
	"<KEY>" +
	"<KEY>"
const fingerprintRsa2048 = "3f:96:4d:01:7e:43:a8:09:40:29:4b:e4:28:6a:e1:21"
const fingerprintSHA256Rsa2048 = "VmyFUZbo/kpCuG28EyR463w/Wl+1SkRfI+1oeCmwvc0"

const pubkeyRsa1024 = "<KEY> +
	"<KEY> +
	"<KEY>" +
	"J9tQ=="
const fingerprintRsa1024 = "e6:96:4f:57:3a:65:d9:f5:23:bb:56:5a:03:27:86:8d"
const fingerprintSHA256Rsa1024 = "F+TENUvs5TAmRYHDb4DA4nRaD40APli0nOCsL8hskBE"

const pubkeyDsa = "<KEY>" +
	"<KEY>" +
	"<KEY>" +
	"<KEY>cCWJxt4cPAidwFyf5/nOduzI2DmuFGLupEK" +
	"VY4LlI8luNyTcBxxE3rdyeF0wuI7Ssoma8sib4u1NLA1QDMzXTpqP2sKZiAWkgh0h4neHwQz" +
	"XZD6vDJmKuJ95BavLQrQaxlSjjgbvlJoVPWhRBbWW//5qG/w4UqrsnwMcAAACBALGGFn3chw" +
	"/iQOIQAzKDyBm3iYvTB6ZoxxRRIx5H6hpXKSnki1QG2m7B25WTxgJy+DdEoBhIe74G0Q4eB3" +
	"ExJLS1G+mBd11IRJNpl8F7Ai46Sqdg3rqlghR6abPGMtS8VqDY/aQyO63yyUQjYvL+KiFKTM" +
	"Qgf9WpltBpP2rg0BDO"
const fingerprintDsa = "b9:e9:3c:2b:e7:47:87:35:4e:b4:ab:28:5d:b0:dd:03"
const fingerprintSHA256Dsa = "3bLWcIqMtaj8oGVGw3LPCyed1y2kXjXj2oINCahL/ME"

const pubkeyEcdsa256 = "<KEY> +
	"<KEY>" +
	"US01YAlcrVyahI="
const fingerprintEcdsa256 = "b0:3a:37:c0:99:09:b0:e4:a1:9f:9f:fb:de:18:a5:56"
const fingerprintSHA256Ecdsa256 = "Gz0UeVhLA4DHQMlK+Ru0cSsWAA03RxNouMiZrE31Bd8"

const pubkeyEcdsa384 = "<KEY> +
	"<KEY>" +
	"KsEflg1spEGNCfrBB/OtB93RDz6mzSMmouJfXeidYjI1VMtZVVJY59DbQ=="
const fingerprintEcdsa384 = "fc:16:56:45:33:1b:e5:71:45:c4:88:7d:b9:2d:8a:b9"
const fingerprintSHA256Ecdsa384 = "loP2THC86Gf2cGyfZ98GpU8Cz/63XlkPF/5bqnQxabw"

const pubkeyEcdsa521 = "<KEY>" +
	"<KEY>" +
	"Vay8SogT1MEE5sqowG/NFMo+ntjTbloUzIXXyyfU/owI939bOmSCrttWd6lDQ24y1ZXFi+Sg" +
	"<KEY>bVcNQLH0Egig=="
const fingerprintEcdsa521 = "58:b4:2c:c4:a6:48:11:aa:4b:c9:29:6f:f9:b4:db:ba"
const fingerprintSHA256Ecdsa521 = "TTCk17hNFxJwsbezGRWcr4/53KcaA9Vjck70jZrJoNk"

const pubkeyEd25519 = "<KEY>"
const fingerprintEd25519 = "b7:32:01:5c:78:97:b1:3f:4d:bd:98:56:d0:33:61:3a"
const fingerprintSHA256Ed25519 = "dqnPmznV1WeYUTUo+ZRBoaZzgbo1H30rqbk1MyiQsB4"

func TestComputeFingerprint(t *testing.T) {
	parameters := []struct {
		pubkey            string
		fingerprintMD5    string
		fingerprintSHA256 string
	}{
		{pubkeyRsa1024, fingerprintRsa1024, fingerprintSHA256Rsa1024},
		{pubkeyRsa2048, fingerprintRsa2048, fingerprintSHA256Rsa2048},
		{pubkeyRsa4096, fingerprintRsa4096, fingerprintSHA256Rsa4096},
		{pubkeyDsa, fingerprintDsa, fingerprintSHA256Dsa},
		{pubkeyEcdsa256, fingerprintEcdsa256, fingerprintSHA256Ecdsa256},
		{pubkeyEcdsa384, fingerprintEcdsa384, fingerprintSHA256Ecdsa384},
		{pubkeyEcdsa521, fingerprintEcdsa521, fingerprintSHA256Ecdsa521},
		{pubkeyEd25519, fingerprintEd25519, fingerprintSHA256Ed25519},
	}

	for _, p := range parameters {
		md5 := fingerprintMD5(p.pubkey)
		if md5 != p.fingerprintMD5 {
			t.Errorf("Expected MD5 %s but got %s", p.fingerprintMD5, md5)
		}

		sha256 := fingerprintSHA256(p.pubkey)
		if sha256 != p.fingerprintSHA256 {
			t.Errorf("Expected SHA256 %s but got %s", p.fingerprintSHA256, sha256)
		}
	}
}

func TestParseAuthorizedKeys(t *testing.T) {
	authorizedKeys := "ssh-rsa " + pubkeyRsa4096 + " <EMAIL>@github.com\n" +
		"ssh-rsa INVALIDKEY"

	var reader io.Reader = strings.NewReader(authorizedKeys)
	keys, err := parseAuthorizedKeys(&reader)

	if err != nil {
		t.Fatalf("Failed with error: %s", err)
	}

	if len(keys) != 1 {
		t.Fatalf("Expected %d but got %d keys", 1, len(keys))
	}

	if keys[0].name != "<EMAIL>" {
		t.Errorf("Expected name %s but got %s", "<EMAIL>",
			keys[0].name)
	}

	if keys[0].alg.name != "RSA" {
		t.Errorf("Expected algorithm %s but got %s", "RSA",
			keys[0].alg.name)
	}

	if keys[0].alg.keylen != 4096 {
		t.Errorf("Expected keylen %d but got %d", 4096, keys[0].alg.keylen)
	}

	if keys[0].fingerprintMD5 != fingerprintRsa4096 {
		t.Errorf("Expected fingerprint (MD5) %s but got %s", fingerprintRsa4096,
			keys[0].fingerprintMD5)
	}

	if keys[0].fingerprintSHA256 != fingerprintSHA256Rsa4096 {
		t.Errorf("Expected fingerprint (SHA256) %s but got %s", fingerprintSHA256Rsa4096,
			keys[0].fingerprintSHA256)
	}
}

func TestParseAllUsers(t *testing.T) {
	passwd := "root:x:0:0:root:/root:/bin/bash\n" +
		"hans:x:1000:1000:Hans,,,:/home/hans:/usr/bin/zsh"

	var reader io.Reader = strings.NewReader(passwd)
	users, err := parseAllUsers(&reader)

	if err != nil {
		t.Fatalf("Failed with error: %s", err)
	}

	if len(users) != 2 {
		t.Fatalf("Expected %d but got %d users", 2, len(users))
	}

	if users[0].name != "root" {
		t.Errorf("Expected name %s but %s", "root", users[0].name)
	}

	if users[0].home != "/root" {
		t.Errorf("Expected home %s but got %s", "/root", users[0].home)
	}

	if users[1].name != "hans" {
		t.Errorf("Expected name %s but got %s", "hans", users[1].name)
	}

	if users[1].home != "/home/hans" {
		t.Errorf("Expected home %s but got %s", "/home/hans", users[1].home)
	}
}

func TestDurationAsString(t *testing.T) {
	parameters := []struct {
		in  time.Duration
		out string
	}{
		{12 * time.Second, "just now"},
		{1 * time.Minute, "1 minute ago"},
		{2 * time.Minute, "2 minutes ago"},<commit_msg>Fix unit tests for durationAsString<commit_after>package main

import (
	"io"
	"strings"
	"testing"
	"time"
)

const pubkeyRsa4096 = "<KEY>" +
	"<KEY>" +
	"<KEY>" +
	"<KEY>" +
	"<KEY>" +
	"<KEY>" +
	"<KEY> +
	"<KEY>" +
	"Y9Ocm7IGAz1u/<KEY>" +
	"<KEY>" +
	"<KEY>o/Vow6PyTHgEc74L2vE1ZtR2F8O1Vw=="
const fingerprintRsa4096 = "3c:a1:90:94:fd:56:ea:92:d2:d8:3f:12:27:47:96:d3"
const fingerprintSHA256Rsa4096 = "ijtgEqybuFNrfP777QRpiuQzhbjUaSbeqcEPXsJFqnc"

const pubkeyRsa2048 = "<KEY> +
	"<KEY>" +
	"<KEY>" +
	"<KEY>" +
	"<KEY>" +
	"<KEY>"
const fingerprintRsa2048 = "3f:96:4d:01:7e:43:a8:09:40:29:4b:e4:28:6a:e1:21"
const fingerprintSHA256Rsa2048 = "VmyFUZbo/kpCuG28EyR463w/Wl+1SkRfI+1oeCmwvc0"

const pubkeyRsa1024 = "<KEY> +
	"<KEY>c+<KEY>" +
	"T/cKoxQ1sBRAeFDCchwaHxf8HDZOw6bARJzkmhUpMvw7ZaEaCLseNHkc0FAbPHuYrN6xCCiz" +
	"J9tQ=="
const fingerprintRsa1024 = "e6:96:4f:57:3a:65:d9:f5:23:bb:56:5a:03:27:86:8d"
const fingerprintSHA256Rsa1024 = "F+TENUvs5TAmRYHDb4DA4nRaD40APli0nOCsL8hskBE"

const pubkeyDsa = "<KEY>" +
	"<KEY>" +
	"<KEY>" +
	"<KEY>5Rs4adBXMVBQAAAIEAm6w3yAWcCWJxt4cPAidwFyf5/nOduzI2DmuFGLupEK" +
	"VY4LlI8luNyTcBxxE3rdyeF0wuI7Ssoma8sib4u1NLA1QDMzXTpqP2sKZiAWkgh0h4neHwQz" +
	"XZD6vDJmKuJ95BavLQrQaxlSjjgbvlJoVPWhRBbWW//5qG/w4UqrsnwMcAAACBALGGFn3chw" +
	"/iQOIQAzKDyBm3iYvTB6ZoxxRRIx5H6hpXKSnki1QG2m7B25WTxgJy+DdEoBhIe74G0Q4eB3" +
	"ExJLS1G+mBd11IRJNpl8F7Ai46Sqdg3rqlghR6abPGMtS8VqDY/aQyO63yyUQjYvL+KiFKTM" +
	"Qgf9WpltBpP2rg0BDO"
const fingerprintDsa = "b9:e9:3c:2b:e7:47:87:35:4e:b4:ab:28:5d:b0:dd:03"
const fingerprintSHA256Dsa = "3bLWcIqMtaj8oGVGw3LPCyed1y2kXjXj2oINCahL/ME"

const pubkeyEcdsa256 = "<KEY>" +
	"<KEY>" +
	"US01YAlcrVyahI="
const fingerprintEcdsa256 = "b0:3a:37:c0:99:09:b0:e4:a1:9f:9f:fb:de:18:a5:56"
const fingerprintSHA256Ecdsa256 = "Gz0UeVhLA4DHQMlK+Ru0cSsWAA03RxNouMiZrE31Bd8"

const pubkeyEcdsa384 = "<KEY> +
	"<KEY>" +
	"KsEflg1spEGNCfrBB/OtB93RDz6mzSMmouJfXeidYjI1VMtZVVJY59DbQ=="
const fingerprintEcdsa384 = "fc:16:56:45:33:1b:e5:71:45:c4:88:7d:b9:2d:8a:b9"
const fingerprintSHA256Ecdsa384 = "loP2THC86Gf2cGyfZ98GpU8Cz/63XlkPF/5bqnQxabw"

const pubkeyEcdsa521 = "<KEY>" +
	"<KEY>" +
	"Vay8SogT1MEE5sqowG/NFMo+ntjTbloUzIXXyyfU/owI939bOmSCrttWd6lDQ24y1ZXFi+Sg" +
	"Ymks8rhruGNTv0quXWgC5bVcNQLH0Egig=="
const fingerprintEcdsa521 = "58:b4:2c:c4:a6:48:11:aa:4b:c9:29:6f:f9:b4:db:ba"
const fingerprintSHA256Ecdsa521 = "TTCk17hNFxJwsbezGRWcr4/53KcaA9Vjck70jZrJoNk"

const pubkeyEd25519 = "<KEY>" +
	"<KEY>"
const fingerprintEd25519 = "b7:32:01:5c:78:97:b1:3f:4d:bd:98:56:d0:33:61:3a"
const fingerprintSHA256Ed25519 = "dqnPmznV1WeYUTUo+ZRBoaZzgbo1H30rqbk1MyiQsB4"

func TestComputeFingerprint(t *testing.T) {
	parameters := []struct {
		pubkey            string
		fingerprintMD5    string
		fingerprintSHA256 string
	}{
		{pubkeyRsa1024, fingerprintRsa1024, fingerprintSHA256Rsa1024},
		{pubkeyRsa2048, fingerprintRsa2048, fingerprintSHA256Rsa2048},
		{pubkeyRsa4096, fingerprintRsa4096, fingerprintSHA256Rsa4096},
		{pubkeyDsa, fingerprintDsa, fingerprintSHA256Dsa},
		{pubkeyEcdsa256, fingerprintEcdsa256, fingerprintSHA256Ecdsa256},
		{pubkeyEcdsa384, fingerprintEcdsa384, fingerprintSHA256Ecdsa384},
		{pubkeyEcdsa521, fingerprintEcdsa521, fingerprintSHA256Ecdsa521},
		{pubkeyEd25519, fingerprintEd25519, fingerprintSHA256Ed25519},
	}

	for _, p := range parameters {
		md5 := fingerprintMD5(p.pubkey)
		if md5 != p.fingerprintMD5 {
			t.Errorf("Expected MD5 %s but got %s", p.fingerprintMD5, md5)
		}

		sha256 := fingerprintSHA256(p.pubkey)
		if sha256 != p.fingerprintSHA256 {
			t.Errorf("Expected SHA256 %s but got %s", p.fingerprintSHA256, sha256)
		}
	}
}

func TestParseAuthorizedKeys(t *testing.T) {
	authorizedKeys := "ssh-rsa " + pubkeyRsa4096 + " <EMAIL>\n" +
		"ssh-rsa INVALIDKEY"

	var reader io.Reader = strings.NewReader(authorizedKeys)
	keys, err := parseAuthorizedKeys(&reader)

	if err != nil {
		t.Fatalf("Failed with error: %s", err)
	}

	if len(keys) != 1 {
		t.Fatalf("Expected %d but got %d keys", 1, len(keys))
	}

	if keys[0].name != "<EMAIL>" {
		t.Errorf("Expected name %s but got %s", "<EMAIL>",
			keys[0].name)
	}

	if keys[0].alg.name != "RSA" {
		t.Errorf("Expected algorithm %s but got %s", "RSA",
			keys[0].alg.name)
	}

	if keys[0].alg.keylen != 4096 {
		t.Errorf("Expected keylen %d but got %d", 4096, keys[0].alg.keylen)
	}

	if keys[0].fingerprintMD5 != fingerprintRsa4096 {
		t.Errorf("Expected fingerprint (MD5) %s but got %s", fingerprintRsa4096,
			keys[0].fingerprintMD5)
	}

	if keys[0].fingerprintSHA256 != fingerprintSHA256Rsa4096 {
		t.Errorf("Expected fingerprint (SHA256) %s but got %s", fingerprintSHA256Rsa4096,
			keys[0].fingerprintSHA256)
	}
}

func TestParseAllUsers(t *testing.T) {
	passwd := "root:x:0:0:root:/root:/bin/bash\n" +
		"hans:x:1000:1000:Hans,,,:/home/hans:/usr/bin/zsh"

	var reader io.Reader = strings.NewReader(passwd)
	users, err := parseAllUsers(&reader)

	if err != nil {
		t.Fatalf("Failed with error: %s", err)
	}

	if len(users) != 2 {
		t.Fatalf("Expected %d but got %d users", 2, len(users))
	}

	if users[0].name != "root" {
		t.Errorf("Expected name %s but %s", "root", users[0].name)
	}

	if users[0].home != "/root" {
		t.Errorf("Expected home %s but got %s", "/root", users[0].home)
	}

	if users[1].name != "hans" {
		t.Errorf("Expected name %s but got %s", "hans", users[1].name)
	}

	if users[1].home != "/home/hans" {
		t.Errorf("Expected home %s but got %s", "/home/hans", users[1].home)
	}
}

func TestDurationAsString(t *testing.T) {
	parameters := []struct {
		in  time.Duration
		out string
	}{
		{999 * time.Millisecond, "just now"},
		{12 * time.Second, "12 seconds ago"},
		{1 * time.Minute, "1 minute ago"},
		{2 * time.Minute, "2 minutes ago"},
{'fraction_non_alphanumeric': 0.15915969378671888, 'fraction_numerical': 0.11429588748442229, 'mean_word_length': 5.863164324984728, 'pattern_counts': {'":': 0, '<': 71, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '447596', 'n_tokens_mistral': 6347, 'n_tokens_neox': 5475, 'n_words': 743}