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

Enable funlen linter (part 2) #1171

Merged
merged 13 commits into from
Apr 24, 2024
Merged

Enable funlen linter (part 2) #1171

merged 13 commits into from
Apr 24, 2024

Conversation

brojeg
Copy link

@brojeg brojeg commented Mar 27, 2024

I hereby agree to the terms of the CLA available at: https://yandex.ru/legal/cla/?lang=en

Pull request type

Please check the type of change your PR introduces:

  • Bugfix
  • Feature
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • Documentation content changes
  • Other (please describe):

What is the current behavior?

Issue Number: 934

What is the new behavior?

Other information

@brojeg
Copy link
Author

brojeg commented Mar 27, 2024

@rekby Please review.

return name, fileName
}

func parseFunctionName(name string) (pkgPath, pkgName, structName, funcName string, lambdas []string) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a unit tests for newest functions?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@codecov-commenter
Copy link

codecov-commenter commented Mar 28, 2024

Codecov Report

Attention: Patch coverage is 66.66667% with 42 lines in your changes are missing coverage. Please review.

Project coverage is 41.08%. Comparing base (b7a9b51) to head (013a60c).
Report is 47 commits behind head on master.

Files Patch % Lines
internal/decimal/decimal.go 51.19% 35 Missing and 6 partials ⚠️
retry/retry.go 92.30% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1171      +/-   ##
==========================================
+ Coverage   40.80%   41.08%   +0.28%     
==========================================
  Files         309      310       +1     
  Lines       32747    32959     +212     
==========================================
+ Hits        13361    13540     +179     
- Misses      18959    18986      +27     
- Partials      427      433       +6     
Flag Coverage Δ
go-1.21.x 43.29% <66.66%> (+0.35%) ⬆️
go-1.22.x 41.07% <66.66%> (+0.28%) ⬆️
macOS 40.60% <68.46%> (+0.30%) ⬆️
ubuntu 40.58% <68.46%> (+0.28%) ⬆️
unit 41.08% <66.66%> (+0.28%) ⬆️
windows 41.05% <66.66%> (+0.25%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@rekby rekby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, thanks for the work!
it is very good for your work for code style.

I see new part better, for example you add linter skip for one of functions, which really doesn't need to split.

I have some for the before merge it.

internal/decimal/decimal.go Show resolved Hide resolved
*scale--
} else if !dot {
if *integral == 0 {
remaining += string(c)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every addition to string has linear complexity and re-allocate memory.
Use strings.Builder{} for build the string.

}

integral := precision - scale
s, err := parseNumber(s, v, &integral, &scale)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What mean integral and scale after return from parseNumber?

Do we need pass the values by pointers?

return syntaxError(s)
}
plus := c > '5'
if !plus && c == '5' {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need check plus, you can check c == '5' only

return v.Set(nan), nil
func shouldRoundUp(v *big.Int, s string) bool {
var x big.Int
plus := x.And(v, big.NewInt(1)).Cmp(big.NewInt(0)) != 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use one and zero variables for prevent new allocation for every function call

return name, fileName
}

func parseFunctionName(name string) (pkgPath, pkgName, structName, funcName string, lambdas []string) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of results, especially with same type is difficult to understand in code and use.
What about return a structure?

retry/retry.go Show resolved Hide resolved
retry/retry.go Outdated

if err == nil {
return nil
}

if ctxErr := ctx.Err(); ctxErr != nil {
return xerrors.WithStackTrace(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need extract simple error formatting

retry/retry.go Show resolved Hide resolved
retry/retry.go Outdated Show resolved Hide resolved
@rekby rekby self-assigned this Mar 29, 2024
@rekby
Copy link
Member

rekby commented Apr 1, 2024

Thanks, it seems good.

I need some time to check PR for logic equals, because it was not only split code to smaller parts, but refactor too.

@brojeg
Copy link
Author

brojeg commented Apr 9, 2024

Is there any news on this PR?

@rekby
Copy link
Member

rekby commented Apr 10, 2024

Is there any news on this PR?

Thanks for remind, I will plan to see the PR today.

Copy link
Member

@rekby rekby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job, thanks.

See for one additional method for test equals of old and new function while refactoring.

v.Set(inf)

if c >= '5' {
if c > '5' || shouldRoundUp(v, s[1:]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in prev version it was shouldRoundUp(v, s), why che call changed to shouldRoundUp(v, s[1:]) and start check from next symbol?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reverted the change.

return v, nil
}

func SetSpecialValue(v *big.Int, s string) bool {
neg := s[0] == '-'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it will be good to use function parseSign here

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used existing function parseSign

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now the function setSpecialValue do many things, instead only parse special values.

Now it:

  1. Detect negative values
  2. Cut sign from string

And it has interface with difficult to understand: it change input "v" and return it.
Usually function return new value without change input, rarer change input without return it.

Change and return used for chaining calls within builder - for you can call Obj.Method1().Method2().Method3().... with one line.

please return separate function parseSign function for detect and cut off sign and reuse the function here and in parseNumber.

Or detect and cut sign before call setSpecialValue (better parseSpecialValue) and pass the sign to the function, then to parseNumber if you won't check the sign twice.

P.S. i think about check the sign twice better - it is very small check, but it more understandable to read, then many parameters.

@@ -95,129 +95,177 @@ func Parse(s string, precision, scale uint32) (*big.Int, error) {
return v, nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New version has difference with old version of Parse in some cases.

please add fuzzing test for check equals of old and new Parse function results:

func FuzzParse(f *testing.F) {
	f.Fuzz(func(t *testing.T, s string, precision, scale uint32) {
		expectedRes, expectedErr := oldParse(s, precision, scale)
		res, err := Parse(s, precision, scale)
		if expectedErr == nil {
			require.Equal(t, expectedRes, res)
		} else {
			require.Error(t, err)
		}
	})
}

Where oldParse is copy of Parse from main branch.
Now result has differences at arguments "100", 0, 0.

You can past oldParse near the test in decimal_test.go, I will remove it from the branch after merge.

You can add better fuzz-test for better test long numbers instead of random strings only.

You can run fuzzing by command:

go test -fuzz=FuzzParse

https://go.dev/doc/security/fuzz/

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added the provided test function FuzzParse and oldParse function to decimal_test.go

Copy link
Member

@rekby rekby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test FuzzParse is failed.

=== RUN   FuzzParse
--- FAIL: FuzzParse (27.30s)
=== RUN   FuzzParse/1279e0a916766c26
    decimal_test.go:366: 
        	Error Trace:	/Users/rekby/projects/yandex/ydb-go-sdk-workspace/ydb-go-sdk/internal/decimal/decimal_test.go:366
        	            				/Users/rekby/gosdk/go1.22.0/src/reflect/value.go:596
        	            				/Users/rekby/gosdk/go1.22.0/src/reflect/value.go:380
        	            				/Users/rekby/gosdk/go1.22.0/src/testing/fuzz.go:335
        	Error:      	Not equal: 
        	            	expected: 100000000000000000000000000000000000
        	            	actual  : 0
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -2,6 +2,3 @@
        	            	  neg: (bool) false,
        	            	- abs: (big.nat) (len=2) {
        	            	-  (big.Word) 3136633892082024448,
        	            	-  (big.Word) 5421010862427522
        	            	- }
        	            	+ abs: (big.nat) <nil>
        	            	 })
        	Test:       	FuzzParse/1279e0a916766c26
    --- FAIL: FuzzParse/1279e0a916766c26 (27.30s)

Expected :100000000000000000000000000000000000
Actual   :0

With same input as in my previous comment:

go test fuzz v1
string("100")
uint32(0)
uint32(0)

It mean that result of old and new functions have differences for string "100", zero scale and zero precision.

@brojeg brojeg requested a review from rekby April 15, 2024 14:39
Copy link
Member

@rekby rekby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, good work, thanks!
I don't found errors now.

It need only small cosmetic fix and resolve conflicts before merge

return v, nil
}

func SetSpecialValue(v *big.Int, s string) bool {
neg := s[0] == '-'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now the function setSpecialValue do many things, instead only parse special values.

Now it:

  1. Detect negative values
  2. Cut sign from string

And it has interface with difficult to understand: it change input "v" and return it.
Usually function return new value without change input, rarer change input without return it.

Change and return used for chaining calls within builder - for you can call Obj.Method1().Method2().Method3().... with one line.

please return separate function parseSign function for detect and cut off sign and reuse the function here and in parseNumber.

Or detect and cut sign before call setSpecialValue (better parseSpecialValue) and pass the sign to the function, then to parseNumber if you won't check the sign twice.

P.S. i think about check the sign twice better - it is very small check, but it more understandable to read, then many parameters.

@brojeg
Copy link
Author

brojeg commented Apr 16, 2024

I'm not quite sure how to resolve the particular merge conflict.
The particular code that needs to be merged in extractLambdas function exists under parseFunctionName function in my PR.

@rekby
Copy link
Member

rekby commented Apr 17, 2024

I'm not quite sure how to resolve the particular merge conflict. The particular code that needs to be merged in extractLambdas function exists under parseFunctionName function in my PR.

You can't merge it "automatically", because you have refactored the code.
You should see what mean changes in master branch, then re-implement the changes at own code. Then remove master's code block on merge.

@brojeg
Copy link
Author

brojeg commented Apr 17, 2024

@rekby please review now.

@brojeg brojeg requested a review from rekby April 22, 2024 14:44
Copy link
Member

@rekby rekby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for great work!

Copy link
Member

@rekby rekby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attention:

I have pushed commit to your branch for resolve merge conflict with master. Pull the branch before work with the code.

if i := strings.LastIndex(file, "/"); i > -1 {
file = file[i+1:]
fileName = file[i+1:]
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once more point:
record.go was 100% coveraged before refactor and 98.8% after.

One branch of the code not tested: point when file doesn't contain /.
Add test for this please and PR will be merge.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed the issue by replace the code by function from standard library - for extrace file name from path.

@rekby rekby merged commit d063e33 into ydb-platform:master Apr 24, 2024
35 of 36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants