From 1f631588ce05f31124c50f78584daadafe01cf4d Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Wed, 14 Oct 2015 19:24:02 +0200 Subject: [PATCH] Support of `--suffix=xxx`, `--keep-beginning` and `--keep-end` (fix #4) --- README.md | 1 + anonuuid.go | 42 +++++++++ anonuuid_test.go | 205 +++++++++++++++++++++++++++++++++++++++++++ cmd/anonuuid/main.go | 15 ++++ 4 files changed, 263 insertions(+) diff --git a/README.md b/README.md index 58b8d9e..c2b8e96 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,7 @@ Using go ### master (unreleased) +* Support of `--suffix=xxx`, `--keep-beginning` and `--keep-end` options ([#4](https://github.com/moul/anonuuid/issues/4)) * Using **party** to stabilize vendor package versions ([#8](https://github.com/moul/anonuuid/issues/8)) * Add homebrew package ([#6](https://github.com/moul/anonuuid/issues/6)) diff --git a/anonuuid.go b/anonuuid.go index f991f04..a3069c6 100644 --- a/anonuuid.go +++ b/anonuuid.go @@ -27,8 +27,17 @@ type AnonUUID struct { // Prefix will be the beginning of all the generated UUIDs Prefix string + // Suffix will be the end of all the generated UUIDs + Suffix string + // AllowNonUUIDInput tells FakeUUID to accept non UUID input string AllowNonUUIDInput bool + + // KeepBeginning tells FakeUUID to let the beginning of the UUID as it is + KeepBeginning bool + + // KeepEnd tells FakeUUID to let the last part of the UUID as it is + KeepEnd bool } // Sanitize takes a string as input and return sanitized string @@ -51,6 +60,14 @@ func (a *AnonUUID) FakeUUID(input string) string { } if _, ok := a.cache[input]; !ok { + if a.KeepBeginning { + a.Prefix = input[:8] + } + + if a.KeepEnd { + a.Suffix = input[36-12:] + } + if a.Prefix != "" { matched, err := regexp.MatchString("^[a-z0-9]+$", a.Prefix) if err != nil || !matched { @@ -58,6 +75,13 @@ func (a *AnonUUID) FakeUUID(input string) string { } } + if a.Suffix != "" { + matched, err := regexp.MatchString("^[a-z0-9]+$", a.Suffix) + if err != nil || !matched { + a.Suffix = "invalsuffix" + } + } + var fakeUUID string var err error if a.Hexspeak { @@ -78,6 +102,13 @@ func (a *AnonUUID) FakeUUID(input string) string { } } + if a.Suffix != "" { + fakeUUID, err = SuffixUUID(a.Suffix, fakeUUID) + if err != nil { + panic(err) + } + } + // FIXME: check for duplicates and retry a.cache[input] = fakeUUID @@ -108,6 +139,17 @@ func PrefixUUID(prefix string, uuid string) (string, error) { return prefixedUUID, nil } +// SuffixUUID returns a suffixed UUID +func SuffixUUID(suffix string, uuid string) (string, error) { + uuidLetters := uuid[:8] + uuid[9:13] + uuid[14:18] + uuid[19:23] + uuid[24:36] + uuidLetters = uuidLetters[:32-len(suffix)] + suffix + suffixedUUID, err := FormatUUID(uuidLetters) + if err != nil { + return "", err + } + return suffixedUUID, nil +} + // IsUUID returns nil if the input is an UUID, else it returns an error func IsUUID(input string) error { matched, err := regexp.MatchString("^"+UUIDRegex+"$", input) diff --git a/anonuuid_test.go b/anonuuid_test.go index bcfa919..250ec3e 100644 --- a/anonuuid_test.go +++ b/anonuuid_test.go @@ -228,6 +228,211 @@ func TestAnonUUID_FakeUUID(t *testing.T) { So(fakeuuid1, ShouldEqual, expected1) So(fakeuuid3, ShouldEqual, expected2) }) + Convey("--suffix=hello", func() { + anonuuid := New() + + anonuuid.Suffix = "hello" + + expected1 := "00000000-0000-1000-0000-0000000hello" + expected2 := "11111111-1111-1111-1111-1111111hello" + + fakeuuid1 := anonuuid.FakeUUID(realuuid1) + fakeuuid2 := anonuuid.FakeUUID(realuuid1) + fakeuuid3 := anonuuid.FakeUUID(realuuid2) + fakeuuid4 := anonuuid.FakeUUID(realuuid2) + fakeuuid5 := anonuuid.FakeUUID(realuuid1) + + So(len(anonuuid.cache), ShouldEqual, 2) + So(fakeuuid1, ShouldEqual, fakeuuid2) + So(fakeuuid1, ShouldEqual, fakeuuid5) + So(fakeuuid3, ShouldEqual, fakeuuid4) + So(fakeuuid2, ShouldNotEqual, fakeuuid3) + So(fakeuuid1, ShouldEqual, expected1) + So(fakeuuid3, ShouldEqual, expected2) + }) + Convey("--suffix=helloworldhello", func() { + anonuuid := New() + + anonuuid.Suffix = "helloworldhello" + + expected1 := "00000000-0000-1000-0hel-loworldhello" + expected2 := "11111111-1111-1111-1hel-loworldhello" + + fakeuuid1 := anonuuid.FakeUUID(realuuid1) + fakeuuid2 := anonuuid.FakeUUID(realuuid1) + fakeuuid3 := anonuuid.FakeUUID(realuuid2) + fakeuuid4 := anonuuid.FakeUUID(realuuid2) + fakeuuid5 := anonuuid.FakeUUID(realuuid1) + + So(len(anonuuid.cache), ShouldEqual, 2) + So(fakeuuid1, ShouldEqual, fakeuuid2) + So(fakeuuid1, ShouldEqual, fakeuuid5) + So(fakeuuid3, ShouldEqual, fakeuuid4) + So(fakeuuid2, ShouldNotEqual, fakeuuid3) + So(fakeuuid1, ShouldEqual, expected1) + So(fakeuuid3, ShouldEqual, expected2) + }) + Convey("--suffix=@@@", func() { + anonuuid := New() + + anonuuid.Suffix = "@@@" + + expected1 := "00000000-0000-1000-0000-0invalsuffix" + expected2 := "11111111-1111-1111-1111-1invalsuffix" + + fakeuuid1 := anonuuid.FakeUUID(realuuid1) + fakeuuid2 := anonuuid.FakeUUID(realuuid1) + fakeuuid3 := anonuuid.FakeUUID(realuuid2) + fakeuuid4 := anonuuid.FakeUUID(realuuid2) + fakeuuid5 := anonuuid.FakeUUID(realuuid1) + + So(len(anonuuid.cache), ShouldEqual, 2) + So(fakeuuid1, ShouldEqual, fakeuuid2) + So(fakeuuid1, ShouldEqual, fakeuuid5) + So(fakeuuid3, ShouldEqual, fakeuuid4) + So(fakeuuid2, ShouldNotEqual, fakeuuid3) + So(fakeuuid1, ShouldEqual, expected1) + So(fakeuuid3, ShouldEqual, expected2) + }) + Convey("--prefix=hello --suffix=hello", func() { + anonuuid := New() + + anonuuid.Prefix = "hello" + anonuuid.Suffix = "hello" + + expected1 := "hello000-0000-1000-0100-0000000hello" + // FIXME: why this ^ ? + expected2 := "hello111-1111-1111-1111-1111111hello" + + fakeuuid1 := anonuuid.FakeUUID(realuuid1) + fakeuuid2 := anonuuid.FakeUUID(realuuid1) + fakeuuid3 := anonuuid.FakeUUID(realuuid2) + fakeuuid4 := anonuuid.FakeUUID(realuuid2) + fakeuuid5 := anonuuid.FakeUUID(realuuid1) + + So(len(anonuuid.cache), ShouldEqual, 2) + So(fakeuuid1, ShouldEqual, fakeuuid2) + So(fakeuuid1, ShouldEqual, fakeuuid5) + So(fakeuuid3, ShouldEqual, fakeuuid4) + So(fakeuuid2, ShouldNotEqual, fakeuuid3) + So(fakeuuid1, ShouldEqual, expected1) + So(fakeuuid3, ShouldEqual, expected2) + }) + Convey("--prefix=helloworldhello --suffix=helloworldhello", func() { + anonuuid := New() + + anonuuid.Prefix = "helloworldhello" + anonuuid.Suffix = "helloworldhello" + + expected1 := "hellowor-ldhe-1lo0-0hel-loworldhello" + // FIXME: should not do this :) + expected2 := "hellowor-ldhe-1lo1-1hel-loworldhello" + // FIXME: should not do this :) + + fakeuuid1 := anonuuid.FakeUUID(realuuid1) + fakeuuid2 := anonuuid.FakeUUID(realuuid1) + fakeuuid3 := anonuuid.FakeUUID(realuuid2) + fakeuuid4 := anonuuid.FakeUUID(realuuid2) + fakeuuid5 := anonuuid.FakeUUID(realuuid1) + + So(len(anonuuid.cache), ShouldEqual, 2) + So(fakeuuid1, ShouldEqual, fakeuuid2) + So(fakeuuid1, ShouldEqual, fakeuuid5) + So(fakeuuid3, ShouldEqual, fakeuuid4) + So(fakeuuid2, ShouldNotEqual, fakeuuid3) + So(fakeuuid1, ShouldEqual, expected1) + So(fakeuuid3, ShouldEqual, expected2) + }) + Convey("--prefix=helloworldhello --suffix=@@@", func() { + anonuuid := New() + + anonuuid.Prefix = "@@@" + anonuuid.Suffix = "@@@" + + expected1 := "invalidp-refi-1000-0000-0invalsuffix" + expected2 := "invalidp-refi-1111-1111-1invalsuffix" + + fakeuuid1 := anonuuid.FakeUUID(realuuid1) + fakeuuid2 := anonuuid.FakeUUID(realuuid1) + fakeuuid3 := anonuuid.FakeUUID(realuuid2) + fakeuuid4 := anonuuid.FakeUUID(realuuid2) + fakeuuid5 := anonuuid.FakeUUID(realuuid1) + + So(len(anonuuid.cache), ShouldEqual, 2) + So(fakeuuid1, ShouldEqual, fakeuuid2) + So(fakeuuid1, ShouldEqual, fakeuuid5) + So(fakeuuid3, ShouldEqual, fakeuuid4) + So(fakeuuid2, ShouldNotEqual, fakeuuid3) + So(fakeuuid1, ShouldEqual, expected1) + So(fakeuuid3, ShouldEqual, expected2) + }) + Convey("--keep-beginning", func() { + anonuuid := New() + + anonuuid.KeepBeginning = true + + expected1 := "15573749-0000-1000-0000-100000000000" + expected2 := "c245c3cb-1111-1111-1111-111111111111" + + fakeuuid1 := anonuuid.FakeUUID(realuuid1) + fakeuuid2 := anonuuid.FakeUUID(realuuid1) + fakeuuid3 := anonuuid.FakeUUID(realuuid2) + fakeuuid4 := anonuuid.FakeUUID(realuuid2) + fakeuuid5 := anonuuid.FakeUUID(realuuid1) + + So(len(anonuuid.cache), ShouldEqual, 2) + So(fakeuuid1, ShouldEqual, fakeuuid2) + So(fakeuuid1, ShouldEqual, fakeuuid5) + So(fakeuuid3, ShouldEqual, fakeuuid4) + So(fakeuuid2, ShouldNotEqual, fakeuuid3) + So(fakeuuid1, ShouldEqual, expected1) + So(fakeuuid3, ShouldEqual, expected2) + }) + Convey("--keep-end", func() { + anonuuid := New() + + anonuuid.KeepEnd = true + + expected1 := "00000000-0000-1000-0000-16e79bed52e0" + expected2 := "11111111-1111-1111-1111-70cb1fe4eefe" + + fakeuuid1 := anonuuid.FakeUUID(realuuid1) + fakeuuid2 := anonuuid.FakeUUID(realuuid1) + fakeuuid3 := anonuuid.FakeUUID(realuuid2) + fakeuuid4 := anonuuid.FakeUUID(realuuid2) + fakeuuid5 := anonuuid.FakeUUID(realuuid1) + + So(len(anonuuid.cache), ShouldEqual, 2) + So(fakeuuid1, ShouldEqual, fakeuuid2) + So(fakeuuid1, ShouldEqual, fakeuuid5) + So(fakeuuid3, ShouldEqual, fakeuuid4) + So(fakeuuid2, ShouldNotEqual, fakeuuid3) + So(fakeuuid1, ShouldEqual, expected1) + So(fakeuuid3, ShouldEqual, expected2) + }) + Convey("--keep-beginning --keep-end", func() { + anonuuid := New() + + anonuuid.KeepBeginning = true + anonuuid.KeepEnd = true + + expected1 := "15573749-0000-1000-0000-16e79bed52e0" + expected2 := "c245c3cb-1111-1111-1111-70cb1fe4eefe" + + fakeuuid1 := anonuuid.FakeUUID(realuuid1) + fakeuuid2 := anonuuid.FakeUUID(realuuid1) + fakeuuid3 := anonuuid.FakeUUID(realuuid2) + fakeuuid4 := anonuuid.FakeUUID(realuuid2) + fakeuuid5 := anonuuid.FakeUUID(realuuid1) + + So(len(anonuuid.cache), ShouldEqual, 2) + So(fakeuuid1, ShouldEqual, fakeuuid2) + So(fakeuuid1, ShouldEqual, fakeuuid5) + So(fakeuuid3, ShouldEqual, fakeuuid4) + So(fakeuuid2, ShouldNotEqual, fakeuuid3) + So(fakeuuid1, ShouldEqual, expected1) + So(fakeuuid3, ShouldEqual, expected2) + }) Convey("--hexspeak", func() { anonuuid := New() diff --git a/cmd/anonuuid/main.go b/cmd/anonuuid/main.go index 8ad770c..1d9119b 100644 --- a/cmd/anonuuid/main.go +++ b/cmd/anonuuid/main.go @@ -28,10 +28,22 @@ func main() { Name: "random, r", Usage: "Generate random fake UUIDs", }, + cli.BoolFlag{ + Name: "keep-beginning", + Usage: "Keep first part of the UUID unchanged", + }, + cli.BoolFlag{ + Name: "keep-end", + Usage: "Keep last part of the UUID unchanged", + }, cli.StringFlag{ Name: "prefix, p", Usage: "Prefix generated UUIDs", }, + cli.StringFlag{ + Name: "suffix", + Usage: "Suffix generated UUIDs", + }, } app.Action = action @@ -46,6 +58,9 @@ func action(c *cli.Context) { anonuuid.Hexspeak = c.Bool("hexspeak") anonuuid.Random = c.Bool("random") anonuuid.Prefix = c.String("prefix") + anonuuid.Suffix = c.String("suffix") + anonuuid.KeepBeginning = c.Bool("keep-beginning") + anonuuid.KeepEnd = c.Bool("keep-end") for scanner.Scan() { line := scanner.Text()