Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NEOS-343: tranformer methods to function init #617

Merged
merged 15 commits into from
Nov 21, 2023
Merged
1 change: 0 additions & 1 deletion docs/docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ const config = {
respectPrefersColorScheme: false,
},
navbar: {
// title: 'Neosync',
logo: {
alt: 'Neosync',
srcDark: 'img/logo_and_text_dark_mode.png',
Expand Down
3 changes: 2 additions & 1 deletion worker/internal/benthos/transformers/card_number.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,13 @@ func GenerateValidLuhnCheckCardNumber() (int64, error) {
// append the checksum to the card number
cardNum = append(cardNum, checkSum)

// convert the card number to a string
// convert the card number to a string to build the card number format
cardNumStr := ""
for _, d := range cardNum {
cardNumStr += fmt.Sprintf("%d", d)
}

// convert the card number back to an int to return it
cardNumInt, err := strconv.ParseInt(cardNumStr, 10, 64)
if err != nil {
return 0, err
Expand Down
110 changes: 75 additions & 35 deletions worker/internal/benthos/transformers/email.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,51 @@
func init() {

spec := bloblang.NewPluginSpec().
Param(bloblang.NewBoolParam("preserve_length")).
Param(bloblang.NewBoolParam("preserve_domain"))
Param(bloblang.NewStringParam("email").Optional()).
Param(bloblang.NewBoolParam("preserve_length").Optional()).
Param(bloblang.NewBoolParam("preserve_domain").Optional())

// register the plugin
err := bloblang.RegisterMethodV2("emailtransformer", spec, func(args *bloblang.ParsedParams) (bloblang.Method, error) {
err := bloblang.RegisterFunctionV2("emailtransformer", spec, func(args *bloblang.ParsedParams) (bloblang.Function, error) {

preserveLength, err := args.GetBool("preserve_length")
// optional params return a pointer

emailPtr, err := args.GetOptionalString("email")
if err != nil {
return nil, err
}

Check warning on line 29 in worker/internal/benthos/transformers/email.go

View check run for this annotation

Codecov / codecov/patch

worker/internal/benthos/transformers/email.go#L28-L29

Added lines #L28 - L29 were not covered by tests

// check if pointer is nil aka the param is not set
var email string
if emailPtr != nil {
email = *emailPtr
}

preserveLengthPtr, err := args.GetOptionalBool("preserve_length")
if err != nil {
return nil, err
}

preserveDomain, err := args.GetBool("preserve_domain")
var preserveLength bool
if preserveLengthPtr != nil {
preserveLength = *preserveLengthPtr
}

preserveDomainPtr, err := args.GetOptionalBool("preserve_domain")
if err != nil {
return nil, err
}

return bloblang.StringMethod(func(e string) (any, error) {
var preserveDomain bool
if preserveDomainPtr != nil {
preserveDomain = *preserveDomainPtr
}

res, err := GenerateEmail(e, preserveLength, preserveDomain)
return func() (any, error) {

res, err := GenerateEmail(email, preserveLength, preserveDomain)
return res, err
}), nil
}, nil

})

if err != nil {
Expand All @@ -44,52 +68,70 @@

}

// generates a random email address
func GenerateEmail(e string, preserveLength, preserveDomain bool) (string, error) {
func GenerateEmail(email string, preserveLength, preserveDomain bool) (string, error) {

var returnValue string
var err error

if !preserveLength && preserveDomain {
if email != "" {
if !preserveLength && preserveDomain {

returnValue, err = GenerateEmailPreserveDomain(e, true)
if err != nil {
return "", err
}
returnValue, err = GenerateEmailPreserveDomain(email, true)
if err != nil {
return "", err
}

Check warning on line 82 in worker/internal/benthos/transformers/email.go

View check run for this annotation

Codecov / codecov/patch

worker/internal/benthos/transformers/email.go#L79-L82

Added lines #L79 - L82 were not covered by tests

} else if preserveLength && !preserveDomain {
} else if preserveLength && !preserveDomain {

returnValue, err = GenerateEmailPreserveLength(e, true)
if err != nil {
return "", err
}
returnValue, err = GenerateEmailPreserveLength(email, true)
if err != nil {
return "", err
}

Check warning on line 89 in worker/internal/benthos/transformers/email.go

View check run for this annotation

Codecov / codecov/patch

worker/internal/benthos/transformers/email.go#L88-L89

Added lines #L88 - L89 were not covered by tests

} else if preserveLength && preserveDomain {
} else if preserveLength && preserveDomain {

returnValue, err = GenerateEmailPreserveDomainAndLength(e, true, true)
if err != nil {
return "", err
}
returnValue, err = GenerateEmailPreserveDomainAndLength(email, true, true)
if err != nil {
return "", err
}

Check warning on line 96 in worker/internal/benthos/transformers/email.go

View check run for this annotation

Codecov / codecov/patch

worker/internal/benthos/transformers/email.go#L95-L96

Added lines #L95 - L96 were not covered by tests

} else {
} else {
e, err := GenerateRandomEmail()
if err != nil {
return "", nil
}

Check warning on line 102 in worker/internal/benthos/transformers/email.go

View check run for this annotation

Codecov / codecov/patch

worker/internal/benthos/transformers/email.go#L101-L102

Added lines #L101 - L102 were not covered by tests

un, err := GenerateRandomUsername()
if err != nil {
return "", nil
returnValue = e
}

domain, err := GenerateDomain()
} else {

e, err := GenerateRandomEmail()
if err != nil {
return "", nil
}

// generate random email
returnValue = un + domain
returnValue = e
}

return returnValue, nil
}

func GenerateRandomEmail() (string, error) {
un, err := GenerateRandomUsername()
if err != nil {
return "", nil
}

Check warning on line 124 in worker/internal/benthos/transformers/email.go

View check run for this annotation

Codecov / codecov/patch

worker/internal/benthos/transformers/email.go#L123-L124

Added lines #L123 - L124 were not covered by tests

domain, err := GenerateDomain()
if err != nil {
return "", nil
}

Check warning on line 129 in worker/internal/benthos/transformers/email.go

View check run for this annotation

Codecov / codecov/patch

worker/internal/benthos/transformers/email.go#L128-L129

Added lines #L128 - L129 were not covered by tests

// generate random email
return un + domain, err
}

// Generate a random email and preserve the input email's domain
func GenerateEmailPreserveDomain(e string, pd bool) (string, error) {

Expand Down Expand Up @@ -167,7 +209,6 @@
var result string

domain, err := transformer_utils.GenerateRandomStringWithLength(6)

if err != nil {
return "", fmt.Errorf("unable to generate random domain name")
}
Expand Down Expand Up @@ -203,7 +244,6 @@

inputEmail, err := mail.ParseAddress(email)
if err != nil {

return nil, fmt.Errorf("invalid email format: %s", email)
}

Expand Down
101 changes: 87 additions & 14 deletions worker/internal/benthos/transformers/email_test.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package neosync_transformers

import (
"fmt"
"regexp"
"strings"
"testing"

"github.com/benthosdev/benthos/v4/public/bloblang"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)

const email = "[email protected]"

func TestGenerateEmail(t *testing.T) {
func Test_GenerateEmail(t *testing.T) {

res, err := GenerateEmailPreserveDomain(email, true)

Expand All @@ -22,7 +24,7 @@ func TestGenerateEmail(t *testing.T) {
assert.Equal(t, true, isValidEmail(res), "true", "The domain should not explicitly be preserved but randomly generated.")
}

func TestGenerateEmailPreserveDomain(t *testing.T) {
func Test_GenerateEmailPreserveDomain(t *testing.T) {

res, err := GenerateEmailPreserveDomain(email, true)

Expand All @@ -33,15 +35,15 @@ func TestGenerateEmailPreserveDomain(t *testing.T) {
assert.Equal(t, true, isValidEmail(res), "true", "The domain should not explicitly be preserved but randomly generated.")
}

func TestGenerateEmailPreserveLength(t *testing.T) {
func Test_GenerateEmailPreserveLength(t *testing.T) {

res, err := GenerateEmailPreserveLength(email, true)

assert.NoError(t, err)
assert.Equal(t, len(email), len(res), "The length of the emails should be the same")
}

func TestGenerateEmailPreserveLengthTruePreserveDomainTrue(t *testing.T) {
func Test_GenerateEmailPreserveLengthTruePreserveDomainTrue(t *testing.T) {
email := "[email protected]"

res, err := GenerateEmailPreserveDomainAndLength(email, true, true)
Expand All @@ -51,7 +53,7 @@ func TestGenerateEmailPreserveLengthTruePreserveDomainTrue(t *testing.T) {

}

func TestGenerateEmailPreserveLengthFalsePreserveDomainFalse(t *testing.T) {
func Test_GenerateEmailPreserveLengthFalsePreserveDomainFalse(t *testing.T) {
email := "[email protected]"

res, err := GenerateEmail(email, false, false)
Expand All @@ -61,38 +63,95 @@ func TestGenerateEmailPreserveLengthFalsePreserveDomainFalse(t *testing.T) {

}

func TestGenerateDomain(t *testing.T) {
func Test_GenerateDomain(t *testing.T) {

res, err := GenerateDomain()
assert.NoError(t, err)

assert.Equal(t, true, IsValidDomain(res))
assert.Equal(t, true, IsValidDomain(res), "The expected email should have a valid domain")

}

func TestGenerateUsername(t *testing.T) {
func Test_GenerateUsername(t *testing.T) {

res, err := GenerateRandomUsername()
assert.NoError(t, err)

assert.Equal(t, true, IsValidUsername(res))
assert.Equal(t, true, IsValidUsername(res), "The expected email should have a valid username")

}

func TestEmailTransformer(t *testing.T) {
mapping := `root = this.emailtransformer(true, true)`
ex, err := bloblang.Parse(mapping)
assert.NoError(t, err, "failed to parse the email transformer")
func Test_GenerateRandomEmail(t *testing.T) {
res, err := GenerateRandomEmail()

assert.NoError(t, err)
assert.Equal(t, true, isValidEmail(res), "The expected email should be have a valid email structure")
}

func Test_EmailTransformerWithValue(t *testing.T) {
testVal := "[email protected]"
mapping := fmt.Sprintf(`root = emailtransformer(%q,true,true)`, testVal)
ex, err := bloblang.Parse(mapping)
assert.NoError(t, err, "failed to parse the email transformer")

res, err := ex.Query(testVal)
res, err := ex.Query(nil)
assert.NoError(t, err)

assert.Len(t, res.(string), len(testVal), "Generated email must be the same length as the input email")
assert.Equal(t, strings.Split(res.(string), "@")[1], "gmail.com")
}

func Test_EmailTransformerWithEmptyValue(t *testing.T) {
mapping := `root = emailtransformer()`
ex, err := bloblang.Parse(mapping)
assert.NoError(t, err, "failed to parse the email transformer")

res, err := ex.Query(nil)
assert.NoError(t, err)

assert.Equal(t, true, isValidEmail(res.(string)))
}

// testing that even if some params are passed, as long as the email param is passed, it'll generate the right value
func Test_EmailTransformerWithMissingParams(t *testing.T) {
testVal := "[email protected]"
mapping := fmt.Sprintf(`root = emailtransformer(%q,true)`, testVal)
ex, err := bloblang.Parse(mapping)
assert.NoError(t, err, "failed to parse the email transformer")

res, err := ex.Query(nil)
assert.NoError(t, err)

assert.Equal(t, true, isValidEmail(res.(string)))
}

// testing that even if some params are passed, as long as the email param isn't passed, it'll always generate a random value
// Note: that if the args aren't named then it will fail, see the test below
func Test_EmailTransformerWithEmptyValueButSomeNamedParams(t *testing.T) {
mapping := `root = emailtransformer(preserve_length: true,preserve_domain: false)`
ex, err := bloblang.Parse(mapping)
assert.NoError(t, err, "failed to parse the email transformer")

res, err := ex.Query(nil)
assert.NoError(t, err)

assert.Equal(t, true, isValidEmail(res.(string)))
}

func Test_EmailTransformerWithEmptyValueButSomeUnnamedParams(t *testing.T) {
mapping := `root = emailtransformer(true, false)`
_, err := bloblang.Parse(mapping)
assert.Error(t, err, "failed to parse the email transformer")
}

func Test_ParseEmailError(t *testing.T) {
test := "ehiu.com"

_, err := parseEmail(test)
assert.Error(t, err)

}

func isValidEmail(email string) bool {
// Regular expression pattern for a simple email validation
emailPattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`
Expand Down Expand Up @@ -125,3 +184,17 @@ func IsValidUsername(domain string) bool {
// Use the regex pattern to validate the email
return re.MatchString(domain)
}

type MockParsedParams struct {
mock.Mock
}

func (m *MockParsedParams) GetString(key string) (string, error) {
args := m.Called(key)
return args.String(0), args.Error(1)
}

func (m *MockParsedParams) GetBool(key string) (bool, error) {
args := m.Called(key)
return args.Bool(0), args.Error(1)
}
Loading
Loading