Skip to content

Instantly share code, notes, and snippets.

@brandur
Created October 28, 2024 12:46
Show Gist options
  • Save brandur/e3ccd45369415031925995cd9cf3265b to your computer and use it in GitHub Desktop.
Save brandur/e3ccd45369415031925995cd9cf3265b to your computer and use it in GitHub Desktop.
Go code mods
def replace_vars(text, vars)
updated_lines = []
text.each_line do |line|
new_line, after_func = line.split("func(", 2)
vars.each do |var|
new_line.gsub!(/([^"]?\b)#{var}\b/, '\1' + "bundle.#{var}")
end
new_line += "func(" + after_func if after_func
updated_lines << new_line unless line.empty?
end
updated_lines.join
end
def code_mod(text)
# i = 0
text.gsub(/func Test(?<pre_var>((?!func).)*?)var (?<var_content>([^\(\n]*?\n|\([^\)\}]*?\)))(?<pre_setup>((?!\n\}).)*?)setup := func\(test func\(\*testing\.T\)\) func\(\*testing\.T\) \{\n(?<setup_block>.*?)\n }\n(?<test_cases>.*?)\n\}/m) do |match_text|
match = Regexp.last_match
root_match = match
new_match_text = match_text
# i += 1
# exit if i > 1
# puts match_text
p "pre var: " + match[:pre_var]
var_content = match[:var_content]
p "var content: " + var_content
vars = var_content.scan(/^\s*(.+?)\b/).flatten
p "var list: " + vars.inspect
abort "pre var should not contain \\n}" if match[:pre_var].include?("\n}")
abort "pre var should not contain t.Run" if match[:pre_var].include?("t.Run}")
abort "var content should not contain \\n}" if match[:var_content].include?("\n}")
abort "var content should not contain t.Run" if match[:var_content].include?("t.Run}")
abort "pre setup should not contain \\n}" if match[:pre_setup].include?("\n}")
abort "pre setup should not contain t.Run}" if match[:pre_setup].include?("t.Run}")
abort "test cases should not contain \\n}" if match[:test_cases].include?("\n}")
p "pre setup: " + match[:pre_setup]
# rewrite vars
lambda do
var_content_no_paren = var_content.dup
var_content_no_paren.sub!("(", "")
var_content_no_paren.sub!(")", "")
new_match_text.sub!("var " + var_content, "type testBundle struct { #{var_content_no_paren} }\n")
end.call
# puts "after var rewrite: " + new_match_text
# rewrite setup function
lambda do
new_match_text.gsub!("setup := func(test func(*testing.T)) func(*testing.T) {", "setup := func(t *testing.T) *testBundle {")
# if !new_match_text.include?("type testBundle struct")
# new_match_text.sub!("setup := func(t *testing.T) *testBundle {", "type testBundle struct {}\n\nsetup := func(t *testing.T) *testBundle {")
# end
new_setup_block = match[:setup_block]
# puts new_setup_block
new_setup_block.gsub!(/\s+return func\(t \*testing\.T\) \{\n/m, '')
new_setup_block.gsub!(/\s+test\(t\)\n\s+\}/m, '')
vars.each do |var|
new_setup_block.sub!("#{var} = ", "#{var} := ")
end
new_setup_block += "\n\n\t\treturn &testBundle{\n"
vars.each do |var|
if new_setup_block.include?(var)
new_setup_block += "\t\t\t#{var}: #{var},\n"
end
end
new_setup_block += "\t\t}"
# puts new_setup_block
new_match_text.gsub!(match[:setup_block], new_setup_block)
end.call
functions_bundle_added = []
extract_bundle_functions = lambda do |text|
text.gsub!(/(?<whitespace>\s+)(?<function_name>.*)? := func\(/) do |match_text|
inner_match = Regexp.last_match
functions_bundle_added << inner_match[:function_name]
"#{inner_match[:whitespace]}#{inner_match[:function_name]} := func(bundle *testBundle, "
end
end
# between var ( ... ) and setup
new_match_text.gsub!(/type testBundle struct \{.*?\}(?<pre_setup>.*?)setup := func\(t \*testing.T\)/m) do |match_text|
# puts "presetup"
# puts match_text
match = Regexp.last_match
new_pre_setup = match[:pre_setup]
new_pre_setup = replace_vars(new_pre_setup, vars)
if match[:pre_setup] != new_pre_setup
extract_bundle_functions.call(new_pre_setup)
end
# puts new_pre_setup
match_text.gsub(match[:pre_setup], new_pre_setup)
end
# between setup and first t.Run
new_match_text.gsub!(/setup := func\(t \*testing\.T\) \{.*? \}(?<post_setup>.*?)t\.Run\("/m) do |match_text|
match = Regexp.last_match
new_post_setup = match[:post_setup]
new_post_setup = replace_vars(new_post_setup, vars)
if match[:post_setup] != new_post_setup
extract_bundle_functions.call(new_post_setup)
end
match_text.gsub(match[:post_setup], new_post_setup)
end
p functions_bundle_added
new_match_text.gsub!(/t\.Run\("(?<test_case_name>.*?)", setup\(func\(t \*testing\.T\) \{(?<test_case_body>.*?\n\t)\}\)\)/m) do |match_text|
# puts match_text
match = Regexp.last_match
test_case_body = match[:test_case_body]
test_case_body = replace_vars(test_case_body, vars)
functions_bundle_added.each do |function|
test_case_body.gsub!(/\b#{function}\(/, "#{function}(bundle, ")
end
t_parallel = "\t\tt.Parallel()\n\n"
if test_case_body.include?("Setenv") || root_match[:setup_block].include?("Setenv")
t_parallel = ""
end
%{t.Run("#{match[:test_case_name]}", func(t *testing.T) {\n#{t_parallel}\t\tbundle := setup(t)\n#{test_case_body}})}
end
new_match_text
end
end
if __FILE__ == $0
# Dir["../**/*_test.go"].each do |path|
# [
# "../bgworkerkind/aws_batch_usage_sender_test.go",
# "../middleware/auth_object_authenticator_test.go",
# "../pcommandkind/cluster_create_test.go",
# # "../server/api/cluster_service_test.go",
# ].each do |path|
[
"../bgworkerkind/google_pub_sub_listener_test.go"
].each do |path|
text = File.read(path)
new_text = code_mod(text)
if text != new_text
puts "modified: #{path}"
File.write(path, new_text)
end
end
end
def code_mod(text)
# type testBundle struct {
# ctx context.Context
# worker *GoogleMarketplacePubSubListener
# }
text = text.gsub(/type testBundle struct \{(?<bundle_content>.*?)\}/m) do |match_text|
# match = Regexp.last_match
match_text.sub!(/\t+ctx\s+context\.Context\n/, '')
match_text
end
# setup := func(t *testing.T) *testBundle {
text = text.gsub(/setup := func\(t \*testing\.T\) \*testBundle \{((?!\n\t}).)+ctx :=(?<post_ctx>(?!\n\t}).)+\n\t\}/m) do |match_text|
# match = Regexp.last_match
match_text.sub!('setup := func(t *testing.T) *testBundle {', 'setup := func(t *testing.T) (*testBundle, context.Context) {')
# return &testBundle{
# ctx: ctx,
# worker: worker,
# }
match_text = match_text.gsub(/return &testBundle\{[^\}]+ctx:\s+ctx,[^\}]+\}/m) do |match_text|
match_text.sub!(/\t+ctx:\s+ctx,\n/, '')
match_text
end
# return &testBundle{
# worker: worker,
# }
match_text = match_text.gsub(/return &testBundle\{[^\}]+\}/m) do |match_text|
match_text + ", ctx"
end
# bundle := &testBundle{
# cluster: cluster,
# ctx: ctx,
# req: req,
# svc: svc,
# tx: tx,
# }
match_text = match_text.gsub(/bundle := &testBundle\{[^\}]+ctx:\s+ctx,[^\}]+\}/m) do |match_text|
match_text.sub!(/\t+ctx:\s+ctx,\n/, '')
match_text
end
# return bundle
match_text = match_text.gsub(/return bundle/) do |match_text|
match_text + ", ctx"
end
match_text
end
text = text.gsub('bundle := setup(t)', 'bundle, ctx := setup(t)')
text = text.gsub('bundle.ctx', 'ctx')
text = text.gsub(/t\.Run\("[^"]+", func\(t \*testing\.T\) \{(?<pre_setup>((?!\n\t\}).)+)bundle, ctx := setup\(t\)(?<post_setup>((?!\n\t\}).)+)\n\t\}/m) do |match_text|
# text = text.gsub(/t\.Run\("[^"]+", func\(t \*testing\.T\) \{/m) do |match_text|
match = Regexp.last_match
# puts match_text
# puts "pre setup: #{match[:pre_setup]}"
# puts "post setup: #{match[:post_setup]}"
unless match[:post_setup].include?("ctx")
match_text.sub!('bundle, ctx := setup(t)', 'bundle, _ := setup(t)')
end
match_text
end
text
end
if __FILE__ == $0
Dir["../**/*_test.go"].each do |path|
# [
# "../bgworkerkind/aws_batch_usage_sender_test.go",
# "../bgworkerkind/google_pub_sub_listener_test.go",
# "../middleware/auth_object_authenticator_test.go",
# "../pcommandkind/cluster_create_test.go",
# "../server/api/cluster_service_test.go",
# ].each do |path|
# [
# "../bgworkerkind/google_pub_sub_listener_test.go"
# ].each do |path|
text = File.read(path)
new_text = code_mod(text)
if text != new_text
puts "modified: #{path}"
File.write(path, new_text)
else
puts "no changes: #{path}"
end
end
end
def code_mod(text)
text = text.dup
# text.gsub!(/svc := pservicetest\.InitAndStart\(ctx, t, (?<service_init>[^\n]+)\)(?<pre_bundle>((?!\n\t\}).)+)&testBundle\{(?<pre_svc>((?!\n\t\t\}).)+)svc:(?<svc_space>\s+)svc,/m) do |match_text|
text.gsub!(/worker := bgworkertest\.InitAndStart\(ctx, t, (?<service_init>[^\n]+)\)(?<pre_bundle>((?!\n\t\}).)+)&testBundle\{(?<pre_svc>((?!\n\t\t\}).)+)worker:(?<svc_space>\s+)worker,/m) do |match_text|
match = Regexp.last_match
# p match
# "#{match[:pre_bundle]}&testBundle{#{match[:pre_svc]}svc:#{match[:svc_space]}pservicetest.InitAndStart(ctx, t, #{match[:service_init]}),"
"#{match[:pre_bundle]}&testBundle{#{match[:pre_svc]}worker:#{match[:svc_space]}bgworkertest.InitAndStart(ctx, t, #{match[:service_init]}, nil),"
end
# text.gsub!(/\bsvc\.(.*?) = /)
text
end
if __FILE__ == $0
Dir["bgworkerkind/**/*_test.go"].each do |path|
# [
# "bgworkerkind/aws_batch_usage_sender_test.go",
# ].each do |path|
text = File.read(path)
new_text = code_mod(text)
if text != new_text
puts "modified: #{path}"
File.write(path, new_text)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment