NAME=text-fields-synthetic
FILE=-
CMDS=<<EOF
!!../bin/r2flutter -c bins/synthetic/field_snapshot.bin 2>/dev/null
EOF
EXPECT=<<EOF
class TestClass implements TestInterface (size=48)
  library: package:test
  fields:
    +0x10 int fieldA
    +0x18 List<int> items
    +0x20 List<X0> genericItems
    +0x28 (int) => String callback
  methods:
    0x00000000 compute (int) => String (RegularFunction)
class TestInterface (size=0)
  library: package:test

EOF
RUN

NAME=json-fields-synthetic
FILE=-
CMDS=<<EOF
!!../bin/r2flutter -j -c bins/synthetic/field_snapshot.bin 2>/dev/null
EOF
EXPECT=<<EOF
[{"ref":12,"name":"TestClass","library":{"ref":11,"name":"package:test"},"interfaces":[{"ref":23,"class_ref":13,"name":"TestInterface"}],"layout":{"instance_size":48,"type_params":1,"type_arg_offset":0},"flags":{"abstract":false,"enum":false,"mixin":false,"toplevel":false},"fields":[{"name":"fieldA","type":"int","offset":16,"flags":{"static":false,"final":false,"const":false,"late":false}},{"name":"items","type":"List<int>","offset":24,"flags":{"static":false,"final":false,"const":false,"late":false}},{"name":"genericItems","type":"List<X0>","offset":32,"flags":{"static":false,"final":false,"const":false,"late":false}},{"name":"callback","type":"(int) => String","offset":40,"flags":{"static":false,"final":false,"const":false,"late":false}}],"methods":[{"name":"compute","entry":0,"owner":"TestClass","signature":"(int) => String","kind_tag":0,"kind":"RegularFunction"}]},{"ref":13,"name":"TestInterface","library":{"ref":11,"name":"package:test"},"layout":{"instance_size":0,"type_params":0,"type_arg_offset":0},"flags":{"abstract":false,"enum":false,"mixin":false,"toplevel":false}}]
EOF
RUN

NAME=strings-fields-synthetic
FILE=-
CMDS=<<EOF
!!../bin/r2flutter -zz bins/synthetic/field_snapshot.bin 2>/dev/null
EOF
EXPECT=<<EOF
0x00000018   74 :app "00000000000000000000000000000000product arm64 macos no-compressed-pointers"
0x0000006e    9 :lib "TestClass"
0x00000078   12 :lib "package:test"
0x00000085    6 :lib "fieldA"
0x00000090    5 :lib "items"
0x00000096   12 :lib "genericItems"
0x000000a3    8 :lib "callback"
0x000000ac    7 :lib "compute"
0x000000b4   13 :lib "TestInterface"

EOF
RUN

NAME=json-strings-fields-synthetic
FILE=-
CMDS=<<EOF
!!../bin/r2flutter -j -xzz bins/synthetic/field_snapshot.bin 2>/dev/null
EOF
EXPECT=<<EOF
[{"ref":0,"len":74,"value":"00000000000000000000000000000000product arm64 macos no-compressed-pointers","category":"app","two_byte":false,"canonical":true,"addr":24},{"ref":1,"len":9,"value":"TestClass","category":"lib","two_byte":false,"canonical":true,"addr":110,"refs":[{"obj":12,"type":"class","kind":"class.name","name":"TestClass"}]},{"ref":2,"len":12,"value":"package:test","category":"lib","two_byte":false,"canonical":true,"addr":120,"refs":[{"obj":11,"type":"library","kind":"library.name","name":"package:test"}]},{"ref":3,"len":6,"value":"fieldA","category":"lib","two_byte":false,"canonical":true,"addr":133,"refs":[{"obj":25,"type":"field","kind":"field.name","name":"TestClass.fieldA"}]},{"ref":4,"len":5,"value":"items","category":"lib","two_byte":false,"canonical":true,"addr":144,"refs":[{"obj":26,"type":"field","kind":"field.name","name":"TestClass.items"}]},{"ref":5,"len":12,"value":"genericItems","category":"lib","two_byte":false,"canonical":true,"addr":150,"refs":[{"obj":27,"type":"field","kind":"field.name","name":"TestClass.genericItems"}]},{"ref":6,"len":8,"value":"callback","category":"lib","two_byte":false,"canonical":true,"addr":163,"refs":[{"obj":28,"type":"field","kind":"field.name","name":"TestClass.callback"}]},{"ref":7,"len":7,"value":"compute","category":"lib","two_byte":false,"canonical":true,"addr":172,"refs":[{"obj":29,"type":"function","kind":"method.name","name":"TestClass.compute"}]},{"ref":8,"len":13,"value":"TestInterface","category":"lib","two_byte":false,"canonical":true,"addr":180,"refs":[{"obj":12,"type":"class","kind":"class.interface","name":"TestClass"},{"obj":13,"type":"class","kind":"class.name","name":"TestInterface"}]}]
EOF
RUN

NAME=xrefs-fields-synthetic
FILE=-
CMDS=<<EOF
!!../bin/r2flutter -x bins/synthetic/field_snapshot.bin 2>/dev/null
EOF
EXPECT=<<EOF
metadata class.name class TestClass [ref=12] -> string TestClass [ref=2] @ 0x6e
metadata class.library class TestClass [ref=12] -> library package:test [ref=11]
metadata class.interface class TestClass [ref=12] -> type TestInterface [ref=23]
metadata field.owner field TestClass.fieldA [ref=25] -> class TestClass [ref=12]
metadata field.name field TestClass.fieldA [ref=25] -> string fieldA [ref=4] @ 0x85
metadata field.type field TestClass.fieldA [ref=25] -> type int [ref=19]
metadata field.owner field TestClass.items [ref=26] -> class TestClass [ref=12]
metadata field.name field TestClass.items [ref=26] -> string items [ref=6] @ 0x90
metadata field.type field TestClass.items [ref=26] -> type List<int> [ref=20]
metadata field.owner field TestClass.genericItems [ref=27] -> class TestClass [ref=12]
metadata field.name field TestClass.genericItems [ref=27] -> string genericItems [ref=7] @ 0x96
metadata field.type field TestClass.genericItems [ref=27] -> type List<X0> [ref=21]
metadata field.owner field TestClass.callback [ref=28] -> class TestClass [ref=12]
metadata field.name field TestClass.callback [ref=28] -> string callback [ref=8] @ 0xa3
metadata field.type field TestClass.callback [ref=28] -> type (int) => String [ref=24]
metadata method.owner method TestClass.compute [ref=29] -> class TestClass [ref=12]
metadata method.name method TestClass.compute [ref=29] -> string compute [ref=9] @ 0xac
metadata method.signature method TestClass.compute [ref=29] -> type (int) => String [ref=24]
metadata class.name class TestInterface [ref=13] -> string TestInterface [ref=10] @ 0xb4
metadata class.library class TestInterface [ref=13] -> library package:test [ref=11]
EOF
RUN

NAME=r2-fields-synthetic-class-metadata
FILE=-
CMDS=<<EOF
!!../bin/r2flutter -r -c bins/synthetic/field_snapshot.bin 2>/dev/null | grep -E '^(# Dart class symbols|ic\+dart_TestClass @ 0|ic\+dart_TestInterface @ 0|ic\+dart_TestClass:dart_TestInterface|ac dart_TestClass$|acb dart_TestClass dart_TestInterface 0|ic\+dart_TestClass\.\.callback void \* @ 0x28|ic\+dart_TestClass.compute @ 0x0|# field dart_TestClass.callback|# method dart_TestClass.compute)'
EOF
EXPECT=<<EOF
# Dart class symbols and analysis metadata
ic+dart_TestClass @ 0
ac dart_TestClass
ic+dart_TestInterface @ 0
ic+dart_TestClass:dart_TestInterface
acb dart_TestClass dart_TestInterface 0
# field dart_TestClass.callback +0x28 type=(int) => String instance
ic+dart_TestClass..callback void * @ 0x28
ic+dart_TestClass.compute @ 0x0
# method dart_TestClass.compute kind=RegularFunction mode=instance cc=dyncc:x0+8,^:x0!T0 signature=(int) => String
ic+dart_TestInterface @ 0
EOF
RUN

NAME=r2-fields-synthetic-safe-type-script
FILE=-
CMDS=<<EOF
!!../bin/r2flutter -r -c bins/synthetic/field_snapshot.bin 2>/dev/null | awk 'BEGIN { td = 0; bad = 0 } /^"td struct dart_TestClass \{ uint8_t _pad0\[0x10\]; int64_t fieldA; void \* items; void \* genericItems; void \* callback; \};"$/ { td = 1 } /^af @/ || /^afc / || /td struct\.dart/ || /\(int\) => String callback @/ { bad = 1 } END { print "td=" td; print "bad=" bad }'
EOF
EXPECT=<<EOF
td=1
bad=0
EOF
RUN

NAME=r2-plugin-C-fields-synthetic
FILE=-
CMDS=<<EOF
!!sh -c "p=../src/r2/core_flutter.dylib; [ -f \"\$p\" ] || p=../src/r2/core_flutter.so; r2 -NN -q -i \"\$p\" -qc \"r2flutter -C\" -qc ic -qc \"t dart_TestClass\" bins/synthetic/field_snapshot.bin 2>/dev/null" | awk '/class .* dart_TestClass( :: dart_TestInterface)?$/ { cls = 1 } /class .* dart_TestClass :: dart_TestInterface$/ { super = 1 } /method.* compute$/ { method = 1 } /field.* fieldA$/ { field = 1 } /^pf \[16\]\.qppp fieldA items genericItems callback$/ { type = 1 } END { print "class=" cls + 0; print "super=" super + 0; print "method=" method + 0; print "field=" field + 0; print "type=" type + 0 }'
EOF
EXPECT=<<EOF
class=1
super=1
method=1
field=1
type=1
EOF
RUN
