RUMM-2651 SR - skip new lines and spaces when obfuscating texts#1078
Conversation
| return String( | ||
| CharArray(text.length) { | ||
| val character = text[it] | ||
| if (character == CHARACTER_SPACE || character == CHARACTER_NEW_LINE) { |
There was a problem hiding this comment.
you can use character.isWhitespace() to check this rather than comparing to our own hardcoded values
| CharArray(text.length) { | ||
| val character = text[it] | ||
| if (character == ' ' || character == '\n') { | ||
| character | ||
| } else { | ||
| 'x' | ||
| } | ||
| } |
There was a problem hiding this comment.
Here you're duplicating the production algorithm, meaning there's no way your test can fail.
There was a problem hiding this comment.
yeah I know, this is for all the other tests that are not exactly testing the obfuscation, is just that we are asserting everything in those. For all the obfuscation cases I added the 3 tests below.
|
|
||
| // Then | ||
| val expectedWireframe = mockButton.toTextWireframe().copy(text = fakeText) | ||
| val expectedWireframe = mockTextView.toTextWireframe().copy(text = fakeExpectedText) |
There was a problem hiding this comment.
You should also have a test in the form
val chunk1 = randomText
val chunk2 = randomText
val spacer = randomWhitespace // forge.forge.aWhitespaceString()
val input = chunk1 + spacer + chunk2
val expectedOutput = ("x" * chunk1.length) + spacer + ("x" * chunk2.length)with this (I don't know if it exist in our repo
operator fun String.times(i: Int) {
val builder = StringBuilder(i * length)
repeat(i) {
builder.append(this)
}
}
Codecov Report
@@ Coverage Diff @@
## feature/sdkv2 #1078 +/- ##
=================================================
+ Coverage 82.58% 82.65% +0.07%
=================================================
Files 346 347 +1
Lines 11157 11165 +8
Branches 1831 1832 +1
=================================================
+ Hits 9214 9228 +14
+ Misses 1381 1378 -3
+ Partials 562 559 -3
|
7bb701a to
52fb574
Compare
52fb574 to
a19d58e
Compare
a19d58e to
99bb53a
Compare
|
|
||
| internal class StringObfuscator { | ||
| fun obfuscate(stringValue: String): String { | ||
| return String( |
There was a problem hiding this comment.
let's add TODO maybe here, saying it works only for ASCII. Also character can be non-printable Control character, but I guess we can ignore it.
There was a problem hiding this comment.
I just realized that I need to use another method to support all unicode characters the way they are specifying in their comments.
There was a problem hiding this comment.
this won't work properly for Unicode still. For example, let's take the following emoji. It has a code \u1f600, so it already exceeds char size (which values go only up to \uffff, because it can fit only 16 bits), so this single symbol consists of the 2 char -> "😀".length will give 2.
But in reality we cannot threat these chars independently, because first is just a high surrogate and second is the low surrogate. This is how UTF-16 encoding is actually working - it will read the stream of char of length 16 bits and decide if next char is a lower surrogate or independent symbol.
There was a problem hiding this comment.
Yes I imagine this is the way it should work but I think this will not be a problem. The only issue would be if one of this emojis will contain one of the non printable characters in their composition. In that case we will brake the text but I am pretty sure Character.isWhitespace() handles that somehow or maybe these whitespace characters are not used in emojis.
There was a problem hiding this comment.
My point is that in case of emoji we will have xx instead of single x, not sure if this is what we want to achieve (I guess Character.isWhitespace() will return false for any surrogate).
There was a problem hiding this comment.
Yeah...I don't think this should be an issue as long as we obfuscate the texts. It will be a corner case anyway. I am going to add this explanation there though to have this in mind.
There was a problem hiding this comment.
I won't say it is a corner case, because there are plenty of symbols with above \uffff, and if we think of emojis we may find a lot of them in messenger apps, for example, and obfuscation may break formatting. Not a blocker for me, but let's acknowledge this.
| assertThat(obfuscatedText).isEqualTo(fakeExpectedText) | ||
| } | ||
|
|
||
| private fun String.times(n: Int): String { |
| fakeExpectedChunk3 + | ||
| fakeExpectedChunk4 + | ||
| fakeExpectedChunk5 | ||
| ).times(n) |
There was a problem hiding this comment.
why do we need times call if it just copies the same?
There was a problem hiding this comment.
the times was more to generate a string with just 'x' of a given size, here it doesn't make sense
754eefd to
94f9404
Compare
94f9404 to
c82b100
Compare
| val character = stringValue[it] | ||
| // Using the Character.isWhitespace() function we will support also the UNICODE | ||
| // characters according with the docs. Also have in mind that in JAVA the | ||
| // `char` primitive is a 16bits long number which covers all the UNICODE characters: |
There was a problem hiding this comment.
char doesn't cover all the Unicode characters. It covers BMP plain Unicode characters, but it doesn't cover Supplementary plain characters (above 0xFFFF). When we call character.code we just cast from char to int, but to get code of the symbol from supplementary plain we need to merge 2 chars into single int.
c82b100 to
dfee181
Compare
|
|
||
| @Test | ||
| @TestTargetApi(Build.VERSION_CODES.N) | ||
| fun `M mask String W maskString(){string with newline, Android N}`( |
There was a problem hiding this comment.
It is not maskString, but obfuscate. Same for other tests.
| fun `M mask String W maskString(){string with newline, Android N}`( | |
| fun `M mask String W obfuscate(){string with newline, Android N}`( |
09bc0c4 to
483486f
Compare
483486f to
0d1e683
Compare
What does this PR do?
We need to skip the new lines and spaces characters when applying the obfuscation on the text values to keep the aspect ratio of the replicated text view element in the Web Player.
Motivation
What inspired you to submit this pull request?
Additional Notes
Anything else we should know when reviewing?
Review checklist (to be filled by reviewers)