Merge pull request #4 from wneessen/dev

Dev
This commit is contained in:
Winni Neessen 2021-03-22 17:55:25 +01:00 committed by GitHub
commit 9bda7a37d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 146 deletions

101
Makefile
View file

@ -1,101 +0,0 @@
# The binaries to build (just the basenames).
BINS := apg
VERSION ?= $(shell grep VersionString apg.go | head -1 | awk '{print $$5}' | sed 's/"//g')
ALL_PLATFORMS := darwin/amd64 darwin/arm64 \
linux/amd64 linux/arm linux/arm64 linux/ppc64le linux/s390x \
freebsd/386 freebsd/amd64 freebsd/arm \
openbsd/386 openbsd/amd64 openbsd/arm \
netbsd/386 netbsd/amd64 netbsd/arm \
windows/386 windows/amd64
OS := $(if $(GOOS),$(GOOS),$(shell go env GOOS))
ARCH := $(if $(GOARCH),$(GOARCH),$(shell go env GOARCH))
TAG := $(VERSION)__$(OS)_$(ARCH)
BIN_EXTENSION :=
ifeq ($(OS), windows)
BIN_EXTENSION := .exe
endif
# If you want to build all binaries, see the 'all-build' rule.
all: # @HELP builds binaries for one platform ($OS/$ARCH)
all: build
# For the following OS/ARCH expansions, we transform OS/ARCH into OS_ARCH
# because make pattern rules don't match with embedded '/' characters.
build-%:
@$(MAKE) build \
--no-print-directory \
GOOS=$(firstword $(subst _, ,$*)) \
GOARCH=$(lastword $(subst _, ,$*))
all-build: # @HELP builds binaries for all platforms
all-build: $(addprefix build-, $(subst /,_, $(ALL_PLATFORMS)))
OUTBINS = $(foreach bin,$(BINS),bin/v$(VERSION)/$(OS)_$(ARCH)/$(bin)$(BIN_EXTENSION))
build: $(OUTBINS)
BUILD_DIRS := bin/v$(VERSION)/$(OS)_$(ARCH) \
bin/zip-files/v$(VERSION) \
.go/bin/v$(VERSION)/$(OS)_$(ARCH) \
.go/cache
# Each outbin target is just a facade for the respective stampfile target.
# This `eval` establishes the dependencies for each.
$(foreach outbin,$(OUTBINS),$(eval \
$(outbin): .go/$(outbin).stamp \
))
# This is the target definition for all outbins.
$(OUTBINS):
@true
# Each stampfile target can reference an $(OUTBIN) variable.
$(foreach outbin,$(OUTBINS),$(eval $(strip \
.go/$(outbin).stamp: OUTBIN = $(outbin) \
)))
# This is the target definition for all stampfiles.
# This will build the binary under ./.go and update the real binary iff needed.
STAMPS = $(foreach outbin,$(OUTBINS),.go/$(outbin).stamp)
.PHONY: $(STAMPS)
$(STAMPS): go-build
@echo "binary: $(OUTBIN)"
@if ! cmp -s .go/$(OUTBIN) $(OUTBIN); then \
mv .go/$(OUTBIN) $(OUTBIN); \
zip -9 ./bin/zip-files/v$(VERSION)/apg_v$(VERSION)_$(OS)_$(ARCH).zip $(OUTBIN) \
date >$@; \
fi
# This runs the actual `go build` which updates all binaries.
go-build: $(BUILD_DIRS)
@echo
@echo "building for $(OS)/$(ARCH)"
@go build -o .go/bin/v$(VERSION)/$(OS)_$(ARCH)/apg$(BIN_EXTENSION) apg.go
version: # @HELP outputs the version string
version:
@echo $(VERSION)
"
$(BUILD_DIRS):
@mkdir -p $@
clean: # @HELP removes built binaries and temporary files
clean: bin-clean
bin-clean:
rm -rf .go bin *.exe
help: # @HELP prints this message
help:
@echo "VARIABLES:"
@echo " BINS = $(BINS)"
@echo " OS = $(OS)"
@echo " ARCH = $(ARCH)"
@echo " REGISTRY = $(REGISTRY)"
@echo
@echo "TARGETS:"
@grep -E '^.*: *# *@HELP' $(MAKEFILE_LIST) \
| awk ' \
BEGIN {FS = ": *# *@HELP"}; \
{ printf " %-30s %s\n", $$1, $$2 }; \
'

14
apg.go
View file

@ -3,12 +3,13 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"log"
"os" "os"
) )
// Constants // Constants
const DefaultPwLenght int = 20 const DefaultPwLenght int = 20
const VersionString string = "0.2.5" const VersionString string = "0.2.6"
const PwLowerCharsHuman string = "abcdefghjkmnpqrstuvwxyz" const PwLowerCharsHuman string = "abcdefghjkmnpqrstuvwxyz"
const PwUpperCharsHuman string = "ABCDEFGHJKMNPQRSTUVWXYZ" const PwUpperCharsHuman string = "ABCDEFGHJKMNPQRSTUVWXYZ"
const PwLowerChars string = "abcdefghijklmnopqrstuvwxyz" const PwLowerChars string = "abcdefghijklmnopqrstuvwxyz"
@ -63,9 +64,11 @@ func init() {
flag.Parse() flag.Parse()
if config.showVersion { if config.showVersion {
_, _ = os.Stderr.WriteString("Winni's Advanced Password Generator Clone (apg.go) v" + VersionString + "\n") _, _ = os.Stderr.WriteString("Winni's Advanced Password Generator Clone (apg.go) v" + VersionString + "\n")
_, _ = os.Stderr.WriteString("© 2021 by Winni Neessen\n") _, _ = os.Stderr.WriteString("(C) 2021 by Winni Neessen\n")
os.Exit(0) os.Exit(0)
} }
log.SetFlags(log.Ltime | log.Ldate | log.Lshortfile)
} }
// Main function that generated the passwords and returns them // Main function that generated the passwords and returns them
@ -77,8 +80,7 @@ func main() {
for i := 1; i <= config.numOfPass; i++ { for i := 1; i <= config.numOfPass; i++ {
pwString, err := getRandChar(&charRange, pwLength) pwString, err := getRandChar(&charRange, pwLength)
if err != nil { if err != nil {
fmt.Printf("getRandChar returned an error: %q\n", err.Error()) log.Fatalf("getRandChar returned an error: %q\n", err)
os.Exit(1)
} }
switch config.outputMode { switch config.outputMode {
@ -86,10 +88,10 @@ func main() {
{ {
spelledPw, err := spellPasswordString(pwString) spelledPw, err := spellPasswordString(pwString)
if err != nil { if err != nil {
fmt.Printf("spellPasswordString returned an error: %q\n", err.Error()) log.Fatalf("spellPasswordString returned an error: %q\n", err.Error())
os.Exit(1)
} }
fmt.Printf("%v (%v)\n", pwString, spelledPw) fmt.Printf("%v (%v)\n", pwString, spelledPw)
break
} }
default: default:
{ {

View file

@ -16,31 +16,31 @@ func TestGetRandNum(t *testing.T) {
t.Run("maxNum_is_1000", func(t *testing.T) { t.Run("maxNum_is_1000", func(t *testing.T) {
randNum, err := getRandNum(1000) randNum, err := getRandNum(1000)
if err != nil { if err != nil {
t.Errorf("Random number generation failed: %v", err.Error()) t.Fatalf("Random number generation failed: %v", err.Error())
} }
if randNum > 1000 { if randNum > 1000 {
t.Errorf("Generated random number between 0 and 1000 is too big: %v", randNum) t.Fatalf("Generated random number between 0 and 1000 is too big: %v", randNum)
} }
if randNum < 0 { if randNum < 0 {
t.Errorf("Generated random number between 0 and 1000 is too small: %v", randNum) t.Fatalf("Generated random number between 0 and 1000 is too small: %v", randNum)
} }
}) })
t.Run("maxNum_is_1", func(t *testing.T) { t.Run("maxNum_is_1", func(t *testing.T) {
randNum, err := getRandNum(1) randNum, err := getRandNum(1)
if err != nil { if err != nil {
t.Errorf("Random number generation failed: %v", err.Error()) t.Fatalf("Random number generation failed: %v", err.Error())
} }
if randNum > 1 { if randNum > 1 {
t.Errorf("Generated random number between 0 and 1000 is too big: %v", randNum) t.Fatalf("Generated random number between 0 and 1000 is too big: %v", randNum)
} }
if randNum < 0 { if randNum < 0 {
t.Errorf("Generated random number between 0 and 1000 is too small: %v", randNum) t.Fatalf("Generated random number between 0 and 1000 is too small: %v", randNum)
} }
}) })
t.Run("maxNum_is_0", func(t *testing.T) { t.Run("maxNum_is_0", func(t *testing.T) {
randNum, err := getRandNum(0) randNum, err := getRandNum(0)
if err == nil { if err == nil {
t.Errorf("Random number expected to fail, but provided a value instead: %v", randNum) t.Fatalf("Random number expected to fail, but provided a value instead: %v", randNum)
} }
}) })
} }
@ -51,10 +51,10 @@ func TestGetRandChar(t *testing.T) {
charRange := "ABC" charRange := "ABC"
randChar, err := getRandChar(&charRange, 1) randChar, err := getRandChar(&charRange, 1)
if err != nil { if err != nil {
t.Errorf("Random character generation failed => %v", err.Error()) t.Fatalf("Random character generation failed => %v", err.Error())
} }
if randChar != "A" && randChar != "B" && randChar != "C" { if randChar != "A" && randChar != "B" && randChar != "C" {
t.Errorf("Random character generation failed. Expected A, B or C but got: %v", randChar) t.Fatalf("Random character generation failed. Expected A, B or C but got: %v", randChar)
} }
}) })
@ -62,10 +62,10 @@ func TestGetRandChar(t *testing.T) {
charRange := "ABC" charRange := "ABC"
randChar, err := getRandChar(&charRange, 1000) randChar, err := getRandChar(&charRange, 1000)
if err != nil { if err != nil {
t.Errorf("Random character generation failed => %v", err.Error()) t.Fatalf("Random character generation failed => %v", err.Error())
} }
if len(randChar) != 1000 { if len(randChar) != 1000 {
t.Errorf("Generated random characters with 1000 chars returned wrong amount of chars: %v", t.Fatalf("Generated random characters with 1000 chars returned wrong amount of chars: %v",
len(randChar)) len(randChar))
} }
}) })
@ -74,7 +74,7 @@ func TestGetRandChar(t *testing.T) {
charRange := "ABC" charRange := "ABC"
randChar, err := getRandChar(&charRange, -2000) randChar, err := getRandChar(&charRange, -2000)
if err == nil { if err == nil {
t.Errorf("Generated random characters expected to fail, but returned a value => %v", t.Fatalf("Generated random characters expected to fail, but returned a value => %v",
randChar) randChar)
} }
}) })
@ -96,7 +96,7 @@ func TestGetCharRange(t *testing.T) {
for _, curChar := range charRange { for _, curChar := range charRange {
searchAllowedBytes := containsByte(allowedBytes, int(curChar)) searchAllowedBytes := containsByte(allowedBytes, int(curChar))
if !searchAllowedBytes { if !searchAllowedBytes {
t.Errorf("Character range for lower-case only returned invalid value: %v", t.Fatalf("Character range for lower-case only returned invalid value: %v",
string(curChar)) string(curChar))
} }
} }
@ -115,7 +115,7 @@ func TestGetCharRange(t *testing.T) {
for _, curChar := range charRange { for _, curChar := range charRange {
searchAllowedBytes := containsByte(allowedBytes, int(curChar)) searchAllowedBytes := containsByte(allowedBytes, int(curChar))
if !searchAllowedBytes { if !searchAllowedBytes {
t.Errorf("Character range for lower-case only (human readable) returned invalid value: %v", t.Fatalf("Character range for lower-case only (human readable) returned invalid value: %v",
string(curChar)) string(curChar))
} }
} }
@ -134,7 +134,7 @@ func TestGetCharRange(t *testing.T) {
for _, curChar := range charRange { for _, curChar := range charRange {
searchAllowedBytes := containsByte(allowedBytes, int(curChar)) searchAllowedBytes := containsByte(allowedBytes, int(curChar))
if !searchAllowedBytes { if !searchAllowedBytes {
t.Errorf("Character range for upper-case only returned invalid value: %v", t.Fatalf("Character range for upper-case only returned invalid value: %v",
string(curChar)) string(curChar))
} }
} }
@ -153,7 +153,7 @@ func TestGetCharRange(t *testing.T) {
for _, curChar := range charRange { for _, curChar := range charRange {
searchAllowedBytes := containsByte(allowedBytes, int(curChar)) searchAllowedBytes := containsByte(allowedBytes, int(curChar))
if !searchAllowedBytes { if !searchAllowedBytes {
t.Errorf("Character range for upper-case only (human readable) returned invalid value: %v", t.Fatalf("Character range for upper-case only (human readable) returned invalid value: %v",
string(curChar)) string(curChar))
} }
} }
@ -171,7 +171,7 @@ func TestGetCharRange(t *testing.T) {
for _, curChar := range charRange { for _, curChar := range charRange {
searchAllowedBytes := containsByte(allowedBytes, int(curChar)) searchAllowedBytes := containsByte(allowedBytes, int(curChar))
if !searchAllowedBytes { if !searchAllowedBytes {
t.Errorf("Character range for numbers only returned invalid value: %v", t.Fatalf("Character range for numbers only returned invalid value: %v",
string(curChar)) string(curChar))
} }
} }
@ -189,7 +189,7 @@ func TestGetCharRange(t *testing.T) {
for _, curChar := range charRange { for _, curChar := range charRange {
searchAllowedBytes := containsByte(allowedBytes, int(curChar)) searchAllowedBytes := containsByte(allowedBytes, int(curChar))
if !searchAllowedBytes { if !searchAllowedBytes {
t.Errorf("Character range for numbers (human readable) only returned invalid value: %v", t.Fatalf("Character range for numbers (human readable) only returned invalid value: %v",
string(curChar)) string(curChar))
} }
} }
@ -208,7 +208,7 @@ func TestGetCharRange(t *testing.T) {
for _, curChar := range charRange { for _, curChar := range charRange {
searchAllowedBytes := containsByte(allowedBytes, int(curChar)) searchAllowedBytes := containsByte(allowedBytes, int(curChar))
if !searchAllowedBytes { if !searchAllowedBytes {
t.Errorf("Character range for special characters only returned invalid value: %v", t.Fatalf("Character range for special characters only returned invalid value: %v",
string(curChar)) string(curChar))
} }
} }
@ -226,7 +226,7 @@ func TestGetCharRange(t *testing.T) {
for _, curChar := range charRange { for _, curChar := range charRange {
searchAllowedBytes := containsByte(allowedBytes, int(curChar)) searchAllowedBytes := containsByte(allowedBytes, int(curChar))
if !searchAllowedBytes { if !searchAllowedBytes {
t.Errorf("Character range for special characters only returned invalid value: %v", t.Fatalf("Character range for special characters only returned invalid value: %v",
string(curChar)) string(curChar))
} }
} }
@ -238,37 +238,37 @@ func TestConvert(t *testing.T) {
t.Run("convert_A_to_Alfa", func(t *testing.T) { t.Run("convert_A_to_Alfa", func(t *testing.T) {
charToString, err := convertCharToName('A') charToString, err := convertCharToName('A')
if err != nil { if err != nil {
t.Errorf("Character to string conversion failed: %v", err.Error()) t.Fatalf("Character to string conversion failed: %v", err.Error())
} }
if charToString != "Alfa" { if charToString != "Alfa" {
t.Errorf("Converting 'A' to string did not return the correct value of 'Alfa': %q", charToString) t.Fatalf("Converting 'A' to string did not return the correct value of 'Alfa': %q", charToString)
} }
}) })
t.Run("convert_a_to_alfa", func(t *testing.T) { t.Run("convert_a_to_alfa", func(t *testing.T) {
charToString, err := convertCharToName('a') charToString, err := convertCharToName('a')
if err != nil { if err != nil {
t.Errorf("Character to string conversion failed: %v", err.Error()) t.Fatalf("Character to string conversion failed: %v", err.Error())
} }
if charToString != "alfa" { if charToString != "alfa" {
t.Errorf("Converting 'a' to string did not return the correct value of 'alfa': %q", charToString) t.Fatalf("Converting 'a' to string did not return the correct value of 'alfa': %q", charToString)
} }
}) })
t.Run("convert_0_to_ZERO", func(t *testing.T) { t.Run("convert_0_to_ZERO", func(t *testing.T) {
charToString, err := convertCharToName('0') charToString, err := convertCharToName('0')
if err != nil { if err != nil {
t.Errorf("Character to string conversion failed: %v", err.Error()) t.Fatalf("Character to string conversion failed: %v", err.Error())
} }
if charToString != "ZERO" { if charToString != "ZERO" {
t.Errorf("Converting '0' to string did not return the correct value of 'ZERO': %q", charToString) t.Fatalf("Converting '0' to string did not return the correct value of 'ZERO': %q", charToString)
} }
}) })
t.Run("convert_/_to_SLASH", func(t *testing.T) { t.Run("convert_/_to_SLASH", func(t *testing.T) {
charToString, err := convertCharToName('/') charToString, err := convertCharToName('/')
if err != nil { if err != nil {
t.Errorf("Character to string conversion failed: %v", err.Error()) t.Fatalf("Character to string conversion failed: %v", err.Error())
} }
if charToString != "SLASH" { if charToString != "SLASH" {
t.Errorf("Converting '/' to string did not return the correct value of 'SLASH': %q", charToString) t.Fatalf("Converting '/' to string did not return the correct value of 'SLASH': %q", charToString)
} }
}) })
t.Run("all_chars_convert_to_string", func(t *testing.T) { t.Run("all_chars_convert_to_string", func(t *testing.T) {
@ -281,7 +281,7 @@ func TestConvert(t *testing.T) {
for _, curChar := range charRange { for _, curChar := range charRange {
_, err := convertCharToName(byte(curChar)) _, err := convertCharToName(byte(curChar))
if err != nil { if err != nil {
t.Errorf("Character to string conversion failed: %v", err.Error()) t.Fatalf("Character to string conversion failed: %v", err.Error())
} }
} }
}) })
@ -289,10 +289,10 @@ func TestConvert(t *testing.T) {
pwString := "Ab!" pwString := "Ab!"
spelledString, err := spellPasswordString(pwString) spelledString, err := spellPasswordString(pwString)
if err != nil { if err != nil {
t.Errorf("password spelling failed: %v", err.Error()) t.Fatalf("password spelling failed: %v", err.Error())
} }
if spelledString != "Alfa/bravo/EXCLAMATION_POINT" { if spelledString != "Alfa/bravo/EXCLAMATION_POINT" {
t.Errorf( t.Fatalf(
"Spelling pwString 'Ab!' is expected to provide 'Alfa/bravo/EXCLAMATION_POINT', but returned: %q", "Spelling pwString 'Ab!' is expected to provide 'Alfa/bravo/EXCLAMATION_POINT', but returned: %q",
spelledString) spelledString)
} }
@ -305,14 +305,14 @@ func TestForceFailures(t *testing.T) {
maxNum := 9223372036854775807 maxNum := 9223372036854775807
maxNumBigInt := big.NewInt(int64(maxNum) + 1) maxNumBigInt := big.NewInt(int64(maxNum) + 1)
if maxNumBigInt.IsUint64() { if maxNumBigInt.IsUint64() {
t.Errorf("Calling big.NewInt() with too large number expected to fail: %v", maxNumBigInt) t.Fatalf("Calling big.NewInt() with too large number expected to fail: %v", maxNumBigInt)
} }
}) })
t.Run("negative value for big.NewInt()", func(t *testing.T) { t.Run("negative value for big.NewInt()", func(t *testing.T) {
randNum, err := getRandNum(-20000) randNum, err := getRandNum(-20000)
if err == nil { if err == nil {
t.Errorf("Calling getRandNum() with negative value is expected to fail, but returned value: %v", t.Fatalf("Calling getRandNum() with negative value is expected to fail, but returned value: %v",
randNum) randNum)
} }
}) })

3
go.mod Normal file
View file

@ -0,0 +1,3 @@
module github.com/wneessen/apg.go
go 1.16

View file

@ -1,8 +1,7 @@
package main package main
import ( import (
"fmt" "log"
"os"
) )
// Parse the parameters and set the according config flags // Parse the parameters and set the according config flags
@ -22,8 +21,7 @@ func parseParams() {
config.useLowerCase == false && config.useLowerCase == false &&
config.useNumber == false && config.useNumber == false &&
config.useSpecial == false { config.useSpecial == false {
fmt.Printf("No password mode set. Cannot generate password from empty character set.") log.Fatalf("No password mode set. Cannot generate password from empty character set.")
os.Exit(1)
} }
// Set output mode // Set output mode
@ -90,8 +88,7 @@ func parseNewStyleParams() {
config.useComplex = false config.useComplex = false
break break
default: default:
fmt.Printf("Unknown password style parameter: %q\n", string(curParam)) log.Fatalf("Unknown password style parameter: %q\n", string(curParam))
os.Exit(1)
} }
} }
} }