From 049b939349c12630e56cfd1d9b7a9cfcaa8a8018 Mon Sep 17 00:00:00 2001 From: Alexandre Pujol Date: Sun, 16 Apr 2023 23:26:46 +0100 Subject: [PATCH] refractor: add initial go internall pkg module. --- pkg/logging/logging.go | 90 +++++++++++++++++++++++++++++++ pkg/logging/logging_test.go | 102 ++++++++++++++++++++++++++++++++++++ pkg/util/tools.go | 40 ++++++++++++++ pkg/util/tools_test.go | 57 ++++++++++++++++++++ 4 files changed, 289 insertions(+) create mode 100644 pkg/logging/logging.go create mode 100644 pkg/logging/logging_test.go create mode 100644 pkg/util/tools.go create mode 100644 pkg/util/tools_test.go diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go new file mode 100644 index 000000000..b27fb70f2 --- /dev/null +++ b/pkg/logging/logging.go @@ -0,0 +1,90 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2023 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package logging + +import ( + "fmt" + "os" +) + +// Colors +const ( + reset = "\033[0m" + bold = "\033[1m" + boldRed = "\033[1;31m" + boldGreen = "\033[1;32m" + boldYellow = "\033[1;33m" +) + +// Logging messages prefix +const ( + bulletText = bold + " ⋅ " + reset + errorText = boldRed + " ✗ Error: " + reset + successText = boldGreen + " ✓ " + reset + warningText = boldYellow + " ‼ " + reset +) + +// Print prints a formatted message. Arguments are handled in the manner of fmt.Print. +func Print(msg string, a ...interface{}) int { + n, _ := fmt.Fprintf(os.Stdout, msg, a...) + return n +} + +// Println prints a formatted message. Arguments are handled in the manner of fmt.Println. +func Println(msg string) int { + n, _ := fmt.Fprintf(os.Stdout, msg+"\n") + return n +} + +// Bulletf returns a formatted bullet point string +func Bulletf(msg string, a ...interface{}) string { + return fmt.Sprintf("%s%s\n", bulletText, fmt.Sprintf(msg, a...)) +} + +// Bullet prints a formatted bullet point string +func Bullet(msg string, a ...interface{}) int { + return Print(Bulletf(msg, a...)) +} + +// Stepf returns a formatted step string +func Stepf(msg string, a ...interface{}) string { + return fmt.Sprintf("%s%s\033[0m\n", boldGreen, fmt.Sprintf(msg, a...)) +} + +// Step prints a step title +func Step(msg string, a ...interface{}) int { + return Print(Stepf(msg, a...)) +} + +// Successf returns a formatted success string +func Successf(msg string, a ...interface{}) string { + return fmt.Sprintf("%s%s\n", successText, fmt.Sprintf(msg, a...)) +} + +// Success prints a formatted success message to stdout +func Success(msg string, a ...interface{}) int { + return Print(Successf(msg, a...)) +} + +// Warningf returns a formatted warning string +func Warningf(msg string, a ...interface{}) string { + return fmt.Sprintf("%s%s\n", warningText, fmt.Sprintf(msg, a...)) +} + +// Warning prints a formatted warning message to stdout +func Warning(msg string, a ...interface{}) int { + return Print(Warningf(msg, a...)) +} + +// Fatalf returns a formatted error message +func Fatalf(msg string, a ...interface{}) string { + return fmt.Sprintf("%s%s\n", errorText, fmt.Sprintf(msg, a...)) +} + +// Fatal is equivalent to Print() followed by a call to os.Exit(1). +func Fatal(msg string, a ...interface{}) { + fmt.Fprint(os.Stderr, Fatalf(msg, a...)) + os.Exit(1) +} diff --git a/pkg/logging/logging_test.go b/pkg/logging/logging_test.go new file mode 100644 index 000000000..b95ee0416 --- /dev/null +++ b/pkg/logging/logging_test.go @@ -0,0 +1,102 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2023 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package logging + +import "testing" + +func TestPrint(t *testing.T) { + msg := "Print message" + wantN := 13 + + gotN := Print(msg) + if gotN != wantN { + t.Errorf("Print() = %v, want %v", gotN, wantN) + } +} + +func TestPrintln(t *testing.T) { + msg := "Print message" + wantN := 14 + gotN := Println(msg) + if gotN != wantN { + t.Errorf("Println() = %v, want %v", gotN, wantN) + } +} + +func TestBulletf(t *testing.T) { + msg := "Bullet message" + want := "\033[1m ⋅ \033[0mBullet message\n" + if got := Bulletf(msg); got != want { + t.Errorf("Bulletf() = %v, want %v", got, want) + } +} + +func TestBullet(t *testing.T) { + msg := "Bullet message" + wantN := 28 + gotN := Bullet(msg) + if gotN != wantN { + t.Errorf("Bullet() = %v, want %v", gotN, wantN) + } +} + +func TestStepf(t *testing.T) { + msg := "Step message" + want := "\033[1;32mStep message\033[0m\n" + if got := Stepf(msg); got != want { + t.Errorf("Stepf() = %v, want %v", got, want) + } +} + +func TestStep(t *testing.T) { + msg := "Step message" + wantN := 24 + gotN := Step(msg) + if gotN != wantN { + t.Errorf("Step() = %v, want %v", gotN, wantN) + } +} + +func TestSuccessf(t *testing.T) { + msg := "Success message" + want := "\033[1;32m ✓ \033[0mSuccess message\n" + if got := Successf(msg); got != want { + t.Errorf("Successf() = %v, want %v", got, want) + } +} + +func TestSuccess(t *testing.T) { + msg := "Success message" + wantN := 32 + gotN := Success(msg) + if gotN != wantN { + t.Errorf("Success() = %v, want %v", gotN, wantN) + } +} + +func TestWarningf(t *testing.T) { + msg := "Warning message" + want := "\033[1;33m ‼ \033[0mWarning message\n" + if got := Warningf(msg); got != want { + t.Errorf("Warningf() = %v, want %v", got, want) + } +} + +func TestWarning(t *testing.T) { + msg := "Warning message" + wantN := 32 + gotN := Warning(msg) + if gotN != wantN { + t.Errorf("Warning() = %v, want %v", gotN, wantN) + } +} + +func TestFatalf(t *testing.T) { + msg := "Error message" + want := "\033[1;31m ✗ Error: \033[0mError message\n" + if got := Fatalf(msg); got != want { + t.Errorf("Fatalf() = %v, want %v", got, want) + } +} diff --git a/pkg/util/tools.go b/pkg/util/tools.go new file mode 100644 index 000000000..1a4ab5248 --- /dev/null +++ b/pkg/util/tools.go @@ -0,0 +1,40 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2023 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package util + +import ( + "encoding/hex" + "os" + "os/exec" + "regexp" + "sort" + "strings" +) + +var isHexa = regexp.MustCompile("^[0-9A-Fa-f]+$") + +// DecodeHex decode a string if it is hexa. +func DecodeHex(str string) string { + if isHexa.MatchString(str) { + bs, _ := hex.DecodeString(str) + return string(bs) + } + return str +} + +// RemoveDuplicate filter out all duplicates from a slice. Also filter out empty string +func RemoveDuplicate[T comparable](inlist []T) []T { + var empty T + list := []T{} + keys := map[T]bool{} + keys[empty] = true + for _, item := range inlist { + if _, ok := keys[item]; !ok { + keys[item] = true + list = append(list, item) + } + } + return list +} diff --git a/pkg/util/tools_test.go b/pkg/util/tools_test.go new file mode 100644 index 000000000..6d4d87f9d --- /dev/null +++ b/pkg/util/tools_test.go @@ -0,0 +1,57 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2023 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package util + +import ( + "reflect" + "testing" +) + +func TestDecodeHex(t *testing.T) { + tests := []struct { + name string + str string + want string + }{ + { + name: "Hexa", + str: "666F6F20626172", + want: "foo bar", + }, + { + name: "Not Hexa", + str: "ALLOWED", + want: "ALLOWED", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := DecodeHex(tt.str); got != tt.want { + t.Errorf("DecodeHex() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestRemoveDuplicate(t *testing.T) { + tests := []struct { + name string + inlist []string + want []string + }{ + { + name: "Duplicate", + inlist: []string{"foo", "bar", "foo", "bar", ""}, + want: []string{"foo", "bar"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := RemoveDuplicate(tt.inlist); !reflect.DeepEqual(got, tt.want) { + t.Errorf("RemoveDuplicate() = %v, want %v", got, tt.want) + } + }) + } +}