Skip to content

Commit 469ba92

Browse files
authored
fixes logic in fullname transformer with tests (#3537)
1 parent f1704d4 commit 469ba92

File tree

2 files changed

+216
-2
lines changed

2 files changed

+216
-2
lines changed

worker/pkg/benthos/transformers/transform_full_name.go

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,28 @@ func transformFullName(
119119
maxValue := maxLength
120120

121121
if preserveLength {
122+
if strings.TrimSpace(name) == "" {
123+
// If the input is all spaces, return a string of spaces of the same length
124+
output := strings.Repeat(" ", len(name))
125+
return &output, nil
126+
}
127+
122128
firstname, lastname := splitEvenly(name)
129+
if lastname == "" {
130+
// Single name: generate two names, join with space, pad/truncate
131+
minFirst := int64(1)
132+
minLast := int64(1)
133+
newfirstname, _ := generateRandomFirstName(randomizer, &minFirst, minFirst)
134+
newlastname, _ := generateRandomLastName(randomizer, &minLast, minLast)
135+
fullname := fmt.Sprintf("%s %s", newfirstname, newlastname)
136+
if len(fullname) < len(name) {
137+
fullname += transformer_utils.GetRandomCharacterString(randomizer, int64(len(name)-len(fullname)))
138+
} else if len(fullname) > len(name) {
139+
fullname = fullname[:len(name)]
140+
}
141+
return &fullname, nil
142+
}
143+
123144
minFirst := int64(len(firstname))
124145
newfirstname, _ := generateRandomFirstName(randomizer, &minFirst, minFirst)
125146
if newfirstname == "" {
@@ -131,19 +152,37 @@ func transformFullName(
131152
)
132153
}
133154
}
155+
// Calculate remaining length for last name (accounting for space)
156+
remainingLength := int64(len(name)) - int64(len(newfirstname)) - 1 // -1 for space
157+
if remainingLength < 0 {
158+
remainingLength = 0
159+
}
134160
minLast := int64(len(lastname))
161+
if minLast == 0 {
162+
minLast = remainingLength
163+
}
135164
newlastname, _ := generateRandomLastName(randomizer, &minLast, minLast)
136165
if newlastname == "" {
137-
newfirstname, _ = generateRandomLastName(randomizer, nil, minLast)
166+
newlastname, _ = generateRandomLastName(randomizer, nil, minLast)
138167
if int64(len(newlastname)) != minLast {
139168
newlastname += transformer_utils.GetRandomCharacterString(
140169
randomizer,
141-
minFirst-int64(len(newlastname)),
170+
minLast-int64(len(newlastname)),
142171
)
143172
}
144173
}
145174
if newfirstname != "" && newlastname != "" {
146175
fullname := fmt.Sprintf("%s %s", newfirstname, newlastname)
176+
if int64(len(fullname)) != int64(len(name)) {
177+
if int64(len(fullname)) < int64(len(name)) {
178+
fullname += transformer_utils.GetRandomCharacterString(
179+
randomizer,
180+
int64(len(name))-int64(len(fullname)),
181+
)
182+
} else {
183+
fullname = fullname[:len(name)]
184+
}
185+
}
147186
return &fullname, nil
148187
}
149188
}

worker/pkg/benthos/transformers/transform_full_name_test.go

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package transformers
22

33
import (
44
"fmt"
5+
"strings"
56
"testing"
67

78
"github.com/nucleuscloud/neosync/worker/pkg/rng"
@@ -85,3 +86,177 @@ func Test_TransformFullNamelTransformer_NoOptions(t *testing.T) {
8586
assert.NoError(t, err)
8687
assert.NotEmpty(t, res)
8788
}
89+
90+
func Test_TransformFullNamePreserveLengthSingleName(t *testing.T) {
91+
t.Run("single name with preserve length", func(t *testing.T) {
92+
randomizer := rng.New(1)
93+
singleName := "John"
94+
expectedLength := int64(len(singleName))
95+
96+
// Debug: Let's see what splitEvenly returns
97+
firstname, lastname := splitEvenly(singleName)
98+
t.Logf("splitEvenly('%s') = firstname: '%s' (len: %d), lastname: '%s' (len: %d)",
99+
singleName, firstname, len(firstname), lastname, len(lastname))
100+
101+
res, err := transformFullName(randomizer, singleName, true, maxCharacterLimit)
102+
103+
assert.NoError(t, err)
104+
assert.NotNil(t, res)
105+
t.Logf("Input: '%s' (len: %d), Output: '%s' (len: %d)",
106+
singleName, len(singleName), *res, len(*res))
107+
assert.Equal(t, expectedLength, int64(len(*res)), "The output should be the same length as the input")
108+
assert.Contains(t, *res, " ", "Should contain a space between first and last name")
109+
})
110+
111+
t.Run("single name with preserve length via bloblang", func(t *testing.T) {
112+
singleName := "John"
113+
mapping := fmt.Sprintf(`root = transform_full_name(value:%q,preserve_length:true,max_length:%d)`, singleName, maxCharacterLimit)
114+
ex, err := bloblang.Parse(mapping)
115+
assert.NoError(t, err, "failed to parse the full name transformer")
116+
117+
res, err := ex.Query(singleName)
118+
assert.NoError(t, err)
119+
120+
resStr, ok := res.(*string)
121+
if !ok {
122+
t.Errorf("Expected *string, got %T", res)
123+
return
124+
}
125+
126+
assert.NotNil(t, resStr)
127+
t.Logf("Bloblang Input: '%s' (len: %d), Output: '%s' (len: %d)",
128+
singleName, len(singleName), *resStr, len(*resStr))
129+
assert.Equal(t, len(singleName), len(*resStr), "Generated full name must be as long as input name")
130+
assert.Contains(t, *resStr, " ", "Should contain a space between first and last name")
131+
})
132+
}
133+
134+
func Test_TransformFullNamePreserveLengthShortLastName(t *testing.T) {
135+
t.Run("name with short last name", func(t *testing.T) {
136+
randomizer := rng.New(1)
137+
nameWithShortLastName := "John A"
138+
expectedLength := int64(len(nameWithShortLastName))
139+
140+
res, err := transformFullName(randomizer, nameWithShortLastName, true, maxCharacterLimit)
141+
142+
assert.NoError(t, err)
143+
assert.NotNil(t, res)
144+
assert.Equal(t, expectedLength, int64(len(*res)), "The output should be the same length as the input")
145+
assert.Contains(t, *res, " ", "Should contain a space between first and last name")
146+
})
147+
}
148+
149+
func Test_TransformFullNamePreserveLengthMultipleWords(t *testing.T) {
150+
t.Run("name with multiple words", func(t *testing.T) {
151+
randomizer := rng.New(1)
152+
multiWordName := "John van der Berg"
153+
expectedLength := int64(len(multiWordName))
154+
155+
res, err := transformFullName(randomizer, multiWordName, true, maxCharacterLimit)
156+
157+
assert.NoError(t, err)
158+
assert.NotNil(t, res)
159+
assert.Equal(t, expectedLength, int64(len(*res)), "The output should be the same length as the input")
160+
assert.Contains(t, *res, " ", "Should contain spaces between name parts")
161+
})
162+
}
163+
164+
func Test_TransformFullNamePreserveLengthEdgeCases(t *testing.T) {
165+
t.Run("very short name", func(t *testing.T) {
166+
randomizer := rng.New(1)
167+
shortName := "A"
168+
expectedLength := int64(len(shortName))
169+
170+
res, err := transformFullName(randomizer, shortName, true, maxCharacterLimit)
171+
172+
assert.NoError(t, err)
173+
assert.NotNil(t, res)
174+
assert.Equal(t, expectedLength, int64(len(*res)), "The output should be the same length as the input")
175+
})
176+
177+
t.Run("name with only spaces", func(t *testing.T) {
178+
randomizer := rng.New(1)
179+
spaceName := " "
180+
181+
res, err := transformFullName(randomizer, spaceName, true, maxCharacterLimit)
182+
183+
assert.NoError(t, err)
184+
assert.NotNil(t, res)
185+
assert.Equal(t, int64(len(spaceName)), int64(len(*res)), "The output should be the same length as the input")
186+
})
187+
}
188+
189+
func Test_SplitEvenly(t *testing.T) {
190+
t.Run("even number of words", func(t *testing.T) {
191+
first, last := splitEvenly("John Smith")
192+
assert.Equal(t, "John", first)
193+
assert.Equal(t, "Smith", last)
194+
})
195+
196+
t.Run("odd number of words", func(t *testing.T) {
197+
first, last := splitEvenly("John van der Berg")
198+
assert.Equal(t, "John van", first)
199+
assert.Equal(t, "der Berg", last)
200+
})
201+
202+
t.Run("single word", func(t *testing.T) {
203+
first, last := splitEvenly("John")
204+
assert.Equal(t, "John", first)
205+
assert.Equal(t, "", last)
206+
})
207+
208+
t.Run("empty string", func(t *testing.T) {
209+
first, last := splitEvenly("")
210+
assert.Equal(t, "", first)
211+
assert.Equal(t, "", last)
212+
})
213+
214+
t.Run("multiple spaces", func(t *testing.T) {
215+
first, last := splitEvenly("John Smith")
216+
assert.Equal(t, "John", first)
217+
assert.Equal(t, "Smith", last)
218+
})
219+
}
220+
221+
func Test_TransformFullNamePreserveLength_FirstNameFallback(t *testing.T) {
222+
t.Run("first name fallback to random string padding", func(t *testing.T) {
223+
randomizer := rng.New(1)
224+
// Use a name with a length that is unlikely to exist in the corpus (e.g., 1 character)
225+
name := "A B"
226+
res, err := transformFullName(randomizer, name, true, maxCharacterLimit)
227+
assert.NoError(t, err)
228+
assert.NotNil(t, res)
229+
assert.Equal(t, len(name), len(*res), "Output should match input length")
230+
assert.Contains(t, *res, " ", "Should contain a space")
231+
// The first and last name parts should each be 1 character (plus the space)
232+
parts := strings.SplitN(*res, " ", 2)
233+
if len(parts) == 2 {
234+
assert.Len(t, parts[0], 1, "First name part should be 1 char (padded if needed)")
235+
assert.Len(t, parts[1], 1, "Last name part should be 1 char (padded if needed)")
236+
}
237+
})
238+
}
239+
240+
func Test_TransformFullNamePreserveLength_PadAndTruncate(t *testing.T) {
241+
t.Run("padding when generated name is shorter than input", func(t *testing.T) {
242+
randomizer := rng.New(1)
243+
// Use a name with a length that is longer than typical generated names
244+
name := "John Smith ExtraLongName"
245+
res, err := transformFullName(randomizer, name, true, maxCharacterLimit)
246+
assert.NoError(t, err)
247+
assert.NotNil(t, res)
248+
assert.Equal(t, len(name), len(*res), "Output should match input length")
249+
assert.Contains(t, *res, " ", "Should contain a space")
250+
})
251+
252+
t.Run("truncation when generated name is longer than input", func(t *testing.T) {
253+
randomizer := rng.New(1)
254+
// Use a very short name so the generated name will be truncated
255+
name := "Jo Sm"
256+
res, err := transformFullName(randomizer, name, true, maxCharacterLimit)
257+
assert.NoError(t, err)
258+
assert.NotNil(t, res)
259+
assert.Equal(t, len(name), len(*res), "Output should match input length")
260+
assert.Contains(t, *res, " ", "Should contain a space")
261+
})
262+
}

0 commit comments

Comments
 (0)