Serialization.cpp 359 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "FileIOBaseTestTypes.h"
  9. #include <AzCore/Asset/AssetManager.h>
  10. #include <AzCore/Asset/AssetSerializer.h>
  11. #include <AzCore/Component/ComponentApplicationBus.h>
  12. #include <AzCore/Serialization/SerializeContext.h>
  13. #include <AzCore/Serialization/EditContext.h>
  14. #include <AzCore/Serialization/DataOverlayProviderMsgs.h>
  15. #include <AzCore/Serialization/DataOverlayInstanceMsgs.h>
  16. #include <AzCore/Serialization/DynamicSerializableField.h>
  17. #include <AzCore/Serialization/Utils.h>
  18. #include <AzCore/Serialization/ObjectStream.h>
  19. #include <AzCore/Serialization/DataPatch.h>
  20. #include <AzCore/std/containers/vector.h>
  21. #include <AzCore/std/containers/fixed_vector.h>
  22. #include <AzCore/std/containers/array.h>
  23. #include <AzCore/std/containers/list.h>
  24. #include <AzCore/std/containers/forward_list.h>
  25. #include <AzCore/std/containers/set.h>
  26. #include <AzCore/std/containers/unordered_set.h>
  27. #include <AzCore/std/containers/unordered_map.h>
  28. #include <AzCore/std/containers/bitset.h>
  29. #include <AzCore/std/containers/array.h>
  30. #include <AzCore/std/functional.h>
  31. #include <AzCore/std/smart_ptr/intrusive_ptr.h>
  32. #include <AzCore/std/smart_ptr/shared_ptr.h>
  33. #include <AzCore/std/smart_ptr/unique_ptr.h>
  34. #include <AzCore/std/smart_ptr/make_shared.h>
  35. #include <AzCore/std/optional.h>
  36. #include <AzCore/std/tuple.h>
  37. #include <AzCore/Component/ComponentApplication.h>
  38. #include <AzCore/Component/ComponentBus.h>
  39. #include <AzCore/Math/Crc.h>
  40. #include <AzCore/Math/Uuid.h>
  41. #include <AzCore/Math/Vector2.h>
  42. #include <AzCore/Math/Vector3.h>
  43. #include <AzCore/Math/Vector4.h>
  44. #include <AzCore/Math/Transform.h>
  45. #include <AzCore/Math/Matrix3x3.h>
  46. #include <AzCore/Math/Matrix4x4.h>
  47. #include <AzCore/Math/Quaternion.h>
  48. #include <AzCore/Math/Aabb.h>
  49. #include <AzCore/Math/Plane.h>
  50. #include <AzCore/IO/GenericStreams.h>
  51. #include <AzCore/IO/Streamer/Streamer.h>
  52. #include <AzCore/IO/SystemFile.h>
  53. #include <AzCore/IO/ByteContainerStream.h>
  54. #include <AzCore/IO/Streamer/StreamerComponent.h>
  55. #include <AzCore/RTTI/AttributeReader.h>
  56. #include <AzCore/std/string/conversions.h>
  57. #include <AzCore/UnitTest/TestTypes.h>
  58. #include <AZTestShared/Utils/Utils.h>
  59. namespace SerializeTestClasses {
  60. class MyClassBase1
  61. {
  62. public:
  63. AZ_RTTI(MyClassBase1, "{AA882C72-C7FB-4D19-A167-44BAF96C7D79}");
  64. static void Reflect(AZ::SerializeContext& sc)
  65. {
  66. sc.Class<MyClassBase1>()->
  67. Version(1)->
  68. Field("data", &MyClassBase1::m_data);
  69. }
  70. virtual ~MyClassBase1() {}
  71. virtual void Set(float v) = 0;
  72. float m_data{ 0.0f };
  73. };
  74. class MyClassBase2
  75. {
  76. public:
  77. AZ_RTTI(MyClassBase2, "{E2DE87D8-15FD-417B-B7E4-5BDF05EA7088}");
  78. static void Reflect(AZ::SerializeContext& sc)
  79. {
  80. sc.Class<MyClassBase2>()->
  81. Version(1)->
  82. Field("data", &MyClassBase2::m_data);
  83. }
  84. virtual ~MyClassBase2() {}
  85. virtual void Set(float v) = 0;
  86. float m_data{ 0.0f };
  87. };
  88. class MyClassBase3
  89. {
  90. public:
  91. AZ_RTTI(MyClassBase3, "{E9308B39-14B9-4760-A141-EBECFE8891D5}");
  92. // enum class EnumField : char // Test C++11
  93. enum EnumField
  94. {
  95. Option1,
  96. Option2,
  97. Option3,
  98. };
  99. static void Reflect(AZ::SerializeContext& sc)
  100. {
  101. sc.Class<MyClassBase3>()->
  102. Version(1)->
  103. Field("data", &MyClassBase3::m_data)->
  104. Field("enum", &MyClassBase3::m_enum);
  105. }
  106. virtual ~MyClassBase3() {}
  107. virtual void Set(float v) = 0;
  108. float m_data{ 0.f };
  109. EnumField m_enum{ Option1 };
  110. };
  111. class MyClassMix
  112. : public MyClassBase1
  113. , public MyClassBase2
  114. , public MyClassBase3
  115. {
  116. public:
  117. AZ_RTTI(MyClassMix, "{A15003C6-797A-41BB-9D21-716DF0678D02}", MyClassBase1, MyClassBase2, MyClassBase3);
  118. AZ_CLASS_ALLOCATOR(MyClassMix, AZ::SystemAllocator);
  119. static void Reflect(AZ::SerializeContext& sc)
  120. {
  121. sc.Class<MyClassMix, MyClassBase1, MyClassBase2, MyClassBase3>()->
  122. Field("dataMix", &MyClassMix::m_dataMix);
  123. }
  124. void Set(float v) override
  125. {
  126. m_dataMix = v;
  127. MyClassBase1::m_data = v * 2;
  128. MyClassBase2::m_data = v * 3;
  129. MyClassBase3::m_data = v * 4;
  130. }
  131. bool operator==(const MyClassMix& rhs) const
  132. {
  133. return m_dataMix == rhs.m_dataMix
  134. && MyClassBase1::m_data == rhs.MyClassBase1::m_data
  135. && MyClassBase2::m_data == rhs.MyClassBase2::m_data
  136. && MyClassBase3::m_data == rhs.MyClassBase3::m_data;
  137. }
  138. double m_dataMix{ 0. };
  139. };
  140. class MyClassMixNew
  141. : public MyClassBase1
  142. , public MyClassBase2
  143. , public MyClassBase3
  144. {
  145. public:
  146. AZ_RTTI(MyClassMixNew, "{A15003C6-797A-41BB-9D21-716DF0678D02}", MyClassBase1, MyClassBase2, MyClassBase3); // Use the same UUID as MyClassMix for conversion test
  147. AZ_CLASS_ALLOCATOR(MyClassMixNew, AZ::SystemAllocator);
  148. static bool ConvertOldVersions(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
  149. {
  150. if (classElement.GetVersion() == 0)
  151. {
  152. // convert from version 0
  153. float sum = 0.f;
  154. for (int i = 0; i < classElement.GetNumSubElements(); )
  155. {
  156. AZ::SerializeContext::DataElementNode& elementNode = classElement.GetSubElement(i);
  157. if (elementNode.GetName() == AZ_CRC("dataMix", 0x041bcc8d))
  158. {
  159. classElement.RemoveElement(i);
  160. continue;
  161. }
  162. else
  163. {
  164. // go through our base classes adding their data members
  165. for (int j = 0; j < elementNode.GetNumSubElements(); ++j)
  166. {
  167. AZ::SerializeContext::DataElementNode& dataNode = elementNode.GetSubElement(j);
  168. if (dataNode.GetName() == AZ_CRC("data", 0xadf3f363))
  169. {
  170. float data;
  171. bool result = dataNode.GetData(data);
  172. EXPECT_TRUE(result);
  173. sum += data;
  174. break;
  175. }
  176. }
  177. }
  178. ++i;
  179. }
  180. // add a new element
  181. int newElement = classElement.AddElement(context, "baseSum", AZ::SerializeTypeInfo<float>::GetUuid());
  182. if (newElement != -1)
  183. {
  184. classElement.GetSubElement(newElement).SetData(context, sum);
  185. }
  186. return true;
  187. }
  188. return false; // just discard unknown versions
  189. }
  190. static void Reflect(AZ::SerializeContext& sc)
  191. {
  192. sc.Class<MyClassMixNew, MyClassBase1, MyClassBase2, MyClassBase3>()->
  193. Version(1, &MyClassMixNew::ConvertOldVersions)->
  194. Field("baseSum", &MyClassMixNew::m_baseSum);
  195. }
  196. void Set(float v) override
  197. {
  198. MyClassBase1::m_data = v * 2;
  199. MyClassBase2::m_data = v * 3;
  200. MyClassBase3::m_data = v * 4;
  201. m_baseSum = v * 2 + v * 3 + v * 4;
  202. }
  203. bool operator==(const MyClassMixNew& rhs)
  204. {
  205. return m_baseSum == rhs.m_baseSum
  206. && MyClassBase1::m_data == rhs.MyClassBase1::m_data
  207. && MyClassBase2::m_data == rhs.MyClassBase2::m_data
  208. && MyClassBase3::m_data == rhs.MyClassBase3::m_data;
  209. }
  210. float m_baseSum;
  211. };
  212. class MyClassMix2
  213. : public MyClassBase2
  214. , public MyClassBase3
  215. , public MyClassBase1
  216. {
  217. public:
  218. AZ_RTTI(MyClassMix2, "{D402F58C-812C-4c20-ABE5-E4AF43D66A71}", MyClassBase2, MyClassBase3, MyClassBase1);
  219. AZ_CLASS_ALLOCATOR(MyClassMix2, AZ::SystemAllocator);
  220. static void Reflect(AZ::SerializeContext& sc)
  221. {
  222. sc.Class<MyClassMix2, MyClassBase2, MyClassBase3, MyClassBase1>()->
  223. Field("dataMix", &MyClassMix2::m_dataMix);
  224. }
  225. void Set(float v) override
  226. {
  227. m_dataMix = v;
  228. MyClassBase1::m_data = v * 2;
  229. MyClassBase2::m_data = v * 3;
  230. MyClassBase3::m_data = v * 4;
  231. }
  232. bool operator==(const MyClassMix2& rhs)
  233. {
  234. return m_dataMix == rhs.m_dataMix
  235. && MyClassBase1::m_data == rhs.MyClassBase1::m_data
  236. && MyClassBase2::m_data == rhs.MyClassBase2::m_data
  237. && MyClassBase3::m_data == rhs.MyClassBase3::m_data;
  238. }
  239. double m_dataMix;
  240. };
  241. class MyClassMix3
  242. : public MyClassBase3
  243. , public MyClassBase1
  244. , public MyClassBase2
  245. {
  246. public:
  247. AZ_RTTI(MyClassMix3, "{4179331A-F4AB-49D2-A14B-06B80CE5952C}", MyClassBase3, MyClassBase1, MyClassBase2);
  248. AZ_CLASS_ALLOCATOR(MyClassMix3, AZ::SystemAllocator);
  249. static void Reflect(AZ::SerializeContext& sc)
  250. {
  251. sc.Class<MyClassMix3, MyClassBase3, MyClassBase1, MyClassBase2>()->
  252. Field("dataMix", &MyClassMix3::m_dataMix);
  253. }
  254. void Set(float v) override
  255. {
  256. m_dataMix = v;
  257. MyClassBase1::m_data = v * 2;
  258. MyClassBase2::m_data = v * 3;
  259. MyClassBase3::m_data = v * 4;
  260. }
  261. bool operator==(const MyClassMix3& rhs)
  262. {
  263. return m_dataMix == rhs.m_dataMix
  264. && MyClassBase1::m_data == rhs.MyClassBase1::m_data
  265. && MyClassBase2::m_data == rhs.MyClassBase2::m_data
  266. && MyClassBase3::m_data == rhs.MyClassBase3::m_data;
  267. }
  268. double m_dataMix;
  269. };
  270. struct UnregisteredBaseClass
  271. {
  272. AZ_RTTI(UnregisteredBaseClass, "{19C26D43-4512-40D8-B5F5-1A69872252D4}");
  273. virtual ~UnregisteredBaseClass() {}
  274. virtual void Func() = 0;
  275. };
  276. struct ChildOfUndeclaredBase
  277. : public UnregisteredBaseClass
  278. {
  279. AZ_CLASS_ALLOCATOR(ChildOfUndeclaredBase, AZ::SystemAllocator);
  280. AZ_RTTI(ChildOfUndeclaredBase, "{85268A9C-1CC1-49C6-9E65-9B5089EBC4CD}", UnregisteredBaseClass);
  281. ChildOfUndeclaredBase()
  282. : m_data(0) {}
  283. static void Reflect(AZ::SerializeContext& sc)
  284. {
  285. sc.Class<ChildOfUndeclaredBase>()->
  286. Field("data", &ChildOfUndeclaredBase::m_data);
  287. }
  288. void Func() override {}
  289. int m_data;
  290. };
  291. struct PolymorphicMemberPointers
  292. {
  293. AZ_CLASS_ALLOCATOR(PolymorphicMemberPointers, AZ::SystemAllocator);
  294. AZ_TYPE_INFO(PolymorphicMemberPointers, "{06864A72-A2E2-40E1-A8F9-CC6C59BFBF2D}")
  295. static void Reflect(AZ::SerializeContext& sc)
  296. {
  297. sc.Class<PolymorphicMemberPointers>()->
  298. Field("base1Mix", &PolymorphicMemberPointers::m_pBase1MyClassMix)->
  299. Field("base1Mix2", &PolymorphicMemberPointers::m_pBase1MyClassMix2)->
  300. Field("base1Mix3", &PolymorphicMemberPointers::m_pBase1MyClassMix3)->
  301. Field("base2Mix", &PolymorphicMemberPointers::m_pBase2MyClassMix)->
  302. Field("base2Mix2", &PolymorphicMemberPointers::m_pBase2MyClassMix2)->
  303. Field("base2Mix3", &PolymorphicMemberPointers::m_pBase2MyClassMix3)->
  304. Field("base3Mix", &PolymorphicMemberPointers::m_pBase3MyClassMix)->
  305. Field("base3Mix2", &PolymorphicMemberPointers::m_pBase3MyClassMix2)->
  306. Field("base3Mix3", &PolymorphicMemberPointers::m_pBase3MyClassMix3)->
  307. Field("memberWithUndeclaredBase", &PolymorphicMemberPointers::m_pMemberWithUndeclaredBase);
  308. }
  309. PolymorphicMemberPointers()
  310. {
  311. m_pBase1MyClassMix = nullptr;
  312. m_pBase1MyClassMix2 = nullptr;
  313. m_pBase1MyClassMix3 = nullptr;
  314. m_pBase2MyClassMix = nullptr;
  315. m_pBase2MyClassMix2 = nullptr;
  316. m_pBase2MyClassMix3 = nullptr;
  317. m_pBase3MyClassMix = nullptr;
  318. m_pBase3MyClassMix2 = nullptr;
  319. m_pBase3MyClassMix3 = nullptr;
  320. m_pMemberWithUndeclaredBase = nullptr;
  321. }
  322. virtual ~PolymorphicMemberPointers()
  323. {
  324. if (m_pBase1MyClassMix)
  325. {
  326. Unset();
  327. }
  328. }
  329. void Set()
  330. {
  331. (m_pBase1MyClassMix = aznew MyClassMix)->Set(10.f);
  332. (m_pBase1MyClassMix2 = aznew MyClassMix2)->Set(20.f);
  333. (m_pBase1MyClassMix3 = aznew MyClassMix3)->Set(30.f);
  334. (m_pBase2MyClassMix = aznew MyClassMix)->Set(100.f);
  335. (m_pBase2MyClassMix2 = aznew MyClassMix2)->Set(200.f);
  336. (m_pBase2MyClassMix3 = aznew MyClassMix3)->Set(300.f);
  337. (m_pBase3MyClassMix = aznew MyClassMix)->Set(1000.f);
  338. (m_pBase3MyClassMix2 = aznew MyClassMix2)->Set(2000.f);
  339. (m_pBase3MyClassMix3 = aznew MyClassMix3)->Set(3000.f);
  340. (m_pMemberWithUndeclaredBase = aznew ChildOfUndeclaredBase)->m_data = 1234;
  341. }
  342. void Unset()
  343. {
  344. delete m_pBase1MyClassMix; m_pBase1MyClassMix = nullptr;
  345. delete m_pBase1MyClassMix2;
  346. delete m_pBase1MyClassMix3;
  347. delete m_pBase2MyClassMix;
  348. delete m_pBase2MyClassMix2;
  349. delete m_pBase2MyClassMix3;
  350. delete m_pBase3MyClassMix;
  351. delete m_pBase3MyClassMix2;
  352. delete m_pBase3MyClassMix3;
  353. delete m_pMemberWithUndeclaredBase;
  354. }
  355. MyClassBase1* m_pBase1MyClassMix;
  356. MyClassBase1* m_pBase1MyClassMix2;
  357. MyClassBase1* m_pBase1MyClassMix3;
  358. MyClassBase2* m_pBase2MyClassMix;
  359. MyClassBase2* m_pBase2MyClassMix2;
  360. MyClassBase2* m_pBase2MyClassMix3;
  361. MyClassBase2* m_pBase3MyClassMix;
  362. MyClassBase2* m_pBase3MyClassMix2;
  363. MyClassBase2* m_pBase3MyClassMix3;
  364. ChildOfUndeclaredBase* m_pMemberWithUndeclaredBase;
  365. };
  366. struct BaseNoRtti
  367. {
  368. AZ_CLASS_ALLOCATOR(BaseNoRtti, AZ::SystemAllocator);
  369. AZ_TYPE_INFO(BaseNoRtti, "{E57A19BA-EF68-4AFF-A534-2C90B9583781}")
  370. static void Reflect(AZ::SerializeContext& sc)
  371. {
  372. sc.Class<BaseNoRtti>()->
  373. Field("data", &BaseNoRtti::m_data);
  374. }
  375. void Set() { m_data = false; }
  376. bool operator==(const BaseNoRtti& rhs) const { return m_data == rhs.m_data; }
  377. bool m_data;
  378. };
  379. struct BaseRtti
  380. {
  381. AZ_RTTI(BaseRtti, "{2581047D-26EC-4969-8354-BA0A4510C51A}");
  382. AZ_CLASS_ALLOCATOR(BaseRtti, AZ::SystemAllocator);
  383. static void Reflect(AZ::SerializeContext& sc)
  384. {
  385. sc.Class<BaseRtti>()->
  386. Field("data", &BaseRtti::m_data);
  387. }
  388. virtual ~BaseRtti() {}
  389. void Set() { m_data = true; }
  390. bool operator==(const BaseRtti& rhs) const { return m_data == rhs.m_data; }
  391. bool m_data;
  392. };
  393. struct DerivedNoRtti
  394. : public BaseNoRtti
  395. {
  396. AZ_CLASS_ALLOCATOR(DerivedNoRtti, AZ::SystemAllocator);
  397. AZ_TYPE_INFO(DerivedNoRtti, "{B5E77A22-9C6F-4755-A074-FEFD8AC2C971}")
  398. static void Reflect(AZ::SerializeContext& sc)
  399. {
  400. sc.Class<DerivedNoRtti, BaseNoRtti>()->
  401. Field("basesRtti", &DerivedNoRtti::m_basesRtti)->
  402. Field("basesNoRtti", &DerivedNoRtti::m_basesNoRtti);
  403. }
  404. void Set() { m_basesRtti = 0; m_basesNoRtti = 1; BaseNoRtti::Set(); }
  405. bool operator==(const DerivedNoRtti& rhs) const { return m_basesRtti == rhs.m_basesRtti && m_basesNoRtti == rhs.m_basesNoRtti && BaseNoRtti::operator==(static_cast<const BaseNoRtti&>(rhs)); }
  406. int m_basesRtti;
  407. int m_basesNoRtti;
  408. };
  409. struct DerivedRtti
  410. : public BaseRtti
  411. {
  412. AZ_RTTI(DerivedRtti, "{A14C419C-6F25-46A6-8D17-7777893073EF}", BaseRtti);
  413. AZ_CLASS_ALLOCATOR(DerivedRtti, AZ::SystemAllocator);
  414. static void Reflect(AZ::SerializeContext& sc)
  415. {
  416. sc.Class<DerivedRtti, BaseRtti>()->
  417. Field("basesRtti", &DerivedRtti::m_basesRtti)->
  418. Field("basesNoRtti", &DerivedRtti::m_basesNoRtti);
  419. }
  420. void Set() { m_basesRtti = 1; m_basesNoRtti = 0; BaseRtti::Set(); }
  421. bool operator==(const DerivedRtti& rhs) const { return m_basesRtti == rhs.m_basesRtti && m_basesNoRtti == rhs.m_basesNoRtti && BaseRtti::operator==(static_cast<const BaseRtti&>(rhs)); }
  422. int m_basesRtti;
  423. int m_basesNoRtti;
  424. };
  425. struct DerivedMix
  426. : public BaseNoRtti
  427. , public BaseRtti
  428. {
  429. AZ_RTTI(DerivedMix, "{BED5293B-3B80-4CEC-BB0F-2E56F921F550}", BaseRtti);
  430. AZ_CLASS_ALLOCATOR(DerivedMix, AZ::SystemAllocator);
  431. static void Reflect(AZ::SerializeContext& sc)
  432. {
  433. sc.Class<DerivedMix, BaseNoRtti, BaseRtti>()->
  434. Field("basesRtti", &DerivedMix::m_basesRtti)->
  435. Field("basesNoRtti", &DerivedMix::m_basesNoRtti);
  436. }
  437. void Set() { m_basesRtti = 1; m_basesNoRtti = 1; BaseNoRtti::Set(); BaseRtti::Set(); }
  438. bool operator==(const DerivedMix& rhs) const { return m_basesRtti == rhs.m_basesRtti && m_basesNoRtti == rhs.m_basesNoRtti && BaseNoRtti::operator==(static_cast<const BaseNoRtti&>(rhs)) && BaseRtti::operator==(static_cast<const BaseRtti&>(rhs)); }
  439. int m_basesRtti;
  440. int m_basesNoRtti;
  441. };
  442. struct BaseProtected
  443. {
  444. AZ_TYPE_INFO(BaseProtected, "{c6e244d8-ffd8-4710-900b-1d3dc4043ffe}");
  445. int m_pad; // Make sure there is no offset assumptions, for base members and we offset properly with in the base class.
  446. int m_data;
  447. protected:
  448. BaseProtected(int data = 0)
  449. : m_data(data) {}
  450. };
  451. struct DerivedWithProtectedBase
  452. : public BaseProtected
  453. {
  454. AZ_TYPE_INFO(DerivedWithProtectedBase, "{ad736023-a491-440a-84e3-5c507c969673}");
  455. AZ_CLASS_ALLOCATOR(DerivedWithProtectedBase, AZ::SystemAllocator);
  456. DerivedWithProtectedBase(int data = 0)
  457. : BaseProtected(data)
  458. {}
  459. static void Reflect(AZ::SerializeContext& context)
  460. {
  461. // Expose base class field without reflecting the class
  462. context.Class<DerivedWithProtectedBase>()
  463. ->FieldFromBase<DerivedWithProtectedBase>("m_data", &DerivedWithProtectedBase::m_data);
  464. }
  465. };
  466. struct SmartPtrClass
  467. {
  468. AZ_CLASS_ALLOCATOR(SmartPtrClass, AZ::SystemAllocator);
  469. AZ_TYPE_INFO(SmartPtrClass, "{A0A2D0A8-8D5D-454D-BE92-684C92C05B06}")
  470. SmartPtrClass(int data = 0)
  471. : m_counter(0)
  472. , m_data(data) {}
  473. static void Reflect(AZ::SerializeContext& sc)
  474. {
  475. sc.Class<SmartPtrClass>()->
  476. Field("data", &SmartPtrClass::m_data);
  477. }
  478. //////////////////////////////////////////////////////////////////////////
  479. // For intrusive pointers
  480. void add_ref() { ++m_counter; }
  481. void release()
  482. {
  483. --m_counter;
  484. if (m_counter == 0)
  485. {
  486. delete this;
  487. }
  488. }
  489. int m_counter;
  490. //////////////////////////////////////////////////////////////////////////
  491. int m_data;
  492. };
  493. struct Generics
  494. {
  495. AZ_CLASS_ALLOCATOR(Generics, AZ::SystemAllocator);
  496. AZ_TYPE_INFO(Generics, "{ACA50B82-D04B-4ACF-9FF6-F780040C9EB9}")
  497. enum class GenericEnum
  498. {
  499. Value1 = 0x01,
  500. Value2 = 0x02,
  501. Value3 = 0x04,
  502. };
  503. static void Reflect(AZ::SerializeContext& sc)
  504. {
  505. sc.Class<Generics>()->
  506. Field("emptyTextData", &Generics::m_emptyTextData)->
  507. Field("textData", &Generics::m_textData)->
  508. Field("vectorInt", &Generics::m_vectorInt)->
  509. Field("vectorIntVector", &Generics::m_vectorIntVector)->
  510. Field("vectorEnum", &Generics::m_vectorEnum)->
  511. Field("fixedVectorInt", &Generics::m_fixedVectorInt)->
  512. Field("listInt", &Generics::m_listInt)->
  513. Field("forwardListInt", &Generics::m_forwardListInt)->
  514. Field("setInt", &Generics::m_setInt)->
  515. Field("usetInt", &Generics::m_usetInt)->
  516. Field("umultisetInt", &Generics::m_umultisetInt)->
  517. Field("mapIntFloat", &Generics::m_mapIntFloat)->
  518. Field("umapIntFloat", &Generics::m_umapIntFloat)->
  519. Field("umultimapIntFloat", &Generics::m_umultimapIntFloat)->
  520. Field("umapPolymorphic", &Generics::m_umapPolymorphic)->
  521. Field("byteStream", &Generics::m_byteStream)->
  522. Field("bitSet", &Generics::m_bitSet)->
  523. Field("sharedPtr", &Generics::m_sharedPtr)->
  524. Field("intrusivePtr", &Generics::m_intrusivePtr)->
  525. Field("uniquePtr", &Generics::m_uniquePtr)->
  526. Field("emptyInitTextData", &Generics::m_emptyInitTextData);
  527. }
  528. Generics()
  529. {
  530. m_emptyInitTextData = "Some init text";
  531. }
  532. ~Generics()
  533. {
  534. if (m_umapPolymorphic.size() > 0)
  535. {
  536. Unset();
  537. }
  538. }
  539. public:
  540. void Set()
  541. {
  542. m_emptyInitTextData = ""; // data was initialized, we set it to nothing (make sure we write empty strings)
  543. m_textData = "Random Text";
  544. m_vectorInt.push_back(1);
  545. m_vectorInt.push_back(2);
  546. m_vectorIntVector.emplace_back();
  547. m_vectorIntVector.back().push_back(5);
  548. m_vectorEnum.push_back(GenericEnum::Value3);
  549. m_vectorEnum.push_back(GenericEnum::Value1);
  550. m_vectorEnum.push_back(GenericEnum::Value3);
  551. m_vectorEnum.push_back(GenericEnum::Value2);
  552. m_fixedVectorInt.push_back(1000);
  553. m_fixedVectorInt.push_back(2000);
  554. m_fixedVectorInt.push_back(3000);
  555. m_fixedVectorInt.push_back(4000);
  556. m_fixedVectorInt.push_back(5000);
  557. m_listInt.push_back(10);
  558. m_forwardListInt.push_front(15);
  559. m_setInt.insert(20);
  560. m_usetInt.insert(20);
  561. m_umultisetInt.insert(20);
  562. m_umultisetInt.insert(20);
  563. m_mapIntFloat.insert(AZStd::make_pair(1, 5.f));
  564. m_mapIntFloat.insert(AZStd::make_pair(2, 10.f));
  565. m_umapIntFloat.insert(AZStd::make_pair(1, 5.f));
  566. m_umapIntFloat.insert(AZStd::make_pair(2, 10.f));
  567. m_umultimapIntFloat.insert(AZStd::make_pair(1, 5.f));
  568. m_umultimapIntFloat.insert(AZStd::make_pair(2, 10.f));
  569. m_umultimapIntFloat.insert(AZStd::make_pair(2, 20.f));
  570. m_umapPolymorphic.insert(AZStd::make_pair(1, aznew MyClassMix)).first->second->Set(100.f);
  571. m_umapPolymorphic.insert(AZStd::make_pair(2, aznew MyClassMix2)).first->second->Set(200.f);
  572. m_umapPolymorphic.insert(AZStd::make_pair(3, aznew MyClassMix3)).first->second->Set(300.f);
  573. AZ::u32 binaryData = 0xbad0f00d;
  574. m_byteStream.assign((AZ::u8*)&binaryData, (AZ::u8*)(&binaryData + 1));
  575. m_bitSet = AZStd::bitset<32>(AZStd::string("01011"));
  576. m_sharedPtr = AZStd::shared_ptr<SmartPtrClass>(aznew SmartPtrClass(122));
  577. m_intrusivePtr = AZStd::intrusive_ptr<SmartPtrClass>(aznew SmartPtrClass(233));
  578. m_uniquePtr = AZStd::unique_ptr<SmartPtrClass>(aznew SmartPtrClass(4242));
  579. }
  580. void Unset()
  581. {
  582. m_emptyTextData.set_capacity(0);
  583. m_emptyInitTextData.set_capacity(0);
  584. m_textData.set_capacity(0);
  585. m_vectorInt.set_capacity(0);
  586. m_vectorIntVector.set_capacity(0);
  587. m_vectorEnum.set_capacity(0);
  588. m_listInt.clear();
  589. m_forwardListInt.clear();
  590. m_setInt.clear();
  591. m_mapIntFloat.clear();
  592. for (AZStd::unordered_map<int, MyClassBase1*>::iterator it = m_umapPolymorphic.begin(); it != m_umapPolymorphic.end(); ++it)
  593. {
  594. delete it->second;
  595. }
  596. m_umapPolymorphic.clear();
  597. m_byteStream.set_capacity(0);
  598. m_bitSet.reset();
  599. m_sharedPtr.reset();
  600. m_intrusivePtr.reset();
  601. m_uniquePtr.reset();
  602. }
  603. AZStd::string m_emptyTextData;
  604. AZStd::string m_emptyInitTextData;
  605. AZStd::string m_textData;
  606. AZStd::vector<int> m_vectorInt;
  607. AZStd::vector<AZStd::vector<int> > m_vectorIntVector;
  608. AZStd::vector<GenericEnum> m_vectorEnum;
  609. AZStd::fixed_vector<int, 5> m_fixedVectorInt;
  610. AZStd::list<int> m_listInt;
  611. AZStd::forward_list<int> m_forwardListInt;
  612. AZStd::set<int> m_setInt;
  613. AZStd::map<int, float> m_mapIntFloat;
  614. AZStd::unordered_set<int> m_usetInt;
  615. AZStd::unordered_multiset<int> m_umultisetInt;
  616. AZStd::unordered_map<int, float> m_umapIntFloat;
  617. AZStd::unordered_map<int, MyClassBase1*> m_umapPolymorphic;
  618. AZStd::unordered_multimap<int, float> m_umultimapIntFloat;
  619. AZStd::vector<AZ::u8> m_byteStream;
  620. AZStd::bitset<32> m_bitSet;
  621. AZStd::shared_ptr<SmartPtrClass> m_sharedPtr;
  622. AZStd::intrusive_ptr<SmartPtrClass> m_intrusivePtr;
  623. AZStd::unique_ptr<SmartPtrClass> m_uniquePtr;
  624. };
  625. struct ElementOverrideType
  626. {
  627. AZ_RTTI(ElementOverrideType, "{BAA18B6C-3CB3-476C-8B41-21EA7CE1F4CF}");
  628. AZ_CLASS_ALLOCATOR(ElementOverrideType, AZ::SystemAllocator);
  629. virtual ~ElementOverrideType() = default;
  630. static AZ::ObjectStreamWriteOverrideResponse Writer(
  631. AZ::SerializeContext::EnumerateInstanceCallContext& callContext,
  632. const void* object,
  633. const AZ::SerializeContext::ClassData&,
  634. const AZ::SerializeContext::ClassElement*)
  635. {
  636. auto ptr = static_cast<const ElementOverrideType*>(object);
  637. if(ptr)
  638. {
  639. switch(ptr->m_field)
  640. {
  641. case 0:
  642. {
  643. float output{};
  644. callContext.m_context->EnumerateInstanceConst(&callContext, &output, azrtti_typeid<decltype(output)>(), nullptr, nullptr);
  645. return AZ::ObjectStreamWriteOverrideResponse::CompletedWrite;
  646. }
  647. case 1:
  648. return AZ::ObjectStreamWriteOverrideResponse::FallbackToDefaultWrite;
  649. }
  650. }
  651. return AZ::ObjectStreamWriteOverrideResponse::AbortWrite;
  652. }
  653. static void Reflect(AZ::SerializeContext& sc)
  654. {
  655. sc.Class<ElementOverrideType>()
  656. ->Attribute(AZ::SerializeContextAttributes::ObjectStreamWriteElementOverride, &ElementOverrideType::Writer)
  657. ->Field("field", &ElementOverrideType::m_field);
  658. }
  659. int m_field = 0;
  660. };
  661. } //SerializeTestClasses
  662. namespace AZ
  663. {
  664. AZ_TYPE_INFO_SPECIALIZE(SerializeTestClasses::Generics::GenericEnum, "{1D382230-EF25-4583-812B-7576334AB1A9}");
  665. }
  666. namespace SerializeTestClasses
  667. {
  668. struct GenericsNew
  669. {
  670. AZ_CLASS_ALLOCATOR(GenericsNew, AZ::SystemAllocator);
  671. AZ_TYPE_INFO(GenericsNew, "{ACA50B82-D04B-4ACF-9FF6-F780040C9EB9}") // Match Generics ID for conversion test
  672. static bool ConvertOldVersions(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
  673. {
  674. if (classElement.GetVersion() == 0)
  675. {
  676. // convert from version 0
  677. for (int i = 0; i < classElement.GetNumSubElements(); )
  678. {
  679. AZ::SerializeContext::DataElementNode& elementNode = classElement.GetSubElement(i);
  680. if (elementNode.GetName() == AZ_CRC("textData", 0xf322c69d))
  681. {
  682. AZStd::string text;
  683. bool result = elementNode.GetData(text);
  684. EXPECT_TRUE(result);
  685. int memberIdx = classElement.AddElement<AZStd::string>(context, "string");
  686. if (memberIdx != -1)
  687. {
  688. AZ::SerializeContext::DataElementNode& memberNode = classElement.GetSubElement(memberIdx);
  689. memberNode.SetData(context, text);
  690. }
  691. classElement.RemoveElement(i);
  692. }
  693. else if (elementNode.GetName() == AZ_CRC("emptyTextData", 0x61d55942))
  694. {
  695. AZStd::string text;
  696. bool result = elementNode.GetData(text);
  697. EXPECT_TRUE(result);
  698. EXPECT_TRUE(text.empty()); // this should be empty
  699. classElement.RemoveElement(i);
  700. }
  701. else if (elementNode.GetName() == AZ_CRC("vectorInt", 0xe61292a9))
  702. {
  703. int memberIdx = classElement.AddElement<AZStd::vector<int> >(context, "vectorInt2");
  704. if (memberIdx != -1)
  705. {
  706. AZ::SerializeContext::DataElementNode& memberNode = classElement.GetSubElement(memberIdx);
  707. for (int j = 0; j < elementNode.GetNumSubElements(); ++j)
  708. {
  709. AZ::SerializeContext::DataElementNode& vecElemNode = elementNode.GetSubElement(j);
  710. int val;
  711. bool result = vecElemNode.GetData(val);
  712. EXPECT_TRUE(result);
  713. int elemIdx = memberNode.AddElement<int>(context, AZ::SerializeContext::IDataContainer::GetDefaultElementName());
  714. if (elemIdx != -1)
  715. {
  716. memberNode.GetSubElement(elemIdx).SetData(context, val * 2);
  717. }
  718. }
  719. }
  720. classElement.RemoveElement(i);
  721. }
  722. else if (elementNode.GetName() == AZ_CRC("vectorIntVector", 0xd9c44f0b))
  723. {
  724. // add a new element
  725. int newListIntList = classElement.AddElement<AZStd::list<AZStd::list<int> > >(context, "listIntList");
  726. if (newListIntList != -1)
  727. {
  728. AZ::SerializeContext::DataElementNode& listIntListNode = classElement.GetSubElement(newListIntList);
  729. for (int j = 0; j < elementNode.GetNumSubElements(); ++j)
  730. {
  731. AZ::SerializeContext::DataElementNode& subVecNode = elementNode.GetSubElement(j);
  732. int newListInt = listIntListNode.AddElement<AZStd::list<int> >(context, AZ::SerializeContext::IDataContainer::GetDefaultElementName());
  733. if (newListInt != -1)
  734. {
  735. AZ::SerializeContext::DataElementNode& listIntNode = listIntListNode.GetSubElement(newListInt);
  736. for (int k = 0; k < subVecNode.GetNumSubElements(); ++k)
  737. {
  738. AZ::SerializeContext::DataElementNode& intNode = subVecNode.GetSubElement(k);
  739. int val;
  740. bool result = intNode.GetData(val);
  741. EXPECT_TRUE(result);
  742. int newInt = listIntNode.AddElement<int>(context, AZ::SerializeContext::IDataContainer::GetDefaultElementName());
  743. if (newInt != -1)
  744. {
  745. listIntNode.GetSubElement(newInt).SetData(context, val);
  746. }
  747. }
  748. }
  749. }
  750. }
  751. classElement.RemoveElement(i);
  752. }
  753. else if (elementNode.GetName() == AZ_CRC("emptyInitTextData", 0x17b55a4f)
  754. || elementNode.GetName() == AZ_CRC("listInt", 0x4fbe090a)
  755. || elementNode.GetName() == AZ_CRC("setInt", 0x62eb1299)
  756. || elementNode.GetName() == AZ_CRC("usetInt")
  757. || elementNode.GetName() == AZ_CRC("umultisetInt")
  758. || elementNode.GetName() == AZ_CRC("mapIntFloat", 0xb558ac3f)
  759. || elementNode.GetName() == AZ_CRC("umapIntFloat")
  760. || elementNode.GetName() == AZ_CRC("umultimapIntFloat")
  761. || elementNode.GetName() == AZ_CRC("byteStream", 0xda272a22)
  762. || elementNode.GetName() == AZ_CRC("bitSet", 0x9dd4d1cb)
  763. || elementNode.GetName() == AZ_CRC("sharedPtr", 0x033de7f0)
  764. || elementNode.GetName() == AZ_CRC("intrusivePtr", 0x20733e45)
  765. || elementNode.GetName() == AZ_CRC("uniquePtr", 0xdb6f5bd3)
  766. || elementNode.GetName() == AZ_CRC("forwardListInt", 0xf54c1600)
  767. || elementNode.GetName() == AZ_CRC("fixedVectorInt", 0xf7108293)
  768. || elementNode.GetName() == AZ_CRC("vectorEnum"))
  769. {
  770. classElement.RemoveElement(i);
  771. }
  772. else
  773. {
  774. ++i;
  775. }
  776. }
  777. // add a new element
  778. int newElement = classElement.AddElement(context, "newInt", AZ::SerializeTypeInfo<int>::GetUuid());
  779. if (newElement != -1)
  780. {
  781. classElement.GetSubElement(newElement).SetData(context, 50);
  782. }
  783. return true;
  784. }
  785. return false; // just discard unknown versions
  786. }
  787. static void Reflect(AZ::SerializeContext& sc)
  788. {
  789. sc.Class<GenericsNew>()->
  790. Version(1, &GenericsNew::ConvertOldVersions)->
  791. Field("string", &GenericsNew::m_string)->
  792. Field("vectorInt2", &GenericsNew::m_vectorInt2)->
  793. Field("listIntList", &GenericsNew::m_listIntList)->
  794. Field("umapPolymorphic", &GenericsNew::m_umapPolymorphic)->
  795. Field("newInt", &GenericsNew::m_newInt);
  796. }
  797. ~GenericsNew()
  798. {
  799. if (m_umapPolymorphic.size() > 0)
  800. {
  801. Unset();
  802. }
  803. }
  804. void Set()
  805. {
  806. m_string = "Random Text";
  807. m_vectorInt2.push_back(1 * 2);
  808. m_vectorInt2.push_back(2 * 2);
  809. m_listIntList.emplace_back();
  810. m_listIntList.back().push_back(5);
  811. m_umapPolymorphic.insert(AZStd::make_pair(1, aznew MyClassMixNew)).first->second->Set(100.f);
  812. m_umapPolymorphic.insert(AZStd::make_pair(2, aznew MyClassMix2)).first->second->Set(200.f);
  813. m_umapPolymorphic.insert(AZStd::make_pair(3, aznew MyClassMix3)).first->second->Set(300.f);
  814. m_newInt = 50;
  815. }
  816. void Unset()
  817. {
  818. m_string.set_capacity(0);
  819. m_vectorInt2.set_capacity(0);
  820. m_listIntList.clear();
  821. for (AZStd::unordered_map<int, MyClassBase1*>::iterator it = m_umapPolymorphic.begin(); it != m_umapPolymorphic.end(); ++it)
  822. {
  823. delete it->second;
  824. }
  825. m_umapPolymorphic.clear();
  826. }
  827. AZStd::string m_string; // rename m_textData to m_string
  828. AZStd::vector<int> m_vectorInt2; // rename m_vectorInt to m_vectorInt2 and multiply all values by 2
  829. AZStd::list<AZStd::list<int> > m_listIntList; // convert vector<vector<int>> to list<list<int>>
  830. AZStd::unordered_map<int, MyClassBase1*> m_umapPolymorphic; // using new version of MyClassMix
  831. int m_newInt; // added new member
  832. };
  833. class ClassThatAllocatesMemoryInDefaultCtor final
  834. {
  835. public:
  836. AZ_RTTI(ClassThatAllocatesMemoryInDefaultCtor, "{CF9B593D-A19E-467B-8370-28AF68D2F345}")
  837. AZ_CLASS_ALLOCATOR(ClassThatAllocatesMemoryInDefaultCtor, AZ::SystemAllocator)
  838. ClassThatAllocatesMemoryInDefaultCtor()
  839. : m_data(aznew InstanceTracker)
  840. {
  841. }
  842. ~ClassThatAllocatesMemoryInDefaultCtor()
  843. {
  844. delete m_data;
  845. }
  846. static void Reflect(AZ::SerializeContext& sc)
  847. {
  848. sc.Class<InstanceTracker>();
  849. sc.Class<ClassThatAllocatesMemoryInDefaultCtor>()->
  850. Field("data", &ClassThatAllocatesMemoryInDefaultCtor::m_data)
  851. ;
  852. }
  853. class InstanceTracker final
  854. {
  855. public:
  856. AZ_RTTI(InstanceTracker, "{DED6003B-11E0-454C-B170-4889697815A0}");
  857. AZ_CLASS_ALLOCATOR(InstanceTracker, AZ::SystemAllocator);
  858. InstanceTracker()
  859. {
  860. ++s_instanceCount;
  861. }
  862. ~InstanceTracker()
  863. {
  864. --s_instanceCount;
  865. }
  866. InstanceTracker(const InstanceTracker&) = delete;
  867. InstanceTracker(InstanceTracker&&) = delete;
  868. static AZStd::atomic_int s_instanceCount;
  869. };
  870. private:
  871. const InstanceTracker* m_data;
  872. };
  873. AZStd::atomic_int ClassThatAllocatesMemoryInDefaultCtor::InstanceTracker::s_instanceCount(0);
  874. } // namespace SerializeTestClasses
  875. namespace ContainerElementDeprecationTestData
  876. {
  877. using namespace AZ;
  878. // utility classes for testing what happens to container elements, when they are deprecated.
  879. class BaseClass
  880. {
  881. public:
  882. AZ_RTTI(BaseClass, "{B736AD73-E627-467D-A779-7B942D2B5359}");
  883. AZ_CLASS_ALLOCATOR(BaseClass, SystemAllocator);
  884. virtual ~BaseClass() {}
  885. static void Reflect(ReflectContext* context)
  886. {
  887. if (auto serializeContext = azrtti_cast<SerializeContext*>(context))
  888. {
  889. serializeContext->Class<BaseClass>();
  890. }
  891. }
  892. };
  893. class DerivedClass1 : public BaseClass
  894. {
  895. public:
  896. AZ_RTTI(DerivedClass1, "{E55D26B8-96B9-4918-94F0-5ABCA29F2508}", BaseClass);
  897. AZ_CLASS_ALLOCATOR(DerivedClass1, SystemAllocator);
  898. static void Reflect(ReflectContext* context)
  899. {
  900. if (auto serializeContext = azrtti_cast<SerializeContext*>(context))
  901. {
  902. serializeContext->Class<DerivedClass1, BaseClass>();
  903. }
  904. }
  905. };
  906. class DerivedClass2 : public BaseClass
  907. {
  908. public:
  909. AZ_RTTI(DerivedClass2, "{91F6C9A1-1EB1-477E-99FC-41A35FE9CF0B}", BaseClass);
  910. AZ_CLASS_ALLOCATOR(DerivedClass2, SystemAllocator);
  911. static void Reflect(ReflectContext* context)
  912. {
  913. if (auto serializeContext = azrtti_cast<SerializeContext*>(context))
  914. {
  915. serializeContext->Class<DerivedClass2, BaseClass>();
  916. }
  917. }
  918. };
  919. class DerivedClass3 : public BaseClass
  920. {
  921. public:
  922. AZ_RTTI(DerivedClass3, "{1399CC2D-D525-4061-B190-5FCD82FCC161}", BaseClass);
  923. AZ_CLASS_ALLOCATOR(DerivedClass3, AZ::SystemAllocator);
  924. static void Reflect(ReflectContext* context)
  925. {
  926. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  927. {
  928. serializeContext->Class<DerivedClass3, BaseClass>();
  929. }
  930. }
  931. };
  932. static bool ConvertDerivedClass2ToDerivedClass3(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
  933. {
  934. classElement.Convert(context, AZ::AzTypeInfo<DerivedClass3>::Uuid());
  935. return true;
  936. }
  937. class ClassWithAVectorOfBaseClasses final
  938. {
  939. public:
  940. AZ_RTTI(ClassWithAVectorOfBaseClasses, "{B62A3327-8BEE-43BD-BA2C-32BAE9EE5455}");
  941. AZ_CLASS_ALLOCATOR(ClassWithAVectorOfBaseClasses, AZ::SystemAllocator);
  942. AZStd::vector<BaseClass*> m_vectorOfBaseClasses;
  943. ~ClassWithAVectorOfBaseClasses()
  944. {
  945. for (auto base : m_vectorOfBaseClasses)
  946. {
  947. delete base;
  948. }
  949. m_vectorOfBaseClasses = {};
  950. }
  951. static void Reflect(ReflectContext* context)
  952. {
  953. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  954. {
  955. BaseClass::Reflect(context);
  956. DerivedClass1::Reflect(context);
  957. DerivedClass2::Reflect(context);
  958. DerivedClass3::Reflect(context);
  959. serializeContext->Class<ClassWithAVectorOfBaseClasses>()
  960. ->Field("m_vectorOfBaseClasses", &ClassWithAVectorOfBaseClasses::m_vectorOfBaseClasses);
  961. }
  962. }
  963. };
  964. } // End of namespace ContainerElementDeprecationTestData
  965. namespace AZ {
  966. struct GenericClass
  967. {
  968. AZ_RTTI(GenericClass, "{F2DAA5D8-CA20-4DD4-8942-356458AF23A1}");
  969. virtual ~GenericClass() {}
  970. };
  971. class NullFactory
  972. : public SerializeContext::IObjectFactory
  973. {
  974. public:
  975. void* Create(const char* name) override
  976. {
  977. (void)name;
  978. AZ_Assert(false, "We cannot 'new' %s class, it should be used by value in a parent class!", name);
  979. return nullptr;
  980. }
  981. void Destroy(void*) override
  982. {
  983. // do nothing...
  984. }
  985. };
  986. template<>
  987. struct SerializeGenericTypeInfo<GenericClass>
  988. {
  989. class GenericClassGenericInfo
  990. : public GenericClassInfo
  991. {
  992. public:
  993. AZ_TYPE_INFO(GenericClassGenericInfo, "{7A26F864-DADC-4bdf-8C4C-A162349031C6}");
  994. GenericClassGenericInfo()
  995. : m_classData{ SerializeContext::ClassData::Create<GenericClass>("GenericClass", GetSpecializedTypeId(), &m_factory) }
  996. {
  997. }
  998. SerializeContext::ClassData* GetClassData() override
  999. {
  1000. return &m_classData;
  1001. }
  1002. size_t GetNumTemplatedArguments() override
  1003. {
  1004. return 1;
  1005. }
  1006. AZ::TypeId GetTemplatedTypeId(size_t element) override
  1007. {
  1008. (void)element;
  1009. return SerializeGenericTypeInfo<GenericClass>::GetClassTypeId();
  1010. }
  1011. AZ::TypeId GetSpecializedTypeId() const override
  1012. {
  1013. return azrtti_typeid<GenericClass>();
  1014. }
  1015. AZ::TypeId GetGenericTypeId() const override
  1016. {
  1017. return TYPEINFO_Uuid();
  1018. }
  1019. void Reflect(SerializeContext*) override {}
  1020. NullFactory m_factory;
  1021. SerializeContext::ClassData m_classData;
  1022. };
  1023. using ClassInfoType = GenericClassGenericInfo;
  1024. static ClassInfoType* GetGenericInfo()
  1025. {
  1026. return static_cast<ClassInfoType*>(GetCurrentSerializeContextModule().CreateGenericClassInfo<GenericClass>());
  1027. }
  1028. static AZ::TypeId GetClassTypeId()
  1029. {
  1030. return GetGenericInfo()->GetClassData()->m_typeId;
  1031. }
  1032. };
  1033. struct GenericChild
  1034. : public GenericClass
  1035. {
  1036. AZ_RTTI(GenericChild, "{086E933D-F3F9-41EA-9AA9-BA80D3DCF90A}", GenericClass);
  1037. ~GenericChild() override {}
  1038. };
  1039. template<>
  1040. struct SerializeGenericTypeInfo<GenericChild>
  1041. {
  1042. class GenericClassGenericInfo
  1043. : public GenericClassInfo
  1044. {
  1045. public:
  1046. AZ_TYPE_INFO(GenericClassGenericInfo, "{D1E1ACC0-7B90-48e9-999B-5825D4D4E397}");
  1047. GenericClassGenericInfo()
  1048. : m_classData{ SerializeContext::ClassData::Create<GenericChild>("GenericChild", GetSpecializedTypeId(), &m_factory) }
  1049. {
  1050. }
  1051. SerializeContext::ClassData* GetClassData() override
  1052. {
  1053. return &m_classData;
  1054. }
  1055. size_t GetNumTemplatedArguments() override
  1056. {
  1057. return 1;
  1058. }
  1059. AZ::TypeId GetTemplatedTypeId(size_t element) override
  1060. {
  1061. (void)element;
  1062. return SerializeGenericTypeInfo<GenericClass>::GetClassTypeId();
  1063. }
  1064. AZ::TypeId GetSpecializedTypeId() const override
  1065. {
  1066. return azrtti_typeid<GenericChild>();
  1067. }
  1068. AZ::TypeId GetGenericTypeId() const override
  1069. {
  1070. return TYPEINFO_Uuid();
  1071. }
  1072. void Reflect(SerializeContext*) override;
  1073. NullFactory m_factory;
  1074. SerializeContext::ClassData m_classData;
  1075. };
  1076. using ClassInfoType = GenericClassGenericInfo;
  1077. static ClassInfoType* GetGenericInfo()
  1078. {
  1079. return static_cast<ClassInfoType*>(GetCurrentSerializeContextModule().CreateGenericClassInfo<GenericChild>());
  1080. }
  1081. static AZ::TypeId GetClassTypeId()
  1082. {
  1083. return GetGenericInfo()->GetClassData()->m_typeId;
  1084. }
  1085. };
  1086. }
  1087. using namespace SerializeTestClasses;
  1088. using namespace AZ;
  1089. namespace UnitTest
  1090. {
  1091. /*
  1092. * Base class for all serialization unit tests
  1093. */
  1094. class Serialization
  1095. : public LeakDetectionFixture
  1096. , public ComponentApplicationBus::Handler
  1097. {
  1098. public:
  1099. //////////////////////////////////////////////////////////////////////////
  1100. // ComponentApplicationMessages
  1101. ComponentApplication* GetApplication() override { return nullptr; }
  1102. void RegisterComponentDescriptor(const ComponentDescriptor*) override { }
  1103. void UnregisterComponentDescriptor(const ComponentDescriptor*) override { }
  1104. void RegisterEntityAddedEventHandler(EntityAddedEvent::Handler&) override { }
  1105. void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler&) override { }
  1106. void RegisterEntityActivatedEventHandler(EntityActivatedEvent::Handler&) override { }
  1107. void RegisterEntityDeactivatedEventHandler(EntityDeactivatedEvent::Handler&) override { }
  1108. void SignalEntityActivated(Entity*) override { }
  1109. void SignalEntityDeactivated(Entity*) override { }
  1110. bool AddEntity(Entity*) override { return false; }
  1111. bool RemoveEntity(Entity*) override { return false; }
  1112. bool DeleteEntity(const EntityId&) override { return false; }
  1113. Entity* FindEntity(const EntityId&) override { return nullptr; }
  1114. SerializeContext* GetSerializeContext() override { return m_serializeContext.get(); }
  1115. BehaviorContext* GetBehaviorContext() override { return nullptr; }
  1116. JsonRegistrationContext* GetJsonRegistrationContext() override { return nullptr; }
  1117. const char* GetEngineRoot() const override { return nullptr; }
  1118. const char* GetExecutableFolder() const override { return nullptr; }
  1119. void EnumerateEntities(const EntityCallback& /*callback*/) override {}
  1120. void QueryApplicationType(AZ::ApplicationTypeQuery& /*appType*/) const override {}
  1121. //////////////////////////////////////////////////////////////////////////
  1122. void SetUp() override
  1123. {
  1124. m_serializeContext.reset(aznew AZ::SerializeContext());
  1125. ComponentApplicationBus::Handler::BusConnect();
  1126. AZ::Interface<AZ::ComponentApplicationRequests>::Register(this);
  1127. m_streamer = AZStd::make_unique<IO::Streamer>(AZStd::thread_desc{}, AZ::StreamerComponent::CreateStreamerStack());
  1128. Interface<IO::IStreamer>::Register(m_streamer.get());
  1129. }
  1130. void TearDown() override
  1131. {
  1132. m_serializeContext.reset();
  1133. Interface<IO::IStreamer>::Unregister(m_streamer.get());
  1134. m_streamer.reset();
  1135. AZ::Interface<AZ::ComponentApplicationRequests>::Unregister(this);
  1136. ComponentApplicationBus::Handler::BusDisconnect();
  1137. }
  1138. template<typename Container>
  1139. void ReserveAndFreeWithoutMemLeaks()
  1140. {
  1141. Container instance;
  1142. GenericClassInfo* containerInfo = SerializeGenericTypeInfo<decltype(instance)>::GetGenericInfo();
  1143. EXPECT_NE(nullptr, containerInfo);
  1144. EXPECT_NE(nullptr, containerInfo->GetClassData());
  1145. SerializeContext::IDataContainer* container = containerInfo->GetClassData()->m_container;
  1146. EXPECT_NE(nullptr, container);
  1147. SerializeContext::IEventHandler* eventHandler = containerInfo->GetClassData()->m_eventHandler;
  1148. if (eventHandler)
  1149. {
  1150. eventHandler->OnWriteBegin(&container);
  1151. }
  1152. void* element = container->ReserveElement(&instance, nullptr);
  1153. EXPECT_NE(nullptr, element);
  1154. *reinterpret_cast<float*>(element) = 42.0f;
  1155. container->FreeReservedElement(&instance, element, nullptr);
  1156. if (eventHandler)
  1157. {
  1158. eventHandler->OnWriteEnd(&container);
  1159. }
  1160. }
  1161. protected:
  1162. AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
  1163. AZStd::unique_ptr<AZ::IO::Streamer> m_streamer;
  1164. };
  1165. /*
  1166. * Test serialization of built-in types
  1167. */
  1168. class SerializeBasicTest
  1169. : public Serialization
  1170. {
  1171. protected:
  1172. enum ClassicEnum
  1173. {
  1174. CE_A = 0,
  1175. CR_B = 1,
  1176. };
  1177. enum class ClassEnum : char
  1178. {
  1179. A = 0,
  1180. B = 1,
  1181. };
  1182. AZStd::unique_ptr<SerializeContext> m_context;
  1183. char m_char;
  1184. short m_short;
  1185. int m_int;
  1186. long m_long;
  1187. AZ::s64 m_s64;
  1188. unsigned char m_uchar;
  1189. unsigned short m_ushort;
  1190. unsigned int m_uint;
  1191. unsigned long m_ulong;
  1192. AZ::u64 m_u64;
  1193. float m_float;
  1194. double m_double;
  1195. bool m_true;
  1196. bool m_false;
  1197. // Math
  1198. AZ::Uuid m_uuid;
  1199. Vector2 m_vector2;
  1200. Vector3 m_vector3;
  1201. Vector4 m_vector4;
  1202. Transform m_transform;
  1203. Matrix3x3 m_matrix3x3;
  1204. Matrix4x4 m_matrix4x4;
  1205. Quaternion m_quaternion;
  1206. Aabb m_aabb;
  1207. Plane m_plane;
  1208. ClassicEnum m_classicEnum;
  1209. ClassEnum m_classEnum;
  1210. public:
  1211. void SetUp() override
  1212. {
  1213. Serialization::SetUp();
  1214. m_context.reset(aznew SerializeContext());
  1215. }
  1216. void TearDown() override
  1217. {
  1218. m_context.reset();
  1219. Serialization::TearDown();
  1220. }
  1221. void OnLoadedClassReady(void* classPtr, const Uuid& classId, int* callCount)
  1222. {
  1223. switch ((*callCount)++)
  1224. {
  1225. case 0:
  1226. EXPECT_EQ( SerializeTypeInfo<char>::GetUuid(), classId );
  1227. EXPECT_EQ( m_char, *reinterpret_cast<char*>(classPtr) );
  1228. azdestroy(classPtr, AZ::SystemAllocator, char);
  1229. break;
  1230. case 1:
  1231. EXPECT_EQ( SerializeTypeInfo<short>::GetUuid(), classId );
  1232. EXPECT_EQ( m_short, *reinterpret_cast<short*>(classPtr) );
  1233. azdestroy(classPtr, AZ::SystemAllocator, short);
  1234. break;
  1235. case 2:
  1236. EXPECT_EQ( SerializeTypeInfo<int>::GetUuid(), classId );
  1237. EXPECT_EQ( m_int, *reinterpret_cast<int*>(classPtr) );
  1238. azdestroy(classPtr, AZ::SystemAllocator, int);
  1239. break;
  1240. case 3:
  1241. EXPECT_EQ( SerializeTypeInfo<long>::GetUuid(), classId );
  1242. EXPECT_EQ( m_long, *reinterpret_cast<long*>(classPtr) );
  1243. azdestroy(classPtr, AZ::SystemAllocator, long);
  1244. break;
  1245. case 4:
  1246. EXPECT_EQ( SerializeTypeInfo<AZ::s64>::GetUuid(), classId );
  1247. EXPECT_EQ( m_s64, *reinterpret_cast<AZ::s64*>(classPtr) );
  1248. azdestroy(classPtr, AZ::SystemAllocator, AZ::s64);
  1249. break;
  1250. case 5:
  1251. EXPECT_EQ( SerializeTypeInfo<unsigned char>::GetUuid(), classId );
  1252. EXPECT_EQ( m_uchar, *reinterpret_cast<unsigned char*>(classPtr) );
  1253. azdestroy(classPtr, AZ::SystemAllocator, unsigned char);
  1254. break;
  1255. case 6:
  1256. EXPECT_EQ( SerializeTypeInfo<unsigned short>::GetUuid(), classId );
  1257. EXPECT_EQ( m_ushort, *reinterpret_cast<unsigned short*>(classPtr) );
  1258. azdestroy(classPtr, AZ::SystemAllocator, unsigned short);
  1259. break;
  1260. case 7:
  1261. EXPECT_EQ( SerializeTypeInfo<unsigned int>::GetUuid(), classId );
  1262. EXPECT_EQ( m_uint, *reinterpret_cast<unsigned int*>(classPtr) );
  1263. azdestroy(classPtr, AZ::SystemAllocator, unsigned int);
  1264. break;
  1265. case 8:
  1266. EXPECT_EQ( SerializeTypeInfo<unsigned long>::GetUuid(), classId );
  1267. EXPECT_EQ( m_ulong, *reinterpret_cast<unsigned long*>(classPtr) );
  1268. azdestroy(classPtr, AZ::SystemAllocator, unsigned long);
  1269. break;
  1270. case 9:
  1271. EXPECT_EQ( SerializeTypeInfo<AZ::u64>::GetUuid(), classId );
  1272. EXPECT_EQ( m_u64, *reinterpret_cast<AZ::u64*>(classPtr) );
  1273. azdestroy(classPtr, AZ::SystemAllocator, AZ::u64);
  1274. break;
  1275. case 10:
  1276. EXPECT_EQ( SerializeTypeInfo<float>::GetUuid(), classId );
  1277. EXPECT_TRUE(fabsf(*reinterpret_cast<float*>(classPtr) - m_float) < 0.001f);
  1278. azdestroy(classPtr, AZ::SystemAllocator, float);
  1279. break;
  1280. case 11:
  1281. EXPECT_EQ( SerializeTypeInfo<double>::GetUuid(), classId );
  1282. EXPECT_TRUE(fabs(*reinterpret_cast<double*>(classPtr) - m_double) < 0.00000001);
  1283. azdestroy(classPtr, AZ::SystemAllocator, double);
  1284. break;
  1285. case 12:
  1286. EXPECT_EQ( SerializeTypeInfo<bool>::GetUuid(), classId );
  1287. EXPECT_EQ( m_true, *reinterpret_cast<bool*>(classPtr) );
  1288. azdestroy(classPtr, AZ::SystemAllocator, bool);
  1289. break;
  1290. case 13:
  1291. EXPECT_EQ( SerializeTypeInfo<bool>::GetUuid(), classId );
  1292. EXPECT_EQ( m_false, *reinterpret_cast<bool*>(classPtr) );
  1293. azdestroy(classPtr, AZ::SystemAllocator, bool);
  1294. break;
  1295. case 14:
  1296. EXPECT_EQ( SerializeTypeInfo<AZ::Uuid>::GetUuid(), classId );
  1297. EXPECT_EQ( m_uuid, *reinterpret_cast<AZ::Uuid*>(classPtr) );
  1298. azdestroy(classPtr, AZ::SystemAllocator, AZ::Uuid);
  1299. break;
  1300. case 15:
  1301. EXPECT_EQ( SerializeTypeInfo<AZ::Vector2>::GetUuid(), classId );
  1302. EXPECT_TRUE(reinterpret_cast<AZ::Vector2*>(classPtr)->IsClose(m_vector2, Constants::FloatEpsilon));
  1303. azdestroy(classPtr, AZ::SystemAllocator, AZ::Vector2);
  1304. break;
  1305. case 16:
  1306. EXPECT_EQ( SerializeTypeInfo<AZ::Vector3>::GetUuid(), classId );
  1307. EXPECT_TRUE(reinterpret_cast<AZ::Vector3*>(classPtr)->IsClose(m_vector3, Constants::FloatEpsilon));
  1308. azdestroy(classPtr, AZ::SystemAllocator, AZ::Vector3);
  1309. break;
  1310. case 17:
  1311. EXPECT_EQ( SerializeTypeInfo<AZ::Vector4>::GetUuid(), classId );
  1312. EXPECT_TRUE(reinterpret_cast<AZ::Vector4*>(classPtr)->IsClose(m_vector4, Constants::FloatEpsilon));
  1313. azdestroy(classPtr, AZ::SystemAllocator, AZ::Vector4);
  1314. break;
  1315. case 18:
  1316. EXPECT_EQ( SerializeTypeInfo<AZ::Transform>::GetUuid(), classId );
  1317. EXPECT_TRUE(reinterpret_cast<AZ::Transform*>(classPtr)->IsClose(m_transform, Constants::FloatEpsilon));
  1318. azdestroy(classPtr, AZ::SystemAllocator, AZ::Transform);
  1319. break;
  1320. case 19:
  1321. EXPECT_EQ( SerializeTypeInfo<AZ::Matrix3x3>::GetUuid(), classId );
  1322. EXPECT_TRUE(reinterpret_cast<AZ::Matrix3x3*>(classPtr)->IsClose(m_matrix3x3, Constants::FloatEpsilon));
  1323. azdestroy(classPtr, AZ::SystemAllocator, AZ::Matrix3x3);
  1324. break;
  1325. case 20:
  1326. EXPECT_EQ( SerializeTypeInfo<AZ::Matrix4x4>::GetUuid(), classId );
  1327. EXPECT_TRUE(reinterpret_cast<AZ::Matrix4x4*>(classPtr)->IsClose(m_matrix4x4, Constants::FloatEpsilon));
  1328. azdestroy(classPtr, AZ::SystemAllocator, AZ::Matrix4x4);
  1329. break;
  1330. case 21:
  1331. EXPECT_EQ( SerializeTypeInfo<AZ::Quaternion>::GetUuid(), classId );
  1332. EXPECT_TRUE(reinterpret_cast<AZ::Quaternion*>(classPtr)->IsClose(m_quaternion, Constants::FloatEpsilon));
  1333. azdestroy(classPtr, AZ::SystemAllocator, AZ::Quaternion);
  1334. break;
  1335. case 22:
  1336. EXPECT_EQ( SerializeTypeInfo<AZ::Aabb>::GetUuid(), classId );
  1337. EXPECT_TRUE(reinterpret_cast<AZ::Aabb*>(classPtr)->GetMin().IsClose(m_aabb.GetMin(), Constants::FloatEpsilon));
  1338. EXPECT_TRUE(reinterpret_cast<AZ::Aabb*>(classPtr)->GetMax().IsClose(m_aabb.GetMax(), Constants::FloatEpsilon));
  1339. azdestroy(classPtr, AZ::SystemAllocator, AZ::Aabb);
  1340. break;
  1341. case 23:
  1342. EXPECT_EQ( SerializeTypeInfo<AZ::Plane>::GetUuid(), classId );
  1343. EXPECT_TRUE(reinterpret_cast<AZ::Plane*>(classPtr)->GetPlaneEquationCoefficients().IsClose(m_plane.GetPlaneEquationCoefficients(), Constants::FloatEpsilon));
  1344. azdestroy(classPtr, AZ::SystemAllocator, AZ::Plane);
  1345. break;
  1346. case 24:
  1347. EXPECT_EQ( SerializeTypeInfo<ClassicEnum>::GetUuid(), classId );
  1348. EXPECT_EQ( CE_A, *reinterpret_cast<ClassicEnum*>(classPtr) );
  1349. azdestroy(classPtr, AZ::SystemAllocator, ClassicEnum);
  1350. break;
  1351. case 25:
  1352. EXPECT_EQ( SerializeTypeInfo<ClassEnum>::GetUuid(), classId );
  1353. EXPECT_EQ( ClassEnum::B, *reinterpret_cast<ClassEnum*>(classPtr) );
  1354. azdestroy(classPtr, AZ::SystemAllocator, ClassEnum);
  1355. break;
  1356. }
  1357. }
  1358. void SaveObjects(ObjectStream* writer)
  1359. {
  1360. bool success = true;
  1361. success = writer->WriteClass(&m_char);
  1362. EXPECT_TRUE(success);
  1363. success = writer->WriteClass(&m_short);
  1364. EXPECT_TRUE(success);
  1365. success = writer->WriteClass(&m_int);
  1366. EXPECT_TRUE(success);
  1367. success = writer->WriteClass(&m_long);
  1368. EXPECT_TRUE(success);
  1369. success = writer->WriteClass(&m_s64);
  1370. EXPECT_TRUE(success);
  1371. success = writer->WriteClass(&m_uchar);
  1372. EXPECT_TRUE(success);
  1373. success = writer->WriteClass(&m_ushort);
  1374. EXPECT_TRUE(success);
  1375. success = writer->WriteClass(&m_uint);
  1376. EXPECT_TRUE(success);
  1377. success = writer->WriteClass(&m_ulong);
  1378. EXPECT_TRUE(success);
  1379. success = writer->WriteClass(&m_u64);
  1380. EXPECT_TRUE(success);
  1381. success = writer->WriteClass(&m_float);
  1382. EXPECT_TRUE(success);
  1383. success = writer->WriteClass(&m_double);
  1384. EXPECT_TRUE(success);
  1385. success = writer->WriteClass(&m_true);
  1386. EXPECT_TRUE(success);
  1387. success = writer->WriteClass(&m_false);
  1388. EXPECT_TRUE(success);
  1389. success = writer->WriteClass(&m_uuid);
  1390. EXPECT_TRUE(success);
  1391. success = writer->WriteClass(&m_vector2);
  1392. EXPECT_TRUE(success);
  1393. success = writer->WriteClass(&m_vector3);
  1394. EXPECT_TRUE(success);
  1395. success = writer->WriteClass(&m_vector4);
  1396. EXPECT_TRUE(success);
  1397. success = writer->WriteClass(&m_transform);
  1398. EXPECT_TRUE(success);
  1399. success = writer->WriteClass(&m_matrix3x3);
  1400. EXPECT_TRUE(success);
  1401. success = writer->WriteClass(&m_matrix4x4);
  1402. EXPECT_TRUE(success);
  1403. success = writer->WriteClass(&m_quaternion);
  1404. EXPECT_TRUE(success);
  1405. success = writer->WriteClass(&m_aabb);
  1406. EXPECT_TRUE(success);
  1407. success = writer->WriteClass(&m_plane);
  1408. EXPECT_TRUE(success);
  1409. success = writer->WriteClass(&m_classicEnum);
  1410. EXPECT_TRUE(success);
  1411. success = writer->WriteClass(&m_classEnum);
  1412. EXPECT_TRUE(success);
  1413. }
  1414. void OnDone(ObjectStream::Handle handle, bool success, bool* done)
  1415. {
  1416. (void)handle;
  1417. EXPECT_TRUE(success);
  1418. *done = true;
  1419. }
  1420. void TestSave(IO::GenericStream* stream, ObjectStream::StreamType format)
  1421. {
  1422. ObjectStream* objStream = ObjectStream::Create(stream, *m_context, format);
  1423. SaveObjects(objStream);
  1424. bool done = objStream->Finalize();
  1425. EXPECT_TRUE(done);
  1426. }
  1427. void TestLoad(IO::GenericStream* stream)
  1428. {
  1429. int cbCount = 0;
  1430. bool done = false;
  1431. ObjectStream::ClassReadyCB readyCB(AZStd::bind(&SerializeBasicTest::OnLoadedClassReady, this, AZStd::placeholders::_1, AZStd::placeholders::_2, &cbCount));
  1432. ObjectStream::CompletionCB doneCB(AZStd::bind(&SerializeBasicTest::OnDone, this, AZStd::placeholders::_1, AZStd::placeholders::_2, &done));
  1433. ObjectStream::LoadBlocking(stream, *m_context, readyCB);
  1434. EXPECT_EQ( 26, cbCount );
  1435. }
  1436. };
  1437. namespace AdvancedTest
  1438. {
  1439. class EmptyClass
  1440. {
  1441. public:
  1442. AZ_CLASS_ALLOCATOR(EmptyClass, SystemAllocator);
  1443. AZ_TYPE_INFO(EmptyClass, "{7B2AA956-80A9-4996-B750-7CE8F7F79A29}")
  1444. EmptyClass()
  1445. : m_data(101)
  1446. {
  1447. }
  1448. static void Reflect(SerializeContext& context)
  1449. {
  1450. context.Class<EmptyClass>()
  1451. ->Version(1)
  1452. ->SerializeWithNoData();
  1453. }
  1454. int m_data;
  1455. };
  1456. // We don't recommend using this pattern as it can be tricky to track why some objects are stored, we
  1457. // wecommend that you have fully symetrical save/load.
  1458. class ConditionalSave
  1459. {
  1460. public:
  1461. AZ_CLASS_ALLOCATOR(ConditionalSave, SystemAllocator);
  1462. AZ_TYPE_INFO(ConditionalSave, "{E1E6910F-C029-492A-8163-026F6F69FC53}");
  1463. ConditionalSave()
  1464. : m_doSave(true)
  1465. , m_data(201)
  1466. {
  1467. }
  1468. static void Reflect(SerializeContext& context)
  1469. {
  1470. context.Class<ConditionalSave>()->
  1471. Version(1)->
  1472. SerializerDoSave([](const void* instance) { return reinterpret_cast<const ConditionalSave*>(instance)->m_doSave; })->
  1473. Field("m_data", &ConditionalSave::m_data);
  1474. }
  1475. bool m_doSave;
  1476. int m_data;
  1477. };
  1478. }
  1479. namespace ContainersTest
  1480. {
  1481. struct ContainersStruct
  1482. {
  1483. AZ_TYPE_INFO(ContainersStruct, "{E88A592D-5221-49DE-9DFD-6E25B39C65C7}");
  1484. AZ_CLASS_ALLOCATOR(ContainersStruct, AZ::SystemAllocator);
  1485. AZStd::vector<int> m_vector;
  1486. AZStd::fixed_vector<int, 5> m_fixedVector;
  1487. AZStd::array<int, 5> m_array;
  1488. AZStd::list<int> m_list;
  1489. AZStd::forward_list<int> m_forwardList;
  1490. AZStd::unordered_set<int> m_unorderedSet;
  1491. AZStd::unordered_map<int, float> m_unorderedMap;
  1492. AZStd::bitset<10> m_bitset;
  1493. };
  1494. struct AssociativePtrContainer
  1495. {
  1496. AZ_TYPE_INFO(AssociativePtrContainer, "{02223E23-9B9C-4196-84C2-77D3A57BFF87}");
  1497. AZ_CLASS_ALLOCATOR(AssociativePtrContainer, AZ::SystemAllocator);
  1498. static void Reflect(SerializeContext& serializeContext)
  1499. {
  1500. serializeContext.Class<AssociativePtrContainer>()
  1501. ->Field("m_setOfPointers", &AssociativePtrContainer::m_setOfPointers)
  1502. ->Field("m_mapOfFloatPointers", &AssociativePtrContainer::m_mapOfFloatPointers)
  1503. ->Field("m_sharedEntityPointer", &AssociativePtrContainer::m_sharedEntityPointer)
  1504. ;
  1505. }
  1506. AZStd::unordered_set<AZ::Entity*> m_setOfPointers;
  1507. AZStd::unordered_map<int, float*> m_mapOfFloatPointers;
  1508. AZStd::shared_ptr<AZ::Entity> m_sharedEntityPointer;
  1509. };
  1510. void ReflectVectorOfInts(AZ::SerializeContext* serializeContext)
  1511. {
  1512. AZ::GenericClassInfo* genericClassInfo = AZ::SerializeGenericTypeInfo<AZStd::vector<int>>::GetGenericInfo();
  1513. if (genericClassInfo)
  1514. {
  1515. genericClassInfo->Reflect(serializeContext);
  1516. }
  1517. genericClassInfo = AZ::SerializeGenericTypeInfo<AZStd::vector<int*>>::GetGenericInfo();
  1518. if (genericClassInfo)
  1519. {
  1520. genericClassInfo->Reflect(serializeContext);
  1521. }
  1522. }
  1523. }
  1524. TEST_F(Serialization, ElementOverrideTest_DefaultSerializationWorks)
  1525. {
  1526. ElementOverrideType::Reflect(*m_serializeContext);
  1527. ElementOverrideType testType;
  1528. testType.m_field = 1; // Our custom serializer will use the default output when this value is 1
  1529. AZStd::vector<char> buffer;
  1530. IO::ByteContainerStream<AZStd::vector<char>> stream(&buffer);
  1531. ASSERT_TRUE(Utils::SaveObjectToStream(stream, DataStream::ST_XML, &testType, m_serializeContext.get()));
  1532. constexpr const char* expectedValue =
  1533. R"(<ObjectStream version="3">)" "\n"
  1534. "\t" R"(<Class name="ElementOverrideType" type="{BAA18B6C-3CB3-476C-8B41-21EA7CE1F4CF}">)" "\n"
  1535. "\t\t" R"(<Class name="int" field="field" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>)" "\n"
  1536. "\t" R"(</Class>)" "\n"
  1537. R"(</ObjectStream>)";
  1538. AZStd::string result(buffer.data(), stream.GetLength());
  1539. AZ::StringFunc::TrimWhiteSpace(result, true, true);
  1540. EXPECT_STREQ(result.c_str(), expectedValue);
  1541. }
  1542. TEST_F(Serialization, ElementOverrideTest_CustomSerializationWorks)
  1543. {
  1544. ElementOverrideType::Reflect(*m_serializeContext);
  1545. ElementOverrideType testType;
  1546. testType.m_field = 0; // Our custom serializer will do its own output when this value is 0
  1547. AZStd::vector<char> buffer;
  1548. IO::ByteContainerStream<AZStd::vector<char>> stream(&buffer);
  1549. ASSERT_TRUE(Utils::SaveObjectToStream(stream, DataStream::ST_XML, &testType, m_serializeContext.get()));
  1550. constexpr const char* expectedValue =
  1551. R"(<ObjectStream version="3">)" "\n"
  1552. "\t" R"(<Class name="float" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>)" "\n"
  1553. R"(</ObjectStream>)";
  1554. AZStd::string result(buffer.data(), stream.GetLength());
  1555. AZ::StringFunc::TrimWhiteSpace(result, true, true);
  1556. EXPECT_STREQ(result.c_str(), expectedValue);
  1557. }
  1558. TEST_F(Serialization, ElementOverrideTest_FailureCase)
  1559. {
  1560. ElementOverrideType::Reflect(*m_serializeContext);
  1561. ElementOverrideType testType;
  1562. testType.m_field = 2; // Our custom serializer will report a failure when this value is not 0/1
  1563. AZStd::vector<char> buffer;
  1564. IO::ByteContainerStream<AZStd::vector<char>> stream(&buffer);
  1565. AZ_TEST_START_TRACE_SUPPRESSION;
  1566. ASSERT_FALSE(Utils::SaveObjectToStream(stream, DataStream::ST_XML, &testType, m_serializeContext.get()));
  1567. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  1568. }
  1569. TEST_F(Serialization, ContainerTypeContainedTypeDiffersByPointer)
  1570. {
  1571. ContainersTest::ReflectVectorOfInts(m_serializeContext.get());
  1572. AZStd::vector<int> vectorOfInts;
  1573. AZStd::vector<int*> vectorOfIntPointers;
  1574. vectorOfInts.push_back(5);
  1575. vectorOfIntPointers.push_back(azcreate(int, (5), AZ::SystemAllocator));
  1576. // Write Vector of Int to object stream
  1577. AZStd::vector<char> vectorIntBuffer;
  1578. IO::ByteContainerStream<AZStd::vector<char> > vectorIntStream(&vectorIntBuffer);
  1579. {
  1580. ObjectStream* objStream = ObjectStream::Create(&vectorIntStream, *m_serializeContext, ObjectStream::ST_XML);
  1581. objStream->WriteClass(&vectorOfInts);
  1582. objStream->Finalize();
  1583. }
  1584. AZStd::vector<char> vectorIntPointerBuffer;
  1585. IO::ByteContainerStream<AZStd::vector<char> > vectorIntPointerStream(&vectorIntPointerBuffer);
  1586. {
  1587. /*
  1588. * The vectorIntPointerBuffer.data() function call should be examined in the debugger after this block
  1589. * This will write out an the address of the integer 5 stored in the vectorOfIntPointers instead of 5 to the xml data
  1590. */
  1591. ObjectStream* objStream = ObjectStream::Create(&vectorIntPointerStream, *m_serializeContext, ObjectStream::ST_XML);
  1592. objStream->WriteClass(&vectorOfIntPointers);
  1593. objStream->Finalize();
  1594. }
  1595. vectorIntStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  1596. vectorIntPointerStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  1597. AZStd::vector<int> loadIntVector;
  1598. AZStd::vector<int*> loadIntPtrVector;
  1599. bool loadResult = AZ::Utils::LoadObjectFromStreamInPlace(vectorIntStream, loadIntVector, m_serializeContext.get());
  1600. EXPECT_TRUE(loadResult);
  1601. loadResult = AZ::Utils::LoadObjectFromStreamInPlace(vectorIntPointerStream, loadIntPtrVector, m_serializeContext.get());
  1602. EXPECT_TRUE(loadResult);
  1603. /*
  1604. * As the vector to int pointer class was reflected second, it would not get placed into the SerializeContext GenericClassInfoMap
  1605. * Therefore the write of the AZStd::vector<int*> to vectorIntPointerStream will output bad data as it reinterpret_cast
  1606. * the supplied AZStd::vector<int*> to an AZStd::vector<int>
  1607. */
  1608. ASSERT_EQ(1, loadIntVector.size());
  1609. EXPECT_EQ(vectorOfInts[0], loadIntVector[0]);
  1610. ASSERT_EQ(1, loadIntPtrVector.size());
  1611. ASSERT_NE(nullptr, loadIntPtrVector[0]);
  1612. EXPECT_NE(vectorOfIntPointers[0], loadIntPtrVector[0]);
  1613. EXPECT_EQ(*vectorOfIntPointers[0], *loadIntPtrVector[0]);
  1614. for (int* intPtr : vectorOfIntPointers)
  1615. {
  1616. azdestroy(intPtr);
  1617. }
  1618. for (int* intPtr : loadIntPtrVector)
  1619. {
  1620. // NOTE: This will crash if loadIntPtrVector uses the incorrect GenericClassInfo to serialize its data
  1621. azdestroy(intPtr);
  1622. }
  1623. m_serializeContext->EnableRemoveReflection();
  1624. ContainersTest::ReflectVectorOfInts(m_serializeContext.get());
  1625. m_serializeContext->DisableRemoveReflection();
  1626. }
  1627. #if AZ_TRAIT_DISABLE_FAILED_SERIALIZE_BASIC_TEST
  1628. TEST_F(SerializeBasicTest, DISABLED_BasicTypeTest_Succeed)
  1629. #else
  1630. TEST_F(SerializeBasicTest, BasicTypeTest_Succeed)
  1631. #endif
  1632. {
  1633. m_char = -1;
  1634. m_short = -2;
  1635. m_int = -3;
  1636. m_long = -4;
  1637. m_s64 = -5;
  1638. m_uchar = 1;
  1639. m_ushort = 2;
  1640. m_uint = 3;
  1641. m_ulong = 4;
  1642. m_u64 = 5;
  1643. m_float = 2.f;
  1644. m_double = 20.0000005;
  1645. m_true = true;
  1646. m_false = false;
  1647. // Math
  1648. m_uuid = AZ::Uuid::CreateString("{16490FB4-A7CE-4a8a-A882-F98DDA6A788F}");
  1649. m_vector2 = Vector2(1.0f, 2.0f);
  1650. m_vector3 = Vector3(3.0f, 4.0f, 5.0f);
  1651. m_vector4 = Vector4(6.0f, 7.0f, 8.0f, 9.0f);
  1652. m_quaternion = Quaternion::CreateRotationZ(0.7f);
  1653. m_transform = Transform::CreateRotationX(1.1f);
  1654. m_matrix3x3 = Matrix3x3::CreateRotationY(0.5f);
  1655. m_matrix4x4 = Matrix4x4::CreateFromQuaternionAndTranslation(m_quaternion, m_vector3);
  1656. m_aabb.Set(-m_vector3, m_vector3);
  1657. m_plane.Set(m_vector4);
  1658. m_classicEnum = CE_A;
  1659. m_classEnum = ClassEnum::B;
  1660. TestFileIOBase fileIO;
  1661. SetRestoreFileIOBaseRAII restoreFileIOScope(fileIO);
  1662. // Store test files within a temporary directory that is deleted
  1663. // when the variable goes out of scope
  1664. AZ::Test::ScopedAutoTempDirectory tempDirectory;
  1665. AZ::IO::Path serializeTestFilePath = tempDirectory.GetDirectory();
  1666. // XML version
  1667. AZ::IO::Path testXmlFilePath = serializeTestFilePath / "serializebasictest.xml";
  1668. {
  1669. AZ_TracePrintf("SerializeBasicTest", "\nWriting as XML...\n");
  1670. IO::FileIOStream stream(testXmlFilePath.c_str(), IO::OpenMode::ModeWrite);
  1671. TestSave(&stream, ObjectStream::ST_XML);
  1672. }
  1673. {
  1674. AZ_TracePrintf("SerializeBasicTest", "Loading as XML...\n");
  1675. IO::FileIOStream stream(testXmlFilePath.c_str(), IO::OpenMode::ModeRead);
  1676. TestLoad(&stream);
  1677. }
  1678. // JSON version
  1679. AZ::IO::Path testJsonFilePath = serializeTestFilePath / "serializebasictest.json";
  1680. {
  1681. AZ_TracePrintf("SerializeBasicTest", "\nWriting as JSON...\n");
  1682. IO::FileIOStream stream(testJsonFilePath.c_str(), IO::OpenMode::ModeWrite);
  1683. TestSave(&stream, ObjectStream::ST_JSON);
  1684. }
  1685. {
  1686. AZ_TracePrintf("SerializeBasicTest", "Loading as JSON...\n");
  1687. IO::FileIOStream stream(testJsonFilePath.c_str(), IO::OpenMode::ModeRead);
  1688. TestLoad(&stream);
  1689. }
  1690. // Binary version
  1691. AZ::IO::Path testBinFilePath = serializeTestFilePath / "serializebasictest.bin";
  1692. {
  1693. AZ_TracePrintf("SerializeBasicTest", "Writing as Binary...\n");
  1694. IO::FileIOStream stream(testBinFilePath.c_str(), IO::OpenMode::ModeWrite);
  1695. TestSave(&stream, ObjectStream::ST_BINARY);
  1696. }
  1697. {
  1698. AZ_TracePrintf("SerializeBasicTest", "Loading as Binary...\n");
  1699. IO::FileIOStream stream(testBinFilePath.c_str(), IO::OpenMode::ModeRead);
  1700. TestLoad(&stream);
  1701. }
  1702. }
  1703. /*
  1704. * Test serialization of built-in container types
  1705. */
  1706. TEST_F(Serialization, ContainersTest)
  1707. {
  1708. using namespace ContainersTest;
  1709. class ContainersTest
  1710. {
  1711. public:
  1712. void VerifyLoad(void* classPtr, const Uuid& classId, ContainersStruct* controlData)
  1713. {
  1714. EXPECT_EQ( SerializeTypeInfo<ContainersStruct>::GetUuid(), classId );
  1715. ContainersStruct* data = reinterpret_cast<ContainersStruct*>(classPtr);
  1716. EXPECT_EQ( controlData->m_vector, data->m_vector );
  1717. EXPECT_EQ( controlData->m_fixedVector, data->m_fixedVector );
  1718. EXPECT_EQ( controlData->m_array[0], data->m_array[0] );
  1719. EXPECT_EQ( controlData->m_array[1], data->m_array[1] );
  1720. EXPECT_EQ( controlData->m_list, data->m_list );
  1721. EXPECT_EQ( controlData->m_forwardList, data->m_forwardList );
  1722. EXPECT_EQ( controlData->m_unorderedSet.size(), data->m_unorderedSet.size() );
  1723. for (AZStd::unordered_set<int>::const_iterator it = data->m_unorderedSet.begin(), ctrlIt = controlData->m_unorderedSet.begin(); it != data->m_unorderedSet.end(); ++it, ++ctrlIt)
  1724. {
  1725. EXPECT_EQ( *ctrlIt, *it );
  1726. }
  1727. EXPECT_EQ( controlData->m_unorderedMap.size(), data->m_unorderedMap.size() );
  1728. for (AZStd::unordered_map<int, float>::const_iterator it = data->m_unorderedMap.begin(), ctrlIt = controlData->m_unorderedMap.begin(); it != data->m_unorderedMap.end(); ++it, ++ctrlIt)
  1729. {
  1730. EXPECT_EQ( *ctrlIt, *it );
  1731. }
  1732. EXPECT_EQ( controlData->m_bitset, data->m_bitset );
  1733. delete data;
  1734. }
  1735. void run()
  1736. {
  1737. SerializeContext serializeContext;
  1738. serializeContext.Class<ContainersStruct>()
  1739. ->Field("m_vector", &ContainersStruct::m_vector)
  1740. ->Field("m_fixedVector", &ContainersStruct::m_fixedVector)
  1741. ->Field("m_array", &ContainersStruct::m_array)
  1742. ->Field("m_list", &ContainersStruct::m_list)
  1743. ->Field("m_forwardList", &ContainersStruct::m_forwardList)
  1744. ->Field("m_unorderedSet", &ContainersStruct::m_unorderedSet)
  1745. ->Field("m_unorderedMap", &ContainersStruct::m_unorderedMap)
  1746. ->Field("m_bitset", &ContainersStruct::m_bitset);
  1747. ContainersStruct testData;
  1748. testData.m_vector.push_back(1);
  1749. testData.m_vector.push_back(2);
  1750. testData.m_fixedVector.push_back(3);
  1751. testData.m_fixedVector.push_back(4);
  1752. testData.m_array[0] = 5;
  1753. testData.m_array[1] = 6;
  1754. testData.m_list.push_back(7);
  1755. testData.m_list.push_back(8);
  1756. auto forwardListIt = testData.m_forwardList.emplace_after(testData.m_forwardList.before_begin(), 9);
  1757. testData.m_forwardList.emplace_after(forwardListIt, 10);
  1758. testData.m_unorderedSet.insert(11);
  1759. testData.m_unorderedSet.insert(12);
  1760. testData.m_unorderedMap.insert(AZStd::make_pair(13, 13.f));
  1761. testData.m_unorderedMap.insert(AZStd::make_pair(14, 14.f));
  1762. testData.m_bitset.set(0);
  1763. testData.m_bitset.set(9);
  1764. // XML
  1765. AZStd::vector<char> xmlBuffer;
  1766. IO::ByteContainerStream<AZStd::vector<char> > xmlStream(&xmlBuffer);
  1767. ObjectStream* xmlObjStream = ObjectStream::Create(&xmlStream, serializeContext, ObjectStream::ST_XML);
  1768. xmlObjStream->WriteClass(&testData);
  1769. xmlObjStream->Finalize();
  1770. xmlStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  1771. ObjectStream::ClassReadyCB readyCB(AZStd::bind(&ContainersTest::VerifyLoad, this, AZStd::placeholders::_1, AZStd::placeholders::_2, &testData));
  1772. ObjectStream::LoadBlocking(&xmlStream, serializeContext, readyCB);
  1773. }
  1774. };
  1775. ContainersTest test;
  1776. test.run();
  1777. }
  1778. TEST_F(Serialization, AssociativeContainerPtrTest)
  1779. {
  1780. using namespace ContainersTest;
  1781. // We must expose the class for serialization first.
  1782. AZ::Entity::Reflect(m_serializeContext.get());
  1783. AssociativePtrContainer::Reflect(*m_serializeContext);
  1784. AssociativePtrContainer testObj;
  1785. testObj.m_setOfPointers.insert(aznew AZ::Entity("Entity1"));
  1786. testObj.m_setOfPointers.insert(aznew AZ::Entity("Entity2"));
  1787. testObj.m_mapOfFloatPointers.emplace(5, azcreate(float, (3.14f), AZ::SystemAllocator));
  1788. testObj.m_sharedEntityPointer.reset(aznew AZ::Entity("Entity3"));
  1789. // XML
  1790. AZStd::vector<char> xmlBuffer;
  1791. IO::ByteContainerStream<AZStd::vector<char> > xmlStream(&xmlBuffer);
  1792. ObjectStream* xmlObjStream = ObjectStream::Create(&xmlStream, *m_serializeContext, ObjectStream::ST_XML);
  1793. xmlObjStream->WriteClass(&testObj);
  1794. xmlObjStream->Finalize();
  1795. xmlStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  1796. bool result = ObjectStream::LoadBlocking(&xmlStream, *m_serializeContext, [&testObj](void* classPtr, const AZ::Uuid& classId, SerializeContext*)
  1797. {
  1798. EXPECT_EQ(SerializeTypeInfo<AssociativePtrContainer>::GetUuid(), classId);
  1799. auto loadObj = reinterpret_cast<AssociativePtrContainer*>(classPtr);
  1800. EXPECT_EQ(testObj.m_setOfPointers.size(), loadObj->m_setOfPointers.size());
  1801. auto testObjSetBeginIt = testObj.m_setOfPointers.begin();
  1802. auto loadObjSetBeginIt = loadObj->m_setOfPointers.begin();
  1803. for (; testObjSetBeginIt != testObj.m_setOfPointers.end(); ++testObjSetBeginIt, ++loadObjSetBeginIt)
  1804. {
  1805. EXPECT_EQ((*testObjSetBeginIt)->GetId(), (*loadObjSetBeginIt)->GetId());
  1806. }
  1807. EXPECT_EQ(testObj.m_mapOfFloatPointers.size(), loadObj->m_mapOfFloatPointers.size());
  1808. auto testObjMapBeginIt = testObj.m_mapOfFloatPointers.begin();
  1809. auto loadObjMapBeginIt = loadObj->m_mapOfFloatPointers.begin();
  1810. for (; testObjMapBeginIt != testObj.m_mapOfFloatPointers.end(); ++testObjMapBeginIt, ++loadObjMapBeginIt)
  1811. {
  1812. EXPECT_EQ(*(testObjMapBeginIt->second), *(loadObjMapBeginIt->second));
  1813. }
  1814. EXPECT_NE(nullptr, loadObj->m_sharedEntityPointer.get());
  1815. EXPECT_EQ(testObj.m_sharedEntityPointer->GetId(), loadObj->m_sharedEntityPointer->GetId());
  1816. //Free the allocated memory
  1817. for (auto& entitySet : { testObj.m_setOfPointers, loadObj->m_setOfPointers })
  1818. {
  1819. for (AZ::Entity* entityPtr : entitySet)
  1820. {
  1821. delete entityPtr;
  1822. }
  1823. }
  1824. for (auto& intFloatPtrMap : { testObj.m_mapOfFloatPointers, loadObj->m_mapOfFloatPointers })
  1825. {
  1826. for (auto& intFloatPtrPair : intFloatPtrMap)
  1827. {
  1828. azdestroy(intFloatPtrPair.second);
  1829. }
  1830. }
  1831. delete loadObj;
  1832. });
  1833. EXPECT_TRUE(result);
  1834. }
  1835. /*
  1836. This test will dynamic cast (azrtti_cast) between incompatible types, which should always result in nullptr.
  1837. If this test fails, the RTTI declaration for the relevant type is incorrect.
  1838. */
  1839. TEST_F(Serialization, AttributeRTTI)
  1840. {
  1841. {
  1842. AttributeInvocable<AZStd::function<AZStd::string(AZStd::string)>> fn([](AZStd::string x) { return x + x; });
  1843. Attribute* fnDownCast = &fn;
  1844. auto fnUpCast = azrtti_cast<AttributeInvocable<AZStd::function<int(int)>>*>(fnDownCast);
  1845. EXPECT_EQ(fnUpCast, nullptr);
  1846. }
  1847. {
  1848. AttributeFunction<AZStd::string(AZStd::string)> fn([](AZStd::string x) { return x + x; });
  1849. Attribute* fnDownCast = &fn;
  1850. auto fnUpCast = azrtti_cast<AttributeFunction<int(int)>*>(fnDownCast);
  1851. EXPECT_EQ(fnUpCast, nullptr);
  1852. }
  1853. }
  1854. /*
  1855. * Deprecation
  1856. */
  1857. namespace Deprecation
  1858. {
  1859. struct DeprecatedClass
  1860. {
  1861. AZ_CLASS_ALLOCATOR(DeprecatedClass, AZ::SystemAllocator);
  1862. AZ_TYPE_INFO(DeprecatedClass, "{893CA46E-6D1A-4D27-94F7-09E26DE5AE4B}")
  1863. DeprecatedClass()
  1864. : m_data(0) {}
  1865. int m_data;
  1866. };
  1867. struct DeprecationTestClass
  1868. {
  1869. AZ_CLASS_ALLOCATOR(DeprecationTestClass, AZ::SystemAllocator);
  1870. AZ_TYPE_INFO(DeprecationTestClass, "{54E27F53-EF3F-4436-9378-E9AF56A9FA4C}")
  1871. DeprecationTestClass()
  1872. : m_deprecatedPtr(nullptr)
  1873. , m_oldClassData(0)
  1874. , m_newClassData(0.f)
  1875. , m_missingMember(0)
  1876. , m_data(0)
  1877. {}
  1878. ~DeprecationTestClass() { Clear(); }
  1879. void Clear()
  1880. {
  1881. if (m_deprecatedPtr)
  1882. {
  1883. delete m_deprecatedPtr;
  1884. m_deprecatedPtr = nullptr;
  1885. }
  1886. }
  1887. DeprecatedClass m_deprecated;
  1888. DeprecatedClass* m_deprecatedPtr;
  1889. int m_oldClassData;
  1890. float m_newClassData;
  1891. int m_missingMember;
  1892. int m_data;
  1893. };
  1894. struct SimpleBaseClass
  1895. {
  1896. AZ_CLASS_ALLOCATOR(SimpleBaseClass, AZ::SystemAllocator);
  1897. AZ_RTTI(SimpleBaseClass, "{829F6E24-AAEF-4C97-9003-0BC22CB64786}")
  1898. SimpleBaseClass()
  1899. : m_data(0.f) {}
  1900. virtual ~SimpleBaseClass() {}
  1901. float m_data;
  1902. };
  1903. struct SimpleDerivedClass1 : public SimpleBaseClass
  1904. {
  1905. AZ_CLASS_ALLOCATOR(SimpleDerivedClass1, AZ::SystemAllocator);
  1906. AZ_RTTI(SimpleDerivedClass1, "{78632262-C303-49BC-ABAD-88B088098311}", SimpleBaseClass)
  1907. SimpleDerivedClass1() {}
  1908. };
  1909. struct SimpleDerivedClass2 : public SimpleBaseClass
  1910. {
  1911. AZ_CLASS_ALLOCATOR(SimpleDerivedClass2, AZ::SystemAllocator);
  1912. AZ_RTTI(SimpleDerivedClass2, "{4932DF7C-0482-4846-AAE5-BED7D03F9E02}", SimpleBaseClass)
  1913. SimpleDerivedClass2() {}
  1914. };
  1915. struct OwnerClass
  1916. {
  1917. AZ_CLASS_ALLOCATOR(OwnerClass, AZ::SystemAllocator);
  1918. AZ_TYPE_INFO(OwnerClass, "{3F305C77-4BE1-49E6-9C51-9F1284F18CCE}");
  1919. OwnerClass() {}
  1920. SimpleBaseClass* m_pointer = nullptr;
  1921. };
  1922. }
  1923. TEST_F(Serialization, TestDeprecatedClassAtRootLevel_Succeeds)
  1924. {
  1925. using namespace Deprecation;
  1926. // Test a deprecated class at the root level.
  1927. SerializeContext sc;
  1928. SimpleDerivedClass1 simpleDerivedClass1;
  1929. sc.Class<SimpleBaseClass>()
  1930. ->Version(1)
  1931. ->Field("m_data", &SimpleBaseClass::m_data);
  1932. sc.Class<SimpleDerivedClass1, SimpleBaseClass>()
  1933. ->Version(1);
  1934. sc.Class<SimpleDerivedClass2, SimpleBaseClass>()
  1935. ->Version(1);
  1936. AZStd::vector<char> xmlBufferRootTest;
  1937. AZStd::vector<char> jsonBufferRootTest;
  1938. AZStd::vector<char> binaryBufferRootTest;
  1939. {
  1940. // XML
  1941. IO::ByteContainerStream<AZStd::vector<char> > xmlStream(&xmlBufferRootTest);
  1942. AZ_TracePrintf("SerializeDeprecationTest", "Writing XML\n");
  1943. ObjectStream* xmlObjStream = ObjectStream::Create(&xmlStream, sc, ObjectStream::ST_XML);
  1944. xmlObjStream->WriteClass(&simpleDerivedClass1);
  1945. bool success = xmlObjStream->Finalize();
  1946. EXPECT_TRUE(success);
  1947. // JSON
  1948. IO::ByteContainerStream<AZStd::vector<char> > jsonStream(&jsonBufferRootTest);
  1949. AZ_TracePrintf("SerializeDeprecationTest", "Writing JSON\n");
  1950. ObjectStream* jsonObjStream = ObjectStream::Create(&jsonStream, sc, ObjectStream::ST_JSON);
  1951. jsonObjStream->WriteClass(&simpleDerivedClass1);
  1952. success = jsonObjStream->Finalize();
  1953. EXPECT_TRUE(success);
  1954. // Binary
  1955. IO::ByteContainerStream<AZStd::vector<char> > binaryStream(&binaryBufferRootTest);
  1956. AZ_TracePrintf("SerializeDeprecationTest", "Writing Binary\n");
  1957. ObjectStream* binaryObjStream = ObjectStream::Create(&binaryStream, sc, ObjectStream::ST_BINARY);
  1958. binaryObjStream->WriteClass(&simpleDerivedClass1);
  1959. success = binaryObjStream->Finalize();
  1960. EXPECT_TRUE(success);
  1961. }
  1962. sc.EnableRemoveReflection();
  1963. sc.Class<SimpleDerivedClass1>();
  1964. sc.DisableRemoveReflection();
  1965. AZ::SerializeContext::VersionConverter converter = [](AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) -> bool
  1966. {
  1967. return classElement.Convert<SimpleDerivedClass2>(context);
  1968. };
  1969. sc.ClassDeprecate("SimpleDerivedClass1", AZ::Uuid("{78632262-C303-49BC-ABAD-88B088098311}"), converter);
  1970. auto cb = [](void* classPtr, const Uuid& classId, SerializeContext* /*context*/) -> void
  1971. {
  1972. EXPECT_EQ(AzTypeInfo<SimpleDerivedClass2>::Uuid(), classId);
  1973. delete static_cast<SimpleDerivedClass2*>(classPtr);
  1974. };
  1975. ObjectStream::ClassReadyCB readyCBTest(cb);
  1976. // XML
  1977. AZ_TracePrintf("SerializeDeprecationTest", "Loading XML with deprecated class\n");
  1978. IO::ByteContainerStream<const AZStd::vector<char> > xmlStreamUuidTest(&xmlBufferRootTest);
  1979. xmlStreamUuidTest.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  1980. EXPECT_TRUE(ObjectStream::LoadBlocking(&xmlStreamUuidTest, sc, readyCBTest));
  1981. // JSON
  1982. AZ_TracePrintf("SerializeDeprecationTest", "Loading JSON with deprecated class\n");
  1983. IO::ByteContainerStream<const AZStd::vector<char> > jsonStream(&jsonBufferRootTest);
  1984. jsonStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  1985. ObjectStream::LoadBlocking(&jsonStream, sc, readyCBTest);
  1986. // Binary
  1987. AZ_TracePrintf("SerializeDeprecationTest", "Loading Binary with deprecated class\n");
  1988. IO::ByteContainerStream<const AZStd::vector<char> > binaryStream(&binaryBufferRootTest);
  1989. binaryStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  1990. ObjectStream::LoadBlocking(&binaryStream, sc, readyCBTest);
  1991. }
  1992. TEST_F(Serialization, DeprecationRulesTest)
  1993. {
  1994. using namespace Deprecation;
  1995. class DeprecationTest
  1996. {
  1997. public:
  1998. DeprecatedClass m_deprecated;
  1999. DeprecationTestClass m_deprecationTestClass;
  2000. void WriteDeprecated(ObjectStream* writer)
  2001. {
  2002. bool success = writer->WriteClass(&m_deprecated);
  2003. EXPECT_TRUE(success);
  2004. }
  2005. void WriteDeprecationTestClass(ObjectStream* writer)
  2006. {
  2007. bool success = writer->WriteClass(&m_deprecationTestClass);
  2008. EXPECT_TRUE(success);
  2009. }
  2010. void CheckDeprecated(void* classPtr, const Uuid& classId)
  2011. {
  2012. (void)classPtr;
  2013. (void)classId;
  2014. // We should never hit here since our class was deprecated
  2015. EXPECT_TRUE(false);
  2016. }
  2017. void CheckMemberDeprecation(void* classPtr, const Uuid& classId)
  2018. {
  2019. (void)classId;
  2020. DeprecationTestClass* obj = reinterpret_cast<DeprecationTestClass*>(classPtr);
  2021. EXPECT_EQ( 0, obj->m_deprecated.m_data );
  2022. EXPECT_EQ( nullptr, obj->m_deprecatedPtr );
  2023. EXPECT_EQ( 0, obj->m_oldClassData );
  2024. EXPECT_EQ( 0.f, obj->m_newClassData );
  2025. EXPECT_EQ( 0, obj->m_missingMember );
  2026. EXPECT_EQ( m_deprecationTestClass.m_data, obj->m_data );
  2027. delete obj;
  2028. }
  2029. void run()
  2030. {
  2031. m_deprecated.m_data = 10;
  2032. m_deprecationTestClass.m_deprecated.m_data = 10;
  2033. m_deprecationTestClass.m_deprecatedPtr = aznew DeprecatedClass;
  2034. m_deprecationTestClass.m_oldClassData = 10;
  2035. m_deprecationTestClass.m_missingMember = 10;
  2036. m_deprecationTestClass.m_data = 10;
  2037. // Test new version without conversion.
  2038. // -Member types without reflection should be silently dropped.
  2039. // -Members whose reflection data don't match should be silently dropped.
  2040. // -Members whose names don't match should be silently dropped.
  2041. // -The converted class itself should still be accepted.
  2042. AZ_TracePrintf("SerializeDeprecationTest", "\nTesting dropped/deprecated members:\n");
  2043. {
  2044. // Write original data
  2045. AZStd::vector<char> xmlBuffer;
  2046. AZStd::vector<char> jsonBuffer;
  2047. AZStd::vector<char> binaryBuffer;
  2048. {
  2049. SerializeContext sc;
  2050. sc.Class<DeprecatedClass>()
  2051. ->Field("m_data", &DeprecatedClass::m_data);
  2052. sc.Class<DeprecationTestClass>()
  2053. ->Field("m_deprecated", &DeprecationTestClass::m_deprecated)
  2054. ->Field("m_deprecatedPtr", &DeprecationTestClass::m_deprecatedPtr)
  2055. ->Field("m_oldClassData", &DeprecationTestClass::m_oldClassData)
  2056. ->Field("m_missingMember", &DeprecationTestClass::m_missingMember)
  2057. ->Field("m_data", &DeprecationTestClass::m_data);
  2058. // XML
  2059. IO::ByteContainerStream<AZStd::vector<char> > xmlStream(&xmlBuffer);
  2060. AZ_TracePrintf("SerializeDeprecationTest", "Writing XML\n");
  2061. ObjectStream* xmlObjStream = ObjectStream::Create(&xmlStream, sc, ObjectStream::ST_XML);
  2062. WriteDeprecationTestClass(xmlObjStream);
  2063. bool success = xmlObjStream->Finalize();
  2064. EXPECT_TRUE(success);
  2065. // JSON
  2066. IO::ByteContainerStream<AZStd::vector<char> > jsonStream(&jsonBuffer);
  2067. AZ_TracePrintf("SerializeDeprecationTest", "Writing JSON\n");
  2068. ObjectStream* jsonObjStream = ObjectStream::Create(&jsonStream, sc, ObjectStream::ST_JSON);
  2069. WriteDeprecationTestClass(jsonObjStream);
  2070. success = jsonObjStream->Finalize();
  2071. EXPECT_TRUE(success);
  2072. // Binary
  2073. IO::ByteContainerStream<AZStd::vector<char> > binaryStream(&binaryBuffer);
  2074. AZ_TracePrintf("SerializeDeprecationTest", "Writing Binary\n");
  2075. ObjectStream* binaryObjStream = ObjectStream::Create(&binaryStream, sc, ObjectStream::ST_BINARY);
  2076. WriteDeprecationTestClass(binaryObjStream);
  2077. success = binaryObjStream->Finalize();
  2078. EXPECT_TRUE(success);
  2079. }
  2080. ObjectStream::ClassReadyCB readyCB(AZStd::bind(&DeprecationTest::CheckMemberDeprecation, this, AZStd::placeholders::_1, AZStd::placeholders::_2));
  2081. // Test deprecation with one member class not reflected at all
  2082. {
  2083. SerializeContext sc;
  2084. sc.Class<DeprecationTestClass>()
  2085. ->Version(2)
  2086. ->Field("m_deprecated", &DeprecationTestClass::m_deprecated)
  2087. ->Field("m_deprecatedPtr", &DeprecationTestClass::m_deprecatedPtr)
  2088. ->Field("m_oldClassData", &DeprecationTestClass::m_newClassData)
  2089. ->Field("m_data", &DeprecationTestClass::m_data);
  2090. // XML
  2091. AZ_TracePrintf("SerializeDeprecationTest", "Loading XML with dropped class\n");
  2092. IO::ByteContainerStream<const AZStd::vector<char> > xmlStream(&xmlBuffer);
  2093. xmlStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2094. ObjectStream::LoadBlocking(&xmlStream, sc, readyCB);
  2095. // JSON
  2096. AZ_TracePrintf("SerializeDeprecationTest", "Loading JSON with dropped class\n");
  2097. IO::ByteContainerStream<const AZStd::vector<char> > jsonStream(&jsonBuffer);
  2098. jsonStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2099. ObjectStream::LoadBlocking(&jsonStream, sc, readyCB);
  2100. // Binary
  2101. AZ_TracePrintf("SerializeDeprecationTest", "Loading Binary with dropped class\n");
  2102. IO::ByteContainerStream<const AZStd::vector<char> > binaryStream(&binaryBuffer);
  2103. binaryStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2104. ObjectStream::LoadBlocking(&binaryStream, sc, readyCB);
  2105. }
  2106. // Test deprecation with one member class marked as deprecated
  2107. {
  2108. SerializeContext sc;
  2109. sc.ClassDeprecate("DeprecatedClass", AZ::Uuid("{893CA46E-6D1A-4D27-94F7-09E26DE5AE4B}"));
  2110. sc.Class<DeprecationTestClass>()
  2111. ->Version(2)
  2112. ->Field("m_deprecated", &DeprecationTestClass::m_deprecated)
  2113. ->Field("m_deprecatedPtr", &DeprecationTestClass::m_deprecatedPtr)
  2114. ->Field("m_oldClassData", &DeprecationTestClass::m_newClassData)
  2115. ->Field("m_data", &DeprecationTestClass::m_data);
  2116. // XML
  2117. AZ_TracePrintf("SerializeDeprecationTest", "Loading XML with deprecated class\n");
  2118. IO::ByteContainerStream<const AZStd::vector<char> > xmlStream(&xmlBuffer);
  2119. xmlStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2120. ObjectStream::LoadBlocking(&xmlStream, sc, readyCB);
  2121. // JSON
  2122. AZ_TracePrintf("SerializeDeprecationTest", "Loading JSON with deprecated class\n");
  2123. IO::ByteContainerStream<const AZStd::vector<char> > jsonStream(&jsonBuffer);
  2124. jsonStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2125. ObjectStream::LoadBlocking(&jsonStream, sc, readyCB);
  2126. // Binary
  2127. AZ_TracePrintf("SerializeDeprecationTest", "Loading Binary with deprecated class\n");
  2128. IO::ByteContainerStream<const AZStd::vector<char> > binaryStream(&binaryBuffer);
  2129. binaryStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2130. ObjectStream::LoadBlocking(&binaryStream, sc, readyCB);
  2131. }
  2132. // Test deprecation with a converter to an entirely new type.
  2133. {
  2134. SerializeContext sc;
  2135. sc.Class<DeprecationTestClass>()
  2136. ->Version(2)
  2137. ->Field("m_deprecated", &DeprecationTestClass::m_deprecated)
  2138. ->Field("m_deprecatedPtr", &DeprecationTestClass::m_deprecatedPtr)
  2139. ->Field("m_oldClassData", &DeprecationTestClass::m_newClassData)
  2140. ->Field("m_data", &DeprecationTestClass::m_data);
  2141. AZ::SerializeContext::VersionConverter converter = [](AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) -> bool
  2142. {
  2143. return classElement.Convert<DeprecationTestClass>(context);
  2144. };
  2145. sc.ClassDeprecate("DeprecatedClass", AZ::Uuid("{893CA46E-6D1A-4D27-94F7-09E26DE5AE4B}"), converter);
  2146. // XML
  2147. AZ_TracePrintf("SerializeDeprecationTest", "Loading XML with deprecated class\n");
  2148. IO::ByteContainerStream<const AZStd::vector<char> > xmlStream(&xmlBuffer);
  2149. xmlStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2150. ObjectStream::LoadBlocking(&xmlStream, sc, readyCB);
  2151. // JSON
  2152. AZ_TracePrintf("SerializeDeprecationTest", "Loading JSON with deprecated class\n");
  2153. IO::ByteContainerStream<const AZStd::vector<char> > jsonStream(&jsonBuffer);
  2154. jsonStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2155. ObjectStream::LoadBlocking(&jsonStream, sc, readyCB);
  2156. // Binary
  2157. AZ_TracePrintf("SerializeDeprecationTest", "Loading Binary with deprecated class\n");
  2158. IO::ByteContainerStream<const AZStd::vector<char> > binaryStream(&binaryBuffer);
  2159. binaryStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2160. ObjectStream::LoadBlocking(&binaryStream, sc, readyCB);
  2161. }
  2162. // Test a converter that completely swaps uuid.
  2163. // This test should FAIL, because the uuid cannot be swapped in non-deprecation cases.
  2164. {
  2165. SerializeContext sc;
  2166. sc.Class<SimpleBaseClass>()
  2167. ->Version(1)
  2168. ->Field("m_data", &SimpleBaseClass::m_data);
  2169. AZ::SerializeContext::VersionConverter converter = [](AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) -> bool
  2170. {
  2171. return classElement.Convert<SimpleBaseClass>(context);
  2172. };
  2173. sc.Class<DeprecationTestClass>()
  2174. ->Version(3, converter)
  2175. ->Field("m_oldClassData", &DeprecationTestClass::m_newClassData)
  2176. ->Field("m_data", &DeprecationTestClass::m_data);
  2177. // XML
  2178. AZ_TracePrintf("SerializeDeprecationTest", "Loading XML with deprecated class\n");
  2179. IO::ByteContainerStream<const AZStd::vector<char> > xmlStream(&xmlBuffer);
  2180. xmlStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2181. // This should fail!
  2182. AZ_TEST_START_TRACE_SUPPRESSION;
  2183. ObjectStream::LoadBlocking(&xmlStream, sc, readyCB);
  2184. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  2185. }
  2186. // Test a converter that swaps uuid to a castable/compatible type in a deprecation converter.
  2187. {
  2188. SimpleDerivedClass1 simpleDerivedClass1;
  2189. OwnerClass ownerClass;
  2190. ownerClass.m_pointer = &simpleDerivedClass1;
  2191. SerializeContext sc;
  2192. sc.Class<SimpleBaseClass>()
  2193. ->Version(1)
  2194. ->Field("m_data", &SimpleBaseClass::m_data);
  2195. sc.Class<SimpleDerivedClass1, SimpleBaseClass>()
  2196. ->Version(1);
  2197. sc.Class<SimpleDerivedClass2, SimpleBaseClass>()
  2198. ->Version(1);
  2199. sc.Class<OwnerClass>()
  2200. ->Version(1)
  2201. ->Field("Pointer", &OwnerClass::m_pointer);
  2202. AZStd::vector<char> xmlBufferUuidTest;
  2203. AZStd::vector<char> jsonBufferUuidTest;
  2204. AZStd::vector<char> binaryBufferUuidTest;
  2205. {
  2206. // XML
  2207. IO::ByteContainerStream<AZStd::vector<char> > xmlStream(&xmlBufferUuidTest);
  2208. AZ_TracePrintf("SerializeDeprecationTest", "Writing XML\n");
  2209. ObjectStream* xmlObjStream = ObjectStream::Create(&xmlStream, sc, ObjectStream::ST_XML);
  2210. xmlObjStream->WriteClass(&ownerClass);
  2211. bool success = xmlObjStream->Finalize();
  2212. EXPECT_TRUE(success);
  2213. // JSON
  2214. IO::ByteContainerStream<AZStd::vector<char> > jsonStream(&jsonBufferUuidTest);
  2215. AZ_TracePrintf("SerializeDeprecationTest", "Writing JSON\n");
  2216. ObjectStream* jsonObjStream = ObjectStream::Create(&jsonStream, sc, ObjectStream::ST_JSON);
  2217. jsonObjStream->WriteClass(&ownerClass);
  2218. success = jsonObjStream->Finalize();
  2219. EXPECT_TRUE(success);
  2220. // Binary
  2221. IO::ByteContainerStream<AZStd::vector<char> > binaryStream(&binaryBufferUuidTest);
  2222. AZ_TracePrintf("SerializeDeprecationTest", "Writing Binary\n");
  2223. ObjectStream* binaryObjStream = ObjectStream::Create(&binaryStream, sc, ObjectStream::ST_BINARY);
  2224. binaryObjStream->WriteClass(&ownerClass);
  2225. success = binaryObjStream->Finalize();
  2226. EXPECT_TRUE(success);
  2227. }
  2228. sc.EnableRemoveReflection();
  2229. sc.Class<OwnerClass>();
  2230. sc.DisableRemoveReflection();
  2231. AZ::SerializeContext::VersionConverter converter = [](AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) -> bool
  2232. {
  2233. const int idx = classElement.FindElement(AZ_CRC("Pointer", 0x320468a8));
  2234. classElement.GetSubElement(idx).Convert<SimpleDerivedClass2>(context);
  2235. return true;
  2236. };
  2237. sc.Class<OwnerClass>()
  2238. ->Version(2, converter)
  2239. ->Field("Pointer", &OwnerClass::m_pointer);
  2240. auto cb = [](void* classPtr, const Uuid& classId, SerializeContext* /*context*/) -> void
  2241. {
  2242. EXPECT_EQ( AzTypeInfo<OwnerClass>::Uuid(), classId );
  2243. EXPECT_TRUE(static_cast<OwnerClass*>(classPtr)->m_pointer);
  2244. EXPECT_EQ( AzTypeInfo<SimpleDerivedClass2>::Uuid(), static_cast<OwnerClass*>(classPtr)->m_pointer->RTTI_GetType() );
  2245. delete static_cast<OwnerClass*>(classPtr)->m_pointer;
  2246. delete static_cast<OwnerClass*>(classPtr);
  2247. };
  2248. ObjectStream::ClassReadyCB readyCBTest(cb);
  2249. // XML
  2250. AZ_TracePrintf("SerializeDeprecationTest", "Loading XML with deprecated class\n");
  2251. IO::ByteContainerStream<const AZStd::vector<char> > xmlStreamUuidTest(&xmlBufferUuidTest);
  2252. xmlStreamUuidTest.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2253. EXPECT_TRUE(ObjectStream::LoadBlocking(&xmlStreamUuidTest, sc, readyCBTest));
  2254. // JSON
  2255. AZ_TracePrintf("SerializeDeprecationTest", "Loading JSON with deprecated class\n");
  2256. IO::ByteContainerStream<const AZStd::vector<char> > jsonStream(&jsonBufferUuidTest);
  2257. jsonStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2258. ObjectStream::LoadBlocking(&jsonStream, sc, readyCBTest);
  2259. // Binary
  2260. AZ_TracePrintf("SerializeDeprecationTest", "Loading Binary with deprecated class\n");
  2261. IO::ByteContainerStream<const AZStd::vector<char> > binaryStream(&binaryBufferUuidTest);
  2262. binaryStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2263. ObjectStream::LoadBlocking(&binaryStream, sc, readyCBTest);
  2264. }
  2265. }
  2266. // Test root objects of deprecated classes.
  2267. // -Classes reflected as deprecated should be silently dropped.
  2268. AZ_TracePrintf("SerializeDeprecationTest", "Testing deprecated root objects:\n");
  2269. {
  2270. AZStd::vector<char> xmlBuffer;
  2271. AZStd::vector<char> jsonBuffer;
  2272. AZStd::vector<char> binaryBuffer;
  2273. // Write original data
  2274. {
  2275. SerializeContext sc;
  2276. sc.Class<DeprecatedClass>()
  2277. ->Field("m_data", &DeprecatedClass::m_data);
  2278. // XML
  2279. AZ_TracePrintf("SerializeDeprecationTest", "Writing XML\n");
  2280. IO::ByteContainerStream<AZStd::vector<char> > xmlStream(&xmlBuffer);
  2281. ObjectStream* xmlObjStream = ObjectStream::Create(&xmlStream, sc, ObjectStream::ST_XML);
  2282. WriteDeprecated(xmlObjStream);
  2283. bool success = xmlObjStream->Finalize();
  2284. EXPECT_TRUE(success);
  2285. // JSON
  2286. AZ_TracePrintf("SerializeDeprecationTest", "Writing JSON\n");
  2287. IO::ByteContainerStream<AZStd::vector<char> > jsonStream(&jsonBuffer);
  2288. ObjectStream* jsonObjStream = ObjectStream::Create(&jsonStream, sc, ObjectStream::ST_JSON);
  2289. WriteDeprecated(jsonObjStream);
  2290. success = jsonObjStream->Finalize();
  2291. EXPECT_TRUE(success);
  2292. // Binary
  2293. AZ_TracePrintf("SerializeDeprecationTest", "Writing Binary\n");
  2294. IO::ByteContainerStream<AZStd::vector<char> > binaryStream(&binaryBuffer);
  2295. ObjectStream* binaryObjStream = ObjectStream::Create(&binaryStream, sc, ObjectStream::ST_BINARY);
  2296. WriteDeprecated(binaryObjStream);
  2297. success = binaryObjStream->Finalize();
  2298. EXPECT_TRUE(success);
  2299. }
  2300. // Test deprecation
  2301. {
  2302. SerializeContext sc;
  2303. sc.ClassDeprecate("DeprecatedClass", AZ::Uuid("{893CA46E-6D1A-4D27-94F7-09E26DE5AE4B}"));
  2304. ObjectStream::ClassReadyCB readyCB(AZStd::bind(&DeprecationTest::CheckDeprecated, this, AZStd::placeholders::_1, AZStd::placeholders::_2));
  2305. // XML
  2306. AZ_TracePrintf("SerializeDeprecationTest", "Loading XML with deprecated root object\n");
  2307. IO::ByteContainerStream<const AZStd::vector<char> > xmlStream(&xmlBuffer);
  2308. xmlStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2309. ObjectStream::LoadBlocking(&xmlStream, sc, readyCB);
  2310. // JSON
  2311. AZ_TracePrintf("SerializeDeprecationTest", "Loading JSON with deprecated root object\n");
  2312. IO::ByteContainerStream<const AZStd::vector<char> > jsonStream(&jsonBuffer);
  2313. jsonStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2314. ObjectStream::LoadBlocking(&jsonStream, sc, readyCB);
  2315. // Binary
  2316. AZ_TracePrintf("SerializeDeprecationTest", "Loading Binary with deprecated root object\n");
  2317. IO::ByteContainerStream<const AZStd::vector<char> > binaryStream(&binaryBuffer);
  2318. binaryStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  2319. ObjectStream::LoadBlocking(&binaryStream, sc, readyCB);
  2320. }
  2321. }
  2322. m_deprecationTestClass.Clear();
  2323. }
  2324. };
  2325. DeprecationTest test;
  2326. test.run();
  2327. }
  2328. /*
  2329. * Test complicated conversion
  2330. */
  2331. namespace Conversion
  2332. {
  2333. struct TestObj
  2334. {
  2335. AZ_TYPE_INFO(TestObj, "{6AE2EE4A-1DB8-41B7-B909-296A10CEF4EA}");
  2336. AZ_CLASS_ALLOCATOR(TestObj, AZ::SystemAllocator);
  2337. TestObj() = default;
  2338. Generics m_dataOld;
  2339. GenericsNew m_dataNew;
  2340. };
  2341. }
  2342. /*
  2343. * Data Overlay Test
  2344. */
  2345. namespace DataOverlay
  2346. {
  2347. struct DataOverlayTestStruct
  2348. {
  2349. AZ_TYPE_INFO(DataOverlayTestStruct, "{AD843B4D-0D08-4CE0-99F9-7E4E1EAD5984}");
  2350. AZ_CLASS_ALLOCATOR(DataOverlayTestStruct, AZ::SystemAllocator);
  2351. DataOverlayTestStruct()
  2352. : m_int(0)
  2353. , m_ptr(nullptr) {}
  2354. int m_int;
  2355. AZStd::vector<int> m_intVector;
  2356. DataOverlayTestStruct* m_ptr;
  2357. };
  2358. }
  2359. TEST_F(Serialization, DataOverlayTest)
  2360. {
  2361. using namespace DataOverlay;
  2362. class DataOverlayTest
  2363. {
  2364. class DataOverlayProviderExample
  2365. : public DataOverlayProviderBus::Handler
  2366. {
  2367. public:
  2368. static DataOverlayProviderId GetProviderId() { return AZ_CRC("DataOverlayProviderExample", 0x60dafdbd); }
  2369. static u32 GetIntToken() { return AZ_CRC("int_data", 0xd74868f3); }
  2370. static u32 GetVectorToken() { return AZ_CRC("vector_data", 0x0aca20c0); }
  2371. static u32 GetPointerToken() { return AZ_CRC("pointer_data", 0xa46a746e); }
  2372. DataOverlayProviderExample()
  2373. {
  2374. m_ptrData.m_int = 5;
  2375. m_ptrData.m_intVector.push_back(1);
  2376. m_ptrData.m_ptr = nullptr;
  2377. m_data.m_int = 3;
  2378. m_data.m_intVector.push_back(10);
  2379. m_data.m_intVector.push_back(20);
  2380. m_data.m_intVector.push_back(30);
  2381. m_data.m_ptr = &m_ptrData;
  2382. }
  2383. void FillOverlayData(DataOverlayTarget* dest, const DataOverlayToken& dataToken) override
  2384. {
  2385. if (*reinterpret_cast<const u32*>(dataToken.m_dataUri.data()) == GetIntToken())
  2386. {
  2387. dest->SetData(m_data.m_int);
  2388. }
  2389. else if (*reinterpret_cast<const u32*>(dataToken.m_dataUri.data()) == GetVectorToken())
  2390. {
  2391. dest->SetData(m_data.m_intVector);
  2392. }
  2393. else if (*reinterpret_cast<const u32*>(dataToken.m_dataUri.data()) == GetPointerToken())
  2394. {
  2395. dest->SetData(*m_data.m_ptr);
  2396. }
  2397. }
  2398. DataOverlayTestStruct m_data;
  2399. DataOverlayTestStruct m_ptrData;
  2400. };
  2401. class DataOverlayInstanceEnumeratorExample
  2402. : public DataOverlayInstanceBus::Handler
  2403. {
  2404. public:
  2405. enum InstanceType
  2406. {
  2407. Type_Int,
  2408. Type_Vector,
  2409. Type_Pointer,
  2410. };
  2411. DataOverlayInstanceEnumeratorExample(InstanceType type)
  2412. : m_type(type) {}
  2413. ~DataOverlayInstanceEnumeratorExample() override
  2414. {
  2415. BusDisconnect();
  2416. }
  2417. DataOverlayInfo GetOverlayInfo() override
  2418. {
  2419. DataOverlayInfo info;
  2420. info.m_providerId = DataOverlayProviderExample::GetProviderId();
  2421. u32 token = m_type == Type_Int ? DataOverlayProviderExample::GetIntToken() : m_type == Type_Vector ? DataOverlayProviderExample::GetVectorToken() : DataOverlayProviderExample::GetPointerToken();
  2422. info.m_dataToken.m_dataUri.insert(info.m_dataToken.m_dataUri.end(), reinterpret_cast<u8*>(&token), reinterpret_cast<u8*>(&token) + sizeof(u32));
  2423. return info;
  2424. }
  2425. InstanceType m_type;
  2426. };
  2427. void CheckOverlay(const DataOverlayTestStruct* controlData, void* classPtr, const Uuid& uuid)
  2428. {
  2429. EXPECT_EQ( SerializeTypeInfo<DataOverlayTestStruct>::GetUuid(), uuid );
  2430. DataOverlayTestStruct* newData = reinterpret_cast<DataOverlayTestStruct*>(classPtr);
  2431. EXPECT_EQ( controlData->m_int, newData->m_int );
  2432. EXPECT_EQ( controlData->m_intVector, newData->m_intVector );
  2433. EXPECT_TRUE(newData->m_ptr != nullptr);
  2434. EXPECT_TRUE(newData->m_ptr != controlData->m_ptr);
  2435. EXPECT_EQ( controlData->m_ptr->m_int, newData->m_ptr->m_int );
  2436. EXPECT_EQ( controlData->m_ptr->m_intVector, newData->m_ptr->m_intVector );
  2437. EXPECT_EQ( controlData->m_ptr->m_ptr, newData->m_ptr->m_ptr );
  2438. delete newData->m_ptr;
  2439. delete newData;
  2440. }
  2441. public:
  2442. void run()
  2443. {
  2444. SerializeContext serializeContext;
  2445. // We must expose the class for serialization first.
  2446. serializeContext.Class<DataOverlayTestStruct>()
  2447. ->Field("int", &DataOverlayTestStruct::m_int)
  2448. ->Field("intVector", &DataOverlayTestStruct::m_intVector)
  2449. ->Field("pointer", &DataOverlayTestStruct::m_ptr);
  2450. DataOverlayTestStruct testData;
  2451. testData.m_ptr = &testData;
  2452. DataOverlayInstanceEnumeratorExample intOverlayEnumerator(DataOverlayInstanceEnumeratorExample::Type_Int);
  2453. intOverlayEnumerator.BusConnect(DataOverlayInstanceId(&testData.m_int, SerializeTypeInfo<int>::GetUuid()));
  2454. DataOverlayInstanceEnumeratorExample vectorOverlayEnumerator(DataOverlayInstanceEnumeratorExample::Type_Vector);
  2455. vectorOverlayEnumerator.BusConnect(DataOverlayInstanceId(&testData.m_intVector, SerializeGenericTypeInfo<AZStd::vector<int> >::GetClassTypeId()));
  2456. DataOverlayInstanceEnumeratorExample pointerOverlayEnumerator(DataOverlayInstanceEnumeratorExample::Type_Pointer);
  2457. pointerOverlayEnumerator.BusConnect(DataOverlayInstanceId(&testData.m_ptr, SerializeTypeInfo<DataOverlayTestStruct>::GetUuid()));
  2458. // XML
  2459. AZStd::vector<char> xmlBuffer;
  2460. IO::ByteContainerStream<AZStd::vector<char> > xmlStream(&xmlBuffer);
  2461. ObjectStream* xmlObjStream = ObjectStream::Create(&xmlStream, serializeContext, ObjectStream::ST_XML);
  2462. xmlObjStream->WriteClass(&testData);
  2463. xmlObjStream->Finalize();
  2464. DataOverlayProviderExample overlayProvider;
  2465. overlayProvider.BusConnect(DataOverlayProviderExample::GetProviderId());
  2466. xmlStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  2467. ObjectStream::ClassReadyCB readyCB(AZStd::bind(&DataOverlayTest::CheckOverlay, this, &overlayProvider.m_data, AZStd::placeholders::_1, AZStd::placeholders::_2));
  2468. ObjectStream::LoadBlocking(&xmlStream, serializeContext, readyCB);
  2469. }
  2470. };
  2471. DataOverlayTest test;
  2472. test.run();
  2473. }
  2474. /*
  2475. * DynamicSerializableFieldTest
  2476. */
  2477. TEST_F(Serialization, DynamicSerializableFieldTest)
  2478. {
  2479. SerializeContext serializeContext;
  2480. // We must expose the class for serialization first.
  2481. MyClassBase1::Reflect(serializeContext);
  2482. MyClassBase2::Reflect(serializeContext);
  2483. MyClassBase3::Reflect(serializeContext);
  2484. SerializeTestClasses::MyClassMix::Reflect(serializeContext);
  2485. SerializeTestClasses::MyClassMix obj;
  2486. obj.Set(5); // Initialize with some value
  2487. DynamicSerializableField testData;
  2488. testData.m_data = &obj;
  2489. testData.m_typeId = SerializeTypeInfo<SerializeTestClasses::MyClassMix>::GetUuid();
  2490. // XML
  2491. AZStd::vector<char> xmlBuffer;
  2492. IO::ByteContainerStream<AZStd::vector<char> > xmlStream(&xmlBuffer);
  2493. ObjectStream* xmlObjStream = ObjectStream::Create(&xmlStream, serializeContext, ObjectStream::ST_XML);
  2494. xmlObjStream->WriteClass(&testData);
  2495. xmlObjStream->Finalize();
  2496. xmlStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  2497. auto verifyLoad = [&testData](void* classPtr, const Uuid& uuid, SerializeContext* sc) -> void
  2498. {
  2499. EXPECT_EQ( SerializeTypeInfo<DynamicSerializableField>::GetUuid(), uuid );
  2500. DynamicSerializableField* newData = reinterpret_cast<DynamicSerializableField*>(classPtr);
  2501. EXPECT_EQ( SerializeTypeInfo<SerializeTestClasses::MyClassMix>::GetUuid(), newData->m_typeId );
  2502. EXPECT_TRUE(newData->m_data != nullptr);
  2503. EXPECT_TRUE( *reinterpret_cast<SerializeTestClasses::MyClassMix*>(testData.m_data) == *reinterpret_cast<SerializeTestClasses::MyClassMix*>(newData->m_data) );
  2504. newData->DestroyData(sc);
  2505. azdestroy(newData, AZ::SystemAllocator, DynamicSerializableField);
  2506. };
  2507. ObjectStream::ClassReadyCB readyCB(verifyLoad);
  2508. ObjectStream::LoadBlocking(&xmlStream, serializeContext, readyCB);
  2509. }
  2510. /*
  2511. * DynamicSerializableFieldTest
  2512. */
  2513. class SerializeDynamicSerializableFieldTest
  2514. : public LeakDetectionFixture
  2515. {
  2516. public:
  2517. // Structure for reflecting Generic Template types to the Serialize context
  2518. // so that they get added to the SerializeContext m_uuidGenericMap
  2519. struct GenericTemplateTypes
  2520. {
  2521. AZ_TYPE_INFO(GenericTemplateTypes, "{24D83563-2AAA-40FE-8C77-0DC8298EDDEA}");
  2522. static void Reflect(AZ::SerializeContext& sc)
  2523. {
  2524. sc.Class<GenericTemplateTypes>()->
  2525. Field("stringToStringMap", &GenericTemplateTypes::m_stringStringMap)
  2526. ;
  2527. }
  2528. AZStd::unordered_map<AZStd::string, AZStd::string> m_stringStringMap;
  2529. };
  2530. };
  2531. TEST_F(SerializeDynamicSerializableFieldTest, NonSerializableTypeTest)
  2532. {
  2533. SerializeContext serializeContext;
  2534. DynamicSerializableField testData;
  2535. EXPECT_EQ(nullptr, testData.m_data);
  2536. EXPECT_EQ(AZ::Uuid::CreateNull(), testData.m_typeId);
  2537. // Write DynamicSerializableField to stream
  2538. AZStd::vector<AZ::u8> buffer;
  2539. AZ::IO::ByteContainerStream<decltype(buffer)> stream(&buffer);
  2540. {
  2541. ObjectStream* binObjectStream = ObjectStream::Create(&stream, serializeContext, ObjectStream::ST_BINARY);
  2542. binObjectStream->WriteClass(&testData);
  2543. binObjectStream->Finalize();
  2544. }
  2545. // Load DynamicSerializableField from stream
  2546. stream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  2547. {
  2548. DynamicSerializableField loadData;
  2549. loadData.m_typeId = AZ::Uuid::CreateRandom();
  2550. // TypeId should be serialized in as a null Uuid and the m_data field should remain unchanged
  2551. AZ::Utils::LoadObjectFromStreamInPlace(stream, loadData, &serializeContext);
  2552. EXPECT_EQ(AZ::Uuid::CreateNull(), loadData.m_typeId);
  2553. }
  2554. }
  2555. TEST_F(SerializeDynamicSerializableFieldTest, TemplateTypeSerializeTest)
  2556. {
  2557. SerializeContext serializeContext;
  2558. GenericTemplateTypes::Reflect(serializeContext);
  2559. DynamicSerializableField testData;
  2560. EXPECT_EQ(nullptr, testData.m_data);
  2561. EXPECT_EQ(AZ::Uuid::CreateNull(), testData.m_typeId);
  2562. AZStd::unordered_map<AZStd::string, AZStd::string> stringMap;
  2563. stringMap.emplace("Key", "Value");
  2564. stringMap.emplace("Lumber", "Yard");
  2565. testData.Set(&stringMap);
  2566. // Write DynamicSerializableField to stream
  2567. AZStd::vector<AZ::u8> buffer;
  2568. AZ::IO::ByteContainerStream<decltype(buffer)> stream(&buffer);
  2569. {
  2570. ObjectStream* binObjectStream = ObjectStream::Create(&stream, serializeContext, ObjectStream::ST_BINARY);
  2571. binObjectStream->WriteClass(&testData);
  2572. binObjectStream->Finalize();
  2573. }
  2574. // Load DynamicSerializableField from stream
  2575. stream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  2576. /* Loaded AZStd::Containers for serialization cannot be pointers, as they use to a NullFactory for heap creation
  2577. {
  2578. DynamicSerializableField loadData;
  2579. loadData.m_typeId = AZ::Uuid::CreateRandom();
  2580. AZ::Utils::LoadObjectFromStreamInPlace(stream, loadData, &serializeContext);
  2581. EXPECT_NE(nullptr, loadData.Get<decltype(stringMap)>());
  2582. auto& loadedStringMap = *loadData.Get<decltype(stringMap)>();
  2583. auto loadedStringIt = loadedStringMap.find("Lumber");
  2584. EXPECT_NE(loadedStringMap.end(), loadedStringIt);
  2585. EXPECT_EQ("Yard", loadedStringIt->second);
  2586. loadData.DestroyData(&serializeContext);
  2587. }
  2588. */
  2589. }
  2590. /*
  2591. * CloneTest
  2592. */
  2593. namespace Clone
  2594. {
  2595. struct RefCounted
  2596. {
  2597. AZ_CLASS_ALLOCATOR(RefCounted, AZ::SystemAllocator);
  2598. AZ_TYPE_INFO(RefCounted, "{ca52979d-b926-461a-b1f5-66bbfdb80639}");
  2599. RefCounted()
  2600. : m_refCount(0)
  2601. , m_data(0)
  2602. {}
  2603. RefCounted(int data)
  2604. : m_refCount(0)
  2605. , m_data(data)
  2606. {}
  2607. virtual ~RefCounted() = default;
  2608. static void Reflect(SerializeContext& serializeContext)
  2609. {
  2610. serializeContext.Class<RefCounted>()
  2611. ->Field("Data", &RefCounted::m_data);
  2612. }
  2613. //////////////////////////////////////////////////////////////////////////
  2614. // For intrusive pointers
  2615. void add_ref() { m_refCount++; }
  2616. void release()
  2617. {
  2618. --m_refCount;
  2619. if (m_refCount == 0)
  2620. {
  2621. delete this;
  2622. }
  2623. }
  2624. int m_refCount;
  2625. //////////////////////////////////////////////////////////////////////////
  2626. int m_data;
  2627. };
  2628. struct Clonable
  2629. {
  2630. Clonable()
  2631. : m_emptyInitText("Some init text!")
  2632. {
  2633. }
  2634. virtual ~Clonable() = default;
  2635. AZ_RTTI(Clonable, "{3E463CC3-CC78-4F21-9BE8-0B0AA10E8E26}");
  2636. AZ_CLASS_ALLOCATOR(Clonable, AZ::SystemAllocator);
  2637. static void Reflect(SerializeContext& serializeContext)
  2638. {
  2639. serializeContext.Class<Clonable>()
  2640. ->Field("m_int", &Clonable::m_int)
  2641. ->Field("m_emptyInitText", &Clonable::m_emptyInitText)
  2642. ->Field("m_map", &Clonable::m_map)
  2643. ->Field("m_fieldValues", &Clonable::m_fieldValues)
  2644. ->Field("m_smartArray", &Clonable::m_smartArray);
  2645. }
  2646. int m_int;
  2647. AZStd::string m_emptyInitText;
  2648. AZStd::unordered_map<int, int> m_map;
  2649. AZStd::vector<DynamicSerializableField> m_fieldValues;
  2650. AZStd::array<AZStd::intrusive_ptr<RefCounted>, 10> m_smartArray;
  2651. };
  2652. struct ClonableMutlipleInheritanceOrderingA
  2653. : public AZ::TickBus::Handler
  2654. , public RefCounted
  2655. , public Clonable
  2656. {
  2657. AZ_RTTI(ClonableMutlipleInheritanceOrderingA, "{4A1FA4E5-48FB-413D-876F-E6633240773A}", Clonable);
  2658. AZ_CLASS_ALLOCATOR(ClonableMutlipleInheritanceOrderingA, AZ::SystemAllocator);
  2659. ClonableMutlipleInheritanceOrderingA() = default;
  2660. ~ClonableMutlipleInheritanceOrderingA() override = default;
  2661. MOCK_METHOD2(OnTick, void (float, AZ::ScriptTimePoint));
  2662. virtual void MyNewVirtualFunction() {}
  2663. static void Reflect(SerializeContext& serializeContext)
  2664. {
  2665. serializeContext.Class<ClonableMutlipleInheritanceOrderingA, Clonable>()
  2666. ->Field("myInt0", &ClonableMutlipleInheritanceOrderingA::m_myInt0)
  2667. ;
  2668. }
  2669. int m_myInt0 = 0;
  2670. };
  2671. struct ClonableMutlipleInheritanceOrderingB
  2672. : public Clonable
  2673. , public RefCounted
  2674. , public AZ::TickBus::Handler
  2675. {
  2676. AZ_RTTI(ClonableMutlipleInheritanceOrderingB, "{169D8A4F-6C8A-4F50-8B7B-3EE81A9948BB}", Clonable);
  2677. AZ_CLASS_ALLOCATOR(ClonableMutlipleInheritanceOrderingB, AZ::SystemAllocator);
  2678. ClonableMutlipleInheritanceOrderingB() = default;
  2679. ~ClonableMutlipleInheritanceOrderingB() override = default;
  2680. MOCK_METHOD2(OnTick, void (float, AZ::ScriptTimePoint));
  2681. MOCK_METHOD0(SomeVirtualFunction, void ());
  2682. virtual char MyCharSumFunction() { return m_myChar0 + m_myChar1 + m_myChar2; }
  2683. virtual void MyCharResetFunction() { m_myChar0 = m_myChar1 = m_myChar2 = 0; }
  2684. static void Reflect(SerializeContext& serializeContext)
  2685. {
  2686. serializeContext.Class<ClonableMutlipleInheritanceOrderingB, Clonable>()
  2687. ->Field("myChar0", &ClonableMutlipleInheritanceOrderingB::m_myChar0)
  2688. ->Field("myChar1", &ClonableMutlipleInheritanceOrderingB::m_myChar1)
  2689. ->Field("myChar2", &ClonableMutlipleInheritanceOrderingB::m_myChar2)
  2690. ;
  2691. }
  2692. char m_myChar0 = 0;
  2693. char m_myChar1 = 1;
  2694. char m_myChar2 = 2;
  2695. };
  2696. struct ClonableAssociativePointerContainer
  2697. {
  2698. AZ_TYPE_INFO(ClonableAssociativePointerContainer, "{F558DC57-7850-42E1-9D16-5538C0D839E2}");
  2699. AZ_CLASS_ALLOCATOR(ClonableAssociativePointerContainer, AZ::SystemAllocator);
  2700. static void Reflect(SerializeContext& serializeContext)
  2701. {
  2702. serializeContext.Class<ClonableAssociativePointerContainer>()
  2703. ->Field("m_setOfPointers", &ClonableAssociativePointerContainer::m_setOfPointers)
  2704. ->Field("m_mapOfFloatPointers", &ClonableAssociativePointerContainer::m_mapOfFloatPointers)
  2705. ->Field("m_sharedEntityPointer", &ClonableAssociativePointerContainer::m_sharedEntityPointer)
  2706. ;
  2707. }
  2708. AZStd::unordered_set<AZ::Entity*> m_setOfPointers;
  2709. AZStd::unordered_map<int, float*> m_mapOfFloatPointers;
  2710. AZStd::shared_ptr<AZ::Entity> m_sharedEntityPointer;
  2711. };
  2712. }
  2713. TEST_F(Serialization, CloneTest)
  2714. {
  2715. using namespace Clone;
  2716. // We must expose the class for serialization first.
  2717. MyClassBase1::Reflect((*m_serializeContext));
  2718. MyClassBase2::Reflect((*m_serializeContext));
  2719. MyClassBase3::Reflect((*m_serializeContext));
  2720. SerializeTestClasses::MyClassMix::Reflect((*m_serializeContext));
  2721. RefCounted::Reflect((*m_serializeContext));
  2722. Clonable::Reflect((*m_serializeContext));
  2723. Clonable testObj;
  2724. testObj.m_int = 100;
  2725. testObj.m_emptyInitText = ""; // set to empty to make sure we write zero values
  2726. testObj.m_map.insert(AZStd::make_pair(1, 2));
  2727. testObj.m_smartArray[0] = aznew RefCounted(101);
  2728. testObj.m_smartArray[1] = aznew RefCounted(201);
  2729. testObj.m_smartArray[2] = aznew RefCounted(301);
  2730. SerializeTestClasses::MyClassMix val1;
  2731. val1.Set(5); // Initialize with some value
  2732. DynamicSerializableField valField1;
  2733. valField1.m_data = &val1;
  2734. valField1.m_typeId = SerializeTypeInfo<SerializeTestClasses::MyClassMix>::GetUuid();
  2735. testObj.m_fieldValues.push_back(valField1);
  2736. Clonable* cloneObj = m_serializeContext->CloneObject(&testObj);
  2737. EXPECT_TRUE(cloneObj);
  2738. EXPECT_EQ( testObj.m_int, cloneObj->m_int );
  2739. EXPECT_EQ( testObj.m_emptyInitText, cloneObj->m_emptyInitText );
  2740. EXPECT_EQ( testObj.m_map, cloneObj->m_map );
  2741. EXPECT_EQ( testObj.m_fieldValues.size(), cloneObj->m_fieldValues.size() );
  2742. EXPECT_TRUE(cloneObj->m_fieldValues[0].m_data);
  2743. EXPECT_TRUE(cloneObj->m_fieldValues[0].m_data != testObj.m_fieldValues[0].m_data);
  2744. EXPECT_TRUE( *reinterpret_cast<SerializeTestClasses::MyClassMix*>(testObj.m_fieldValues[0].m_data) == *reinterpret_cast<SerializeTestClasses::MyClassMix*>(cloneObj->m_fieldValues[0].m_data) );
  2745. delete reinterpret_cast<SerializeTestClasses::MyClassMix*>(cloneObj->m_fieldValues[0].m_data);
  2746. AZ_TEST_ASSERT(cloneObj->m_smartArray[0] && cloneObj->m_smartArray[0]->m_data == 101);
  2747. AZ_TEST_ASSERT(cloneObj->m_smartArray[1] && cloneObj->m_smartArray[1]->m_data == 201);
  2748. AZ_TEST_ASSERT(cloneObj->m_smartArray[2] && cloneObj->m_smartArray[2]->m_data == 301);
  2749. delete cloneObj;
  2750. delete reinterpret_cast<SerializeTestClasses::MyClassMix*>(testObj.m_fieldValues[0].m_data);
  2751. }
  2752. TEST_F(Serialization, CloneInplaceTest)
  2753. {
  2754. using namespace Clone;
  2755. // We must expose the class for serialization first.
  2756. MyClassBase1::Reflect(*m_serializeContext);
  2757. MyClassBase2::Reflect(*m_serializeContext);
  2758. MyClassBase3::Reflect(*m_serializeContext);
  2759. SerializeTestClasses::MyClassMix::Reflect(*m_serializeContext);
  2760. RefCounted::Reflect(*m_serializeContext);
  2761. Clonable::Reflect(*m_serializeContext);
  2762. Clonable testObj;
  2763. testObj.m_int = 100;
  2764. testObj.m_emptyInitText = ""; // set to empty to make sure we write zero values
  2765. testObj.m_map.insert(AZStd::make_pair(1, 2));
  2766. testObj.m_smartArray[0] = aznew RefCounted(101);
  2767. testObj.m_smartArray[1] = aznew RefCounted(201);
  2768. testObj.m_smartArray[2] = aznew RefCounted(301);
  2769. SerializeTestClasses::MyClassMix val1;
  2770. val1.Set(5); // Initialize with some value
  2771. DynamicSerializableField valField1;
  2772. valField1.m_data = &val1;
  2773. valField1.m_typeId = SerializeTypeInfo<SerializeTestClasses::MyClassMix>::GetUuid();
  2774. testObj.m_fieldValues.push_back(valField1);
  2775. Clonable cloneObj;
  2776. m_serializeContext->CloneObjectInplace(cloneObj, &testObj);
  2777. EXPECT_EQ(testObj.m_int, cloneObj.m_int);
  2778. EXPECT_EQ(testObj.m_emptyInitText, cloneObj.m_emptyInitText);
  2779. EXPECT_EQ(testObj.m_map, cloneObj.m_map);
  2780. EXPECT_EQ(testObj.m_fieldValues.size(), cloneObj.m_fieldValues.size());
  2781. EXPECT_TRUE(cloneObj.m_fieldValues[0].m_data);
  2782. EXPECT_TRUE(cloneObj.m_fieldValues[0].m_data != testObj.m_fieldValues[0].m_data);
  2783. EXPECT_TRUE(*reinterpret_cast<SerializeTestClasses::MyClassMix*>(testObj.m_fieldValues[0].m_data) == *reinterpret_cast<SerializeTestClasses::MyClassMix*>(cloneObj.m_fieldValues[0].m_data));
  2784. delete reinterpret_cast<SerializeTestClasses::MyClassMix*>(cloneObj.m_fieldValues[0].m_data);
  2785. AZ_TEST_ASSERT(cloneObj.m_smartArray[0] && cloneObj.m_smartArray[0]->m_data == 101);
  2786. AZ_TEST_ASSERT(cloneObj.m_smartArray[1] && cloneObj.m_smartArray[1]->m_data == 201);
  2787. AZ_TEST_ASSERT(cloneObj.m_smartArray[2] && cloneObj.m_smartArray[2]->m_data == 301);
  2788. delete reinterpret_cast<SerializeTestClasses::MyClassMix*>(testObj.m_fieldValues[0].m_data);
  2789. }
  2790. TEST_F(Serialization, CloneAssociativeContainerOfPointersTest)
  2791. {
  2792. using namespace Clone;
  2793. // We must expose the class for serialization first.
  2794. AZ::Entity::Reflect(m_serializeContext.get());
  2795. ClonableAssociativePointerContainer::Reflect(*m_serializeContext);
  2796. ClonableAssociativePointerContainer testObj;
  2797. testObj.m_setOfPointers.insert(aznew AZ::Entity("Entity1"));
  2798. testObj.m_setOfPointers.insert(aznew AZ::Entity("Entity2"));
  2799. testObj.m_mapOfFloatPointers.emplace(5, azcreate(float, (3.14f), AZ::SystemAllocator));
  2800. testObj.m_sharedEntityPointer.reset(aznew AZ::Entity("Entity3"));
  2801. ClonableAssociativePointerContainer* cloneObj = m_serializeContext->CloneObject(&testObj);
  2802. EXPECT_EQ(testObj.m_setOfPointers.size(), cloneObj->m_setOfPointers.size());
  2803. auto testObjSetBeginIt = testObj.m_setOfPointers.begin();
  2804. auto cloneObjSetBeginIt = cloneObj->m_setOfPointers.begin();
  2805. for (; testObjSetBeginIt != testObj.m_setOfPointers.end(); ++testObjSetBeginIt, ++cloneObjSetBeginIt)
  2806. {
  2807. EXPECT_EQ((*testObjSetBeginIt)->GetId(), (*cloneObjSetBeginIt)->GetId());
  2808. }
  2809. EXPECT_EQ(testObj.m_mapOfFloatPointers.size(), cloneObj->m_mapOfFloatPointers.size());
  2810. auto testObjMapBeginIt = testObj.m_mapOfFloatPointers.begin();
  2811. auto cloneObjMapBeginIt = cloneObj->m_mapOfFloatPointers.begin();
  2812. for (; testObjMapBeginIt != testObj.m_mapOfFloatPointers.end(); ++testObjMapBeginIt, ++cloneObjMapBeginIt)
  2813. {
  2814. EXPECT_EQ(*(testObjMapBeginIt->second), *(cloneObjMapBeginIt->second));
  2815. }
  2816. EXPECT_NE(nullptr, cloneObj->m_sharedEntityPointer.get());
  2817. EXPECT_EQ(testObj.m_sharedEntityPointer->GetId(), cloneObj->m_sharedEntityPointer->GetId());
  2818. //Free the allocated memory
  2819. for (auto& entitySet : { testObj.m_setOfPointers, cloneObj->m_setOfPointers })
  2820. {
  2821. for (AZ::Entity* entityPtr : entitySet)
  2822. {
  2823. delete entityPtr;
  2824. }
  2825. }
  2826. for (auto& intFloatPtrMap : { testObj.m_mapOfFloatPointers, cloneObj->m_mapOfFloatPointers })
  2827. {
  2828. for (auto& intFloatPtrPair : intFloatPtrMap)
  2829. {
  2830. azdestroy(intFloatPtrPair.second);
  2831. }
  2832. }
  2833. delete cloneObj;
  2834. }
  2835. struct TestCloneAssetData
  2836. : public AZ::Data::AssetData
  2837. {
  2838. AZ_CLASS_ALLOCATOR(TestCloneAssetData, AZ::SystemAllocator);
  2839. AZ_RTTI(TestCloneAssetData, "{0BAECA70-262F-4BDC-9D42-B7F7A10077DA}", AZ::Data::AssetData);
  2840. TestCloneAssetData() = default;
  2841. TestCloneAssetData(const AZ::Data::AssetId& assetId, AZ::Data::AssetData::AssetStatus status, uint32_t valueInt = 0)
  2842. : AZ::Data::AssetData(assetId, status)
  2843. , m_valueInt(valueInt)
  2844. {}
  2845. uint32_t m_valueInt{};
  2846. };
  2847. class TestCloneAssetHandler
  2848. : public AZ::Data::AssetHandler
  2849. , public AZ::Data::AssetCatalog
  2850. {
  2851. public:
  2852. AZ_CLASS_ALLOCATOR(TestCloneAssetHandler, AZ::SystemAllocator);
  2853. //////////////////////////////////////////////////////////////////////////
  2854. // AssetHandler
  2855. AZ::Data::AssetPtr CreateAsset(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) override
  2856. {
  2857. EXPECT_EQ(AzTypeInfo<TestCloneAssetData>::Uuid(), type);
  2858. return aznew TestCloneAssetData(id, AZ::Data::AssetData::AssetStatus::NotLoaded);
  2859. }
  2860. Data::AssetHandler::LoadResult LoadAssetData(
  2861. const AZ::Data::Asset<AZ::Data::AssetData>& asset,
  2862. AZStd::shared_ptr<AZ::Data::AssetDataStream> stream,
  2863. [[maybe_unused]] const AZ::Data::AssetFilterCB& assetLoadFilterCB) override
  2864. {
  2865. EXPECT_EQ(AzTypeInfo<TestCloneAssetData>::Uuid(), asset.GetType());
  2866. const size_t assetDataSize = static_cast<size_t>(stream->GetLength());
  2867. EXPECT_EQ(sizeof(TestCloneAssetData::m_valueInt), assetDataSize);
  2868. TestCloneAssetData* cloneAssetData = asset.GetAs<TestCloneAssetData>();
  2869. stream->Read(assetDataSize, &cloneAssetData->m_valueInt);
  2870. return Data::AssetHandler::LoadResult::LoadComplete;
  2871. }
  2872. bool SaveAssetData(const AZ::Data::Asset<AZ::Data::AssetData>& asset, IO::GenericStream* stream) override
  2873. {
  2874. EXPECT_EQ(AzTypeInfo<TestCloneAssetData>::Uuid(), asset.GetType());
  2875. TestCloneAssetData* cloneAssetData = asset.GetAs<TestCloneAssetData>();
  2876. EXPECT_NE(nullptr, cloneAssetData);
  2877. return Save(*cloneAssetData, stream);
  2878. }
  2879. bool Save(const TestCloneAssetData& testCloneAssetData, IO::GenericStream* stream) const
  2880. {
  2881. stream->Write(sizeof(TestCloneAssetData::m_valueInt), &testCloneAssetData.m_valueInt);
  2882. return true;
  2883. }
  2884. void DestroyAsset(AZ::Data::AssetPtr ptr) override
  2885. {
  2886. EXPECT_EQ(AzTypeInfo<TestCloneAssetData>::Uuid(), ptr->GetType());
  2887. delete ptr;
  2888. }
  2889. void GetHandledAssetTypes(AZStd::vector<AZ::Data::AssetType>& assetTypes) override
  2890. {
  2891. assetTypes.push_back(AzTypeInfo<TestCloneAssetData>::Uuid());
  2892. }
  2893. //////////////////////////////////////////////////////////////////////////
  2894. // AssetCatalog
  2895. // Redirects stream info request for assets to always return stream info needed to load a TestCloneAssetData
  2896. AZ::Data::AssetStreamInfo GetStreamInfoForLoad(const AZ::Data::AssetId&, const AZ::Data::AssetType& type) override
  2897. {
  2898. EXPECT_EQ(AzTypeInfo<TestCloneAssetData>::Uuid(), type);
  2899. AZ::Data::AssetStreamInfo info;
  2900. info.m_dataOffset = 0;
  2901. info.m_streamFlags = AZ::IO::OpenMode::ModeRead;
  2902. info.m_streamName = GetAssetFilename();
  2903. AZStd::string fullName = AZStd::string::format("%s%s", GetAssetFolderPath(), info.m_streamName.data());
  2904. info.m_dataLen = static_cast<size_t>(IO::SystemFile::Length(fullName.c_str()));
  2905. return info;
  2906. }
  2907. AZ::Data::AssetStreamInfo GetStreamInfoForSave(const AZ::Data::AssetId&, const AZ::Data::AssetType& type) override
  2908. {
  2909. EXPECT_EQ(AzTypeInfo<TestCloneAssetData>::Uuid(), type);
  2910. AZ::Data::AssetStreamInfo info;
  2911. info.m_dataOffset = 0;
  2912. info.m_streamFlags = AZ::IO::OpenMode::ModeWrite;
  2913. info.m_streamName = GetAssetFilename();
  2914. AZStd::string fullName = AZStd::string::format("%s%s", GetAssetFolderPath(), info.m_streamName.data());
  2915. info.m_dataLen = static_cast<size_t>(AZ::IO::SystemFile::Length(fullName.c_str()));
  2916. return info;
  2917. }
  2918. static const char* GetAssetFilename()
  2919. {
  2920. return "TestCloneAsset.bin";
  2921. }
  2922. static const char* GetAssetFolderPath()
  2923. {
  2924. return "";
  2925. }
  2926. };
  2927. struct TestCloneWrapperObject
  2928. {
  2929. AZ_TYPE_INFO(TestCloneWrapperObject, "{4BAE1D45-EFFD-4157-9F80-E20239265304}");
  2930. AZ_CLASS_ALLOCATOR(TestCloneWrapperObject, AZ::SystemAllocator);
  2931. static void Reflect(AZ::ReflectContext* reflectContext)
  2932. {
  2933. if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext))
  2934. {
  2935. serializeContext->Class<TestCloneWrapperObject>()
  2936. ->Field("TestCloneAsset", &TestCloneWrapperObject::m_cloneAsset);
  2937. }
  2938. }
  2939. AZ::Data::Asset<TestCloneAssetData> m_cloneAsset;
  2940. };
  2941. class SerializeAssetFixture
  2942. : public LeakDetectionFixture
  2943. {
  2944. public:
  2945. void SetUp() override
  2946. {
  2947. LeakDetectionFixture::SetUp();
  2948. m_prevFileIO = IO::FileIOBase::GetInstance();
  2949. IO::FileIOBase::SetInstance(&m_fileIO);
  2950. m_streamer = aznew IO::Streamer(AZStd::thread_desc{}, StreamerComponent::CreateStreamerStack());
  2951. Interface<IO::IStreamer>::Register(m_streamer);
  2952. m_serializeContext.reset(aznew AZ::SerializeContext());
  2953. TestCloneWrapperObject::Reflect(m_serializeContext.get());
  2954. // create the database
  2955. AZ::Data::AssetManager::Descriptor desc;
  2956. AZ::Data::AssetManager::Create(desc);
  2957. // create and register an asset handler
  2958. AZ::Data::AssetManager::Instance().RegisterHandler(&m_testAssetHandlerAndCatalog, AzTypeInfo<TestCloneAssetData>::Uuid());
  2959. AZ::Data::AssetManager::Instance().RegisterCatalog(&m_testAssetHandlerAndCatalog, AzTypeInfo<TestCloneAssetData>::Uuid());
  2960. CreateTestCloneAsset();
  2961. }
  2962. void TearDown() override
  2963. {
  2964. m_serializeContext->EnableRemoveReflection();
  2965. TestCloneWrapperObject::Reflect(m_serializeContext.get());
  2966. m_serializeContext->DisableRemoveReflection();
  2967. m_serializeContext.reset();
  2968. // destroy the database
  2969. AZ::Data::AssetManager::Instance().UnregisterHandler(&m_testAssetHandlerAndCatalog);
  2970. AZ::Data::AssetManager::Instance().UnregisterCatalog(&m_testAssetHandlerAndCatalog);
  2971. AZ::Data::AssetManager::Destroy();
  2972. Interface<IO::IStreamer>::Unregister(m_streamer);
  2973. delete m_streamer;
  2974. IO::FileIOBase::SetInstance(m_prevFileIO);
  2975. LeakDetectionFixture::TearDown();
  2976. }
  2977. void CreateTestCloneAsset()
  2978. {
  2979. AZ::IO::Path assetFullPath = m_tempDirectory.GetDirectory();
  2980. assetFullPath /= TestCloneAssetHandler::GetAssetFolderPath();
  2981. assetFullPath /= TestCloneAssetHandler::GetAssetFilename();
  2982. AZ::IO::FileIOStream cloneTestFileStream(assetFullPath.c_str(), AZ::IO::OpenMode::ModeWrite);
  2983. TestCloneAssetData testCloneAssetData;
  2984. testCloneAssetData.m_valueInt = 5;
  2985. m_testAssetHandlerAndCatalog.Save(testCloneAssetData, &cloneTestFileStream);
  2986. }
  2987. protected:
  2988. AZ::Test::ScopedAutoTempDirectory m_tempDirectory;
  2989. AZ::IO::FileIOBase* m_prevFileIO{};
  2990. AZ::IO::Streamer* m_streamer{};
  2991. TestFileIOBase m_fileIO;
  2992. TestCloneAssetHandler m_testAssetHandlerAndCatalog;
  2993. AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
  2994. };
  2995. TEST_F(SerializeAssetFixture, CloneObjectWithAssetReferenceTest)
  2996. {
  2997. static const AZ::Data::AssetId cloneObjectAssetId(AZ::Uuid("{AF338D46-C607-4F2B-8F0B-8828F88EA5F2}"));
  2998. {
  2999. // Create a TestCloneAssetData asset and keep a reference to in the local testCloneAsset variable so that the AssetManager manages the asset
  3000. AZ::Data::Asset<TestCloneAssetData> testCloneAsset = AZ::Data::AssetManager::Instance().CreateAsset(cloneObjectAssetId, AZ::AzTypeInfo<TestCloneAssetData>::Uuid(), AZ::Data::AssetLoadBehavior::Default);
  3001. testCloneAsset.Get()->m_valueInt = 15;
  3002. /* Create a testCloneWrapper object that has its Asset<T> object set to an AssetId, but not to a loaded asset.
  3003. The PreLoad flag is set on the Asset<T> to validate if the SerializeContext::CloneObject function is attempting to load the asset.
  3004. If the SerializeContext::CloneObject is not attempting to load the asset, then the cloned TestCloneWrapperObject m_cloneAsset member
  3005. should have its asset id set to cloneObjectAssetId without the asset being loaded
  3006. */
  3007. TestCloneWrapperObject testObj;
  3008. testObj.m_cloneAsset = AZ::Data::Asset<TestCloneAssetData>(cloneObjectAssetId, AZ::AzTypeInfo<TestCloneAssetData>::Uuid());
  3009. testObj.m_cloneAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad);
  3010. // the testCloneAsset should have one reference.
  3011. EXPECT_EQ(1, testCloneAsset.Get()->GetUseCount());
  3012. TestCloneWrapperObject clonedTestObj;
  3013. m_serializeContext->CloneObjectInplace(clonedTestObj, &testObj);
  3014. // the testCloneAsset should still be the only reference after the clone
  3015. EXPECT_EQ(1, testCloneAsset.Get()->GetUseCount());
  3016. // The cloned test object should not have AssetData associated with it,
  3017. // but should have the cloneObjectAssetId asset id set on it
  3018. EXPECT_EQ(cloneObjectAssetId, clonedTestObj.m_cloneAsset.GetId());
  3019. ASSERT_EQ(nullptr, clonedTestObj.m_cloneAsset.Get());
  3020. }
  3021. AZ::Data::AssetManager::Instance().DispatchEvents();
  3022. }
  3023. TEST_F(Serialization, CloneMultipleInheritance_RTTIBaseClassDiffererentOrder_KeepsCorrectOffsets)
  3024. {
  3025. using namespace Clone;
  3026. EXPECT_NE(sizeof(ClonableMutlipleInheritanceOrderingA), sizeof(ClonableMutlipleInheritanceOrderingB));
  3027. Clonable::Reflect(*m_serializeContext.get());
  3028. ClonableMutlipleInheritanceOrderingA::Reflect(*m_serializeContext.get());
  3029. ClonableMutlipleInheritanceOrderingB::Reflect(*m_serializeContext.get());
  3030. AZStd::unique_ptr<Clonable> objA(aznew ClonableMutlipleInheritanceOrderingA);
  3031. AZStd::unique_ptr<Clonable> objB(aznew ClonableMutlipleInheritanceOrderingB);
  3032. // sanity check that the pointer offset for the classes being used is different
  3033. const void* aAsBasePtr = AZ::SerializeTypeInfo<Clonable>::RttiCast(objA.get(), AZ::SerializeTypeInfo<Clonable>::GetRttiTypeId(objA.get()));
  3034. const void* bAsBasePtr = AZ::SerializeTypeInfo<Clonable>::RttiCast(objB.get(), AZ::SerializeTypeInfo<Clonable>::GetRttiTypeId(objB.get()));
  3035. AZStd::ptrdiff_t aOffset = (char*)objA.get() - (char*)aAsBasePtr;
  3036. AZStd::ptrdiff_t bOffset = (char*)objB.get() - (char*)bAsBasePtr;
  3037. EXPECT_NE(aOffset, 0);
  3038. EXPECT_EQ(bOffset, 0);
  3039. // Now clone the original objects, and store in the RTTI base type
  3040. AZStd::unique_ptr<Clonable> cloneObjA(m_serializeContext->CloneObject(objA.get()));
  3041. AZStd::unique_ptr<Clonable> cloneObjB(m_serializeContext->CloneObject(objB.get()));
  3042. // Check our pointer offsets are still different in the cloned objects
  3043. const void* aCloneAsBasePtr = AZ::SerializeTypeInfo<Clonable>::RttiCast(cloneObjA.get(), AZ::SerializeTypeInfo<Clonable>::GetRttiTypeId(cloneObjA.get()));
  3044. const void* bCloneAsBasePtr = AZ::SerializeTypeInfo<Clonable>::RttiCast(cloneObjB.get(), AZ::SerializeTypeInfo<Clonable>::GetRttiTypeId(cloneObjB.get()));
  3045. AZStd::ptrdiff_t aCloneOffset = (char*)cloneObjA.get() - (char*)aCloneAsBasePtr;
  3046. AZStd::ptrdiff_t bCloneOffset = (char*)cloneObjB.get() - (char*)bCloneAsBasePtr;
  3047. EXPECT_NE(aCloneOffset, 0);
  3048. EXPECT_EQ(bCloneOffset, 0);
  3049. // Check that offsets are equivalent between the clones and the original objects
  3050. EXPECT_EQ(aCloneOffset, aOffset);
  3051. EXPECT_EQ(bCloneOffset, bOffset);
  3052. m_serializeContext->EnableRemoveReflection();
  3053. ClonableMutlipleInheritanceOrderingB::Reflect(*m_serializeContext.get());
  3054. ClonableMutlipleInheritanceOrderingA::Reflect(*m_serializeContext.get());
  3055. Clonable::Reflect(*m_serializeContext.get());
  3056. m_serializeContext->DisableRemoveReflection();
  3057. }
  3058. // Prove that if a member of a vector of baseclass pointers is unreadable, the container
  3059. // removes the element instead of leaving a null. This is an arbitrary choice (to remove or leave
  3060. // the null) and this test exists just to prove that the chosen way functions as expected.
  3061. TEST_F(Serialization, Clone_UnreadableVectorElements_LeaveNoGaps_Errors)
  3062. {
  3063. using namespace ContainerElementDeprecationTestData;
  3064. // make sure that when a component is deprecated, it is removed during deserialization
  3065. // and does not leave a hole that is a nullptr.
  3066. ClassWithAVectorOfBaseClasses::Reflect(m_serializeContext.get());
  3067. ClassWithAVectorOfBaseClasses vectorContainer;
  3068. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass1());
  3069. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass2());
  3070. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass1());
  3071. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass2());
  3072. // (remove it, but without deprecating)
  3073. m_serializeContext->EnableRemoveReflection();
  3074. DerivedClass2::Reflect(m_serializeContext.get());
  3075. m_serializeContext->DisableRemoveReflection();
  3076. // clone it, we expect errors:
  3077. AZ_TEST_START_TRACE_SUPPRESSION;
  3078. ClassWithAVectorOfBaseClasses loadedContainer;
  3079. m_serializeContext->CloneObjectInplace(loadedContainer, &vectorContainer);
  3080. AZ_TEST_STOP_TRACE_SUPPRESSION(2); // 2 classes should have failed and generated warnings/errors
  3081. EXPECT_EQ(loadedContainer.m_vectorOfBaseClasses.size(), 2); // we still preserve the ones we CAN read.
  3082. for (auto baseclass : loadedContainer.m_vectorOfBaseClasses)
  3083. {
  3084. // we should only have baseclass1's in there.
  3085. EXPECT_EQ(baseclass->RTTI_GetType(), azrtti_typeid<DerivedClass1>());
  3086. }
  3087. }
  3088. // Prove that if you properly deprecate a member of a vector of baseclass pointers, the container
  3089. // removes the element instead of leaving a null and does not emit an error
  3090. TEST_F(Serialization, Clone_DeprecatedVectorElements_LeaveNoGaps_DoesNotError)
  3091. {
  3092. using namespace ContainerElementDeprecationTestData;
  3093. // make sure that when a component is deprecated, it is removed during deserialization
  3094. // and does not leave a hole that is a nullptr.
  3095. ClassWithAVectorOfBaseClasses::Reflect(m_serializeContext.get());
  3096. ClassWithAVectorOfBaseClasses vectorContainer;
  3097. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass1());
  3098. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass2());
  3099. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass1());
  3100. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass2());
  3101. // remove it and properly deprecate it
  3102. m_serializeContext->EnableRemoveReflection();
  3103. DerivedClass2::Reflect(m_serializeContext.get());
  3104. m_serializeContext->DisableRemoveReflection();
  3105. m_serializeContext->ClassDeprecate("Dummy UUID", azrtti_typeid<DerivedClass2>());
  3106. // clone it, we expect no errors:
  3107. ClassWithAVectorOfBaseClasses loadedContainer;
  3108. m_serializeContext->CloneObjectInplace(loadedContainer, &vectorContainer);
  3109. EXPECT_EQ(loadedContainer.m_vectorOfBaseClasses.size(), 2); // we still preserve the ones we CAN read.
  3110. for (auto baseclass : loadedContainer.m_vectorOfBaseClasses)
  3111. {
  3112. // we should only have baseclass1's in there.
  3113. EXPECT_EQ(baseclass->RTTI_GetType(), azrtti_typeid<DerivedClass1>());
  3114. }
  3115. }
  3116. // Prove that if you deprecate but upgrade a member of a vector of baseclass pointers, the container
  3117. // Clone actually errors. This behavior differs from serialize and datapatch because you're not
  3118. // expected to even have a deprecated class being cloned in the first place (it should have
  3119. // converted on deserialize or datapatch!)
  3120. TEST_F(Serialization, Clone_DeprecatedVectorElements_ConvertedClass_LeavesGaps_Errors)
  3121. {
  3122. using namespace ContainerElementDeprecationTestData;
  3123. // make sure that when a component is deprecated, it is removed during deserialization
  3124. // and does not leave a hole that is a nullptr.
  3125. ClassWithAVectorOfBaseClasses::Reflect(m_serializeContext.get());
  3126. ClassWithAVectorOfBaseClasses vectorContainer;
  3127. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass1());
  3128. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass2());
  3129. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass1());
  3130. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass2());
  3131. // remove it and properly deprecate it with a converter that will upgrade it.
  3132. m_serializeContext->EnableRemoveReflection();
  3133. DerivedClass2::Reflect(m_serializeContext.get());
  3134. m_serializeContext->DisableRemoveReflection();
  3135. m_serializeContext->ClassDeprecate("Dummy UUID", azrtti_typeid<DerivedClass2>(), ConvertDerivedClass2ToDerivedClass3);
  3136. // clone it, we expect no errors:
  3137. ClassWithAVectorOfBaseClasses loadedContainer;
  3138. AZ_TEST_START_TRACE_SUPPRESSION;
  3139. m_serializeContext->CloneObjectInplace(loadedContainer, &vectorContainer);
  3140. AZ_TEST_STOP_TRACE_SUPPRESSION(2); // one for each converter
  3141. ASSERT_EQ(loadedContainer.m_vectorOfBaseClasses.size(), 2); // we still preserve the ones we CAN read.
  3142. // this also proves it does not shuffle elements around.
  3143. EXPECT_EQ(loadedContainer.m_vectorOfBaseClasses[0]->RTTI_GetType(), azrtti_typeid<DerivedClass1>());
  3144. EXPECT_EQ(loadedContainer.m_vectorOfBaseClasses[1]->RTTI_GetType(), azrtti_typeid<DerivedClass1>());
  3145. }
  3146. struct TestContainerType
  3147. {
  3148. AZ_TYPE_INFO(TestContainerType, "{81F20E9F-3F35-4063-BE29-A22EAF10AF59}");
  3149. int32_t m_value{};
  3150. };
  3151. struct ContainerWrapper
  3152. {
  3153. AZ_TYPE_INFO(ContainerWrapper, "{F4EE9211-CABE-4D28-8356-2C2ADE6E5315}");
  3154. TestContainerType m_testContainer;
  3155. };
  3156. TEST_F(Serialization, Clone_Container_WhereReserveElement_ReturnsNullptr_DoesNotCrash)
  3157. {
  3158. struct EmptyDataContainer
  3159. : AZ::SerializeContext::IDataContainer
  3160. {
  3161. EmptyDataContainer()
  3162. {
  3163. // Create SerializeContext ClassElement for a int32_t type that is not a pointer
  3164. m_classElement.m_name = "Test";
  3165. m_classElement.m_nameCrc = AZ_CRC("Test");
  3166. m_classElement.m_typeId = azrtti_typeid<int32_t>();
  3167. m_classElement.m_dataSize = sizeof(int32_t);
  3168. m_classElement.m_offset = 0;
  3169. m_classElement.m_azRtti = {};
  3170. m_classElement.m_editData = {};
  3171. m_classElement.m_flags = 0;
  3172. }
  3173. const AZ::SerializeContext::ClassElement* GetElement(uint32_t) const override
  3174. {
  3175. return {};
  3176. }
  3177. bool GetElement(AZ::SerializeContext::ClassElement&, const AZ::SerializeContext::DataElement&) const override
  3178. {
  3179. return {};
  3180. }
  3181. void EnumElements(void* instance, const ElementCB& cb) override
  3182. {
  3183. auto dataContainer = reinterpret_cast<TestContainerType*>(instance);
  3184. cb(&dataContainer->m_value, m_classElement.m_typeId, m_classElement.m_genericClassInfo ? m_classElement.m_genericClassInfo->GetClassData() : nullptr, &m_classElement);
  3185. }
  3186. void EnumTypes(const ElementTypeCB& cb) override
  3187. {
  3188. cb(m_classElement.m_typeId, &m_classElement);
  3189. }
  3190. size_t Size(void*) const override
  3191. {
  3192. return {};
  3193. }
  3194. size_t Capacity(void*) const override
  3195. {
  3196. return {};
  3197. }
  3198. bool IsStableElements() const override
  3199. {
  3200. return {};
  3201. }
  3202. bool IsFixedSize() const override
  3203. {
  3204. return {};
  3205. }
  3206. bool IsFixedCapacity() const override
  3207. {
  3208. return {};
  3209. }
  3210. bool IsSmartPointer() const override
  3211. {
  3212. return {};
  3213. }
  3214. bool CanAccessElementsByIndex() const override
  3215. {
  3216. return {};
  3217. }
  3218. void* ReserveElement(void*, const AZ::SerializeContext::ClassElement*) override
  3219. {
  3220. return {};
  3221. }
  3222. void* GetElementByIndex(void*, const AZ::SerializeContext::ClassElement*, size_t) override
  3223. {
  3224. return {};
  3225. }
  3226. void StoreElement([[maybe_unused]] void* instance, [[maybe_unused]] void* element) override
  3227. {}
  3228. bool RemoveElement(void*, const void*, [[maybe_unused]] AZ::SerializeContext* serializeContext) override
  3229. {
  3230. return {};
  3231. }
  3232. size_t RemoveElements(void*, const void**, size_t, [[maybe_unused]] AZ::SerializeContext* serializeContext) override
  3233. {
  3234. return {};
  3235. }
  3236. void ClearElements(void*, AZ::SerializeContext*) override
  3237. {}
  3238. AZ::SerializeContext::ClassElement m_classElement;
  3239. };
  3240. m_serializeContext->Class<TestContainerType>()
  3241. ->DataContainer<EmptyDataContainer>();
  3242. m_serializeContext->Class<ContainerWrapper>()
  3243. ->Field("m_testContainer", &ContainerWrapper::m_testContainer);
  3244. ContainerWrapper expectObject{ {42} };
  3245. ContainerWrapper resultObject;
  3246. AZ_TEST_START_TRACE_SUPPRESSION;
  3247. m_serializeContext->CloneObjectInplace(resultObject, &expectObject);
  3248. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  3249. EXPECT_EQ(0, resultObject.m_testContainer.m_value);
  3250. m_serializeContext->EnableRemoveReflection();
  3251. m_serializeContext->Class<TestContainerType>();
  3252. m_serializeContext->Class<ContainerWrapper>();
  3253. m_serializeContext->DisableRemoveReflection();
  3254. }
  3255. /*
  3256. * Error Testing
  3257. */
  3258. namespace Error
  3259. {
  3260. struct UnregisteredClass
  3261. {
  3262. AZ_TYPE_INFO(UnregisteredClass, "{6558CEBC-D764-4E50-BAA0-025BF55FAD15}")
  3263. };
  3264. struct UnregisteredRttiClass
  3265. {
  3266. AZ_RTTI(UnregisteredRttiClass, "{F948E16B-975D-4F23-911E-2AA5758D8B21}");
  3267. virtual ~UnregisteredRttiClass() {}
  3268. };
  3269. struct ChildOfUnregisteredClass
  3270. : public UnregisteredClass
  3271. {
  3272. AZ_TYPE_INFO(ChildOfUnregisteredClass, "{C72CB2C9-7E9A-41EB-8219-5D13B6445AFC}")
  3273. ChildOfUnregisteredClass() {}
  3274. ChildOfUnregisteredClass(SerializeContext& sc)
  3275. {
  3276. sc.Class<ChildOfUnregisteredClass, UnregisteredClass>();
  3277. }
  3278. };
  3279. struct ChildOfUnregisteredRttiClass
  3280. : public UnregisteredRttiClass
  3281. {
  3282. AZ_RTTI(ChildOfUnregisteredRttiClass, "{E58F6984-4C0A-4D1B-B034-FDEF711AB711}", UnregisteredRttiClass);
  3283. ChildOfUnregisteredRttiClass() {}
  3284. ChildOfUnregisteredRttiClass(SerializeContext& sc)
  3285. {
  3286. sc.Class<ChildOfUnregisteredRttiClass, UnregisteredRttiClass>();
  3287. }
  3288. };
  3289. struct UnserializableMembers
  3290. {
  3291. AZ_TYPE_INFO(UnserializableMembers, "{36F0C52A-5CAC-4060-982C-FC9A86D1393A}");
  3292. UnserializableMembers() {}
  3293. UnserializableMembers(SerializeContext& sc)
  3294. : m_childOfUnregisteredRttiBase(sc)
  3295. , m_childOfUnregisteredBase(&m_childOfUnregisteredRttiBase)
  3296. , m_basePtrToGenericChild(&m_unserializableGeneric)
  3297. {
  3298. m_vectorUnregisteredClass.emplace_back();
  3299. m_vectorUnregisteredRttiClass.emplace_back();
  3300. m_vectorUnregisteredRttiBase.push_back(&m_unregisteredRttiMember);
  3301. m_vectorGenericChildPtr.push_back(&m_unserializableGeneric);
  3302. sc.Class<UnserializableMembers>()->
  3303. Field("unregisteredMember", &UnserializableMembers::m_unregisteredMember)->
  3304. Field("unregisteredRttiMember", &UnserializableMembers::m_unregisteredRttiMember)->
  3305. Field("childOfUnregisteredBase", &UnserializableMembers::m_childOfUnregisteredBase)->
  3306. Field("basePtrToGenericChild", &UnserializableMembers::m_basePtrToGenericChild)->
  3307. Field("vectorUnregisteredClass", &UnserializableMembers::m_vectorUnregisteredClass)->
  3308. Field("vectorUnregisteredRttiClass", &UnserializableMembers::m_vectorUnregisteredRttiClass)->
  3309. Field("vectorUnregisteredRttiBase", &UnserializableMembers::m_vectorUnregisteredRttiBase)->
  3310. Field("vectorGenericChildPtr", &UnserializableMembers::m_vectorGenericChildPtr);
  3311. }
  3312. ChildOfUnregisteredRttiClass m_childOfUnregisteredRttiBase;
  3313. GenericChild m_unserializableGeneric;
  3314. UnregisteredClass m_unregisteredMember;
  3315. UnregisteredRttiClass m_unregisteredRttiMember;
  3316. UnregisteredRttiClass* m_childOfUnregisteredBase;
  3317. GenericClass* m_basePtrToGenericChild;
  3318. AZStd::vector<UnregisteredClass> m_vectorUnregisteredClass;
  3319. AZStd::vector<UnregisteredRttiClass> m_vectorUnregisteredRttiClass;
  3320. AZStd::vector<UnregisteredRttiClass*> m_vectorUnregisteredRttiBase;
  3321. AZStd::vector<GenericClass*> m_vectorGenericChildPtr;
  3322. };
  3323. }
  3324. // Tests that reflection of classes with no base types and those with base types will reflect and unreflect
  3325. // as expected using the templated function, Class()
  3326. TEST_F(Serialization, ClassReflectAndUnreflect)
  3327. {
  3328. using namespace SerializeTestClasses;
  3329. m_serializeContext->Class<SerializeTestClasses::MyClassMix>();
  3330. m_serializeContext->Class<BaseRtti>();
  3331. {
  3332. AZStd::vector<AZ::Uuid> foundUuids = m_serializeContext->FindClassId(AZ::Crc32(AzTypeInfo<BaseRtti>::Name()));
  3333. ASSERT_FALSE(foundUuids.empty());
  3334. EXPECT_EQ(foundUuids.size(), 1);
  3335. EXPECT_EQ(foundUuids[0], AZ::Uuid::CreateString("{2581047D-26EC-4969-8354-BA0A4510C51A}"));
  3336. EXPECT_NE(m_serializeContext->FindClassData(azrtti_typeid<BaseRtti>()), nullptr);
  3337. AZStd::any testAnyCreate = m_serializeContext->CreateAny(azrtti_typeid<BaseRtti>());
  3338. EXPECT_FALSE(testAnyCreate.empty());
  3339. EXPECT_TRUE(testAnyCreate.is<BaseRtti>());
  3340. }
  3341. {
  3342. AZStd::vector<AZ::Uuid> foundUuids = m_serializeContext->FindClassId(AZ::Crc32(AzTypeInfo<SerializeTestClasses::MyClassMix>::Name()));
  3343. ASSERT_FALSE(foundUuids.empty());
  3344. EXPECT_EQ(foundUuids.size(), 1);
  3345. EXPECT_EQ(foundUuids[0], AZ::Uuid::CreateString("{A15003C6-797A-41BB-9D21-716DF0678D02}"));
  3346. EXPECT_NE(m_serializeContext->FindClassData(azrtti_typeid<SerializeTestClasses::MyClassMix>()), nullptr);
  3347. AZStd::any testAnyCreate = m_serializeContext->CreateAny(azrtti_typeid<SerializeTestClasses::MyClassMix>());
  3348. EXPECT_FALSE(testAnyCreate.empty());
  3349. EXPECT_TRUE(testAnyCreate.is<SerializeTestClasses::MyClassMix>());
  3350. }
  3351. m_serializeContext->EnableRemoveReflection();
  3352. m_serializeContext->Class<SerializeTestClasses::MyClassMix>();
  3353. m_serializeContext->Class<BaseRtti>();
  3354. m_serializeContext->DisableRemoveReflection();
  3355. {
  3356. AZStd::vector<AZ::Uuid> foundUuids = m_serializeContext->FindClassId(AZ::Crc32(AzTypeInfo<BaseRtti>::Name()));
  3357. EXPECT_TRUE(foundUuids.empty());
  3358. EXPECT_EQ(m_serializeContext->FindClassData(azrtti_typeid<BaseRtti>()), nullptr);
  3359. AZStd::any testAnyCreate = m_serializeContext->CreateAny(azrtti_typeid<BaseRtti>());
  3360. EXPECT_TRUE(testAnyCreate.empty());
  3361. EXPECT_FALSE(testAnyCreate.is<BaseRtti>());
  3362. }
  3363. {
  3364. AZStd::vector<AZ::Uuid> foundUuids = m_serializeContext->FindClassId(AZ::Crc32(AzTypeInfo<SerializeTestClasses::MyClassMix>::Name()));
  3365. EXPECT_TRUE(foundUuids.empty());
  3366. EXPECT_EQ(m_serializeContext->FindClassData(azrtti_typeid<SerializeTestClasses::MyClassMix>()), nullptr);
  3367. AZStd::any testAnyCreate = m_serializeContext->CreateAny(azrtti_typeid<SerializeTestClasses::MyClassMix>());
  3368. EXPECT_TRUE(testAnyCreate.empty());
  3369. EXPECT_FALSE(testAnyCreate.is<SerializeTestClasses::MyClassMix>());
  3370. }
  3371. }
  3372. TEST_F(Serialization, ErrorTest)
  3373. {
  3374. using namespace Error;
  3375. class ErrorTest
  3376. {
  3377. public:
  3378. void SaveObjects(ObjectStream* writer, SerializeContext* sc)
  3379. {
  3380. static int i = 0;
  3381. bool success;
  3382. // test saving root unregistered class
  3383. if (i == 0)
  3384. {
  3385. UnregisteredClass unregisteredClass;
  3386. AZ_TEST_START_TRACE_SUPPRESSION;
  3387. success = writer->WriteClass(&unregisteredClass);
  3388. EXPECT_TRUE(!success);
  3389. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  3390. }
  3391. // test saving root unregistered Rtti class
  3392. else if (i == 1)
  3393. {
  3394. UnregisteredRttiClass unregisteredRttiClass;
  3395. AZ_TEST_START_TRACE_SUPPRESSION;
  3396. success = writer->WriteClass(&unregisteredRttiClass);
  3397. EXPECT_TRUE(!success);
  3398. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  3399. }
  3400. // test saving root generic class
  3401. else if (i == 2)
  3402. {
  3403. GenericClass genericClass;
  3404. AZ_TEST_START_TRACE_SUPPRESSION;
  3405. success = writer->WriteClass(&genericClass);
  3406. EXPECT_TRUE(!success);
  3407. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  3408. }
  3409. // test saving as pointer to unregistered base class with no rtti
  3410. else if (i == 3)
  3411. {
  3412. ChildOfUnregisteredClass childOfUnregisteredClass(*sc);
  3413. AZ_TEST_START_TRACE_SUPPRESSION;
  3414. success = writer->WriteClass(static_cast<UnregisteredClass*>(&childOfUnregisteredClass));
  3415. EXPECT_TRUE(!success);
  3416. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  3417. }
  3418. // test saving unserializable members
  3419. else if (i == 4)
  3420. {
  3421. UnserializableMembers badMembers(*sc);
  3422. AZ_TEST_START_TRACE_SUPPRESSION;
  3423. success = writer->WriteClass(&badMembers);
  3424. EXPECT_TRUE(!success);
  3425. AZ_TEST_STOP_TRACE_SUPPRESSION(8); // 1 failure for each member
  3426. }
  3427. i++;
  3428. }
  3429. void run()
  3430. {
  3431. AZStd::vector<char> buffer;
  3432. IO::ByteContainerStream<AZStd::vector<char> > stream(&buffer);
  3433. // test saving root unregistered class
  3434. {
  3435. SerializeContext sc;
  3436. ObjectStream* objStream = ObjectStream::Create(&stream, sc, ObjectStream::ST_XML);
  3437. SaveObjects(objStream, &sc);
  3438. objStream->Finalize();
  3439. }
  3440. // test saving root unregistered Rtti class
  3441. {
  3442. SerializeContext sc;
  3443. ObjectStream* objStream = ObjectStream::Create(&stream, sc, ObjectStream::ST_XML);
  3444. SaveObjects(objStream, &sc);
  3445. objStream->Finalize();
  3446. }
  3447. // test saving root generic class
  3448. {
  3449. SerializeContext sc;
  3450. ObjectStream* objStream = ObjectStream::Create(&stream, sc, ObjectStream::ST_XML);
  3451. SaveObjects(objStream, &sc);
  3452. objStream->Finalize();
  3453. }
  3454. // test saving as pointer to unregistered base class with no rtti
  3455. {
  3456. SerializeContext sc;
  3457. ObjectStream* objStream = ObjectStream::Create(&stream, sc, ObjectStream::ST_XML);
  3458. SaveObjects(objStream, &sc);
  3459. objStream->Finalize();
  3460. }
  3461. // test saving unserializable members
  3462. // errors covered:
  3463. // - unregistered type with no rtti
  3464. // - unregistered type with rtti
  3465. // - pointer to unregistered base with rtti
  3466. // - base pointer pointing to a generic child
  3467. // - vector of unregistered types
  3468. // - vector of unregistered types with rtti
  3469. // - vector of pointers to unregistered base with rtti
  3470. // - vector of base pointers pointing to generic child
  3471. {
  3472. SerializeContext sc;
  3473. ObjectStream* objStream = ObjectStream::Create(&stream, sc, ObjectStream::ST_XML);
  3474. SaveObjects(objStream, &sc);
  3475. objStream->Finalize();
  3476. }
  3477. }
  3478. };
  3479. ErrorTest test;
  3480. test.run();
  3481. }
  3482. namespace EditTest
  3483. {
  3484. struct MyEditStruct
  3485. {
  3486. AZ_TYPE_INFO(MyEditStruct, "{89CCD760-A556-4EDE-98C0-33FD9DD556B9}")
  3487. MyEditStruct()
  3488. : m_data(11)
  3489. , m_specialData(3) {}
  3490. int Foo(int m) { return 5 * m; }
  3491. bool IsShowSpecialData() const { return true; }
  3492. int GetDataOption(int option) { return option * 2; }
  3493. int m_data;
  3494. int m_specialData;
  3495. };
  3496. int MyEditGlobalFunc(int m)
  3497. {
  3498. return 4 * m;
  3499. }
  3500. class MyEditStruct2
  3501. {
  3502. public:
  3503. AZ_TYPE_INFO(MyEditStruct2, "{FFD27958-9856-4CE2-AE13-18878DE5ECE0}");
  3504. MyEditStruct m_myEditStruct;
  3505. };
  3506. class MyEditStruct3
  3507. {
  3508. public:
  3509. enum EditEnum
  3510. {
  3511. ENUM_Test1 = 1,
  3512. ENUM_Test2 = 2,
  3513. ENUM_Test3 = -1,
  3514. ENUM_Test4 = INT_MAX,
  3515. };
  3516. enum class EditEnumClass : AZ::u8
  3517. {
  3518. EEC_1,
  3519. EEC_2,
  3520. EEC_255 = 255,
  3521. };
  3522. public:
  3523. AZ_TYPE_INFO(MyEditStruct3, "{11F859C7-7A15-49C8-8A38-783A1EFC0E06}");
  3524. EditEnum m_enum;
  3525. EditEnum m_enum2;
  3526. EditEnumClass m_enumClass;
  3527. };
  3528. }
  3529. } // namespace UnitTest
  3530. namespace AZ
  3531. {
  3532. AZ_TYPE_INFO_SPECIALIZE(UnitTest::EditTest::MyEditStruct3::EditEnum, "{4AF433C2-055E-4E34-921A-A7D16AB548CA}");
  3533. AZ_TYPE_INFO_SPECIALIZE(UnitTest::EditTest::MyEditStruct3::EditEnumClass, "{4FEC2F0B-A599-4FCD-836B-89E066791793}");
  3534. }
  3535. namespace UnitTest
  3536. {
  3537. TEST_F(Serialization, EditContextTest)
  3538. {
  3539. using namespace EditTest;
  3540. class EditContextTest
  3541. {
  3542. public:
  3543. bool BeginSerializationElement(SerializeContext* sc, void* instance, const SerializeContext::ClassData* classData, const SerializeContext::ClassElement* classElement)
  3544. {
  3545. (void)instance;
  3546. (void)classData;
  3547. (void)classElement;
  3548. if (classElement)
  3549. {
  3550. // if we are a pointer, then we may be pointing to a derived type.
  3551. if (classElement->m_flags & SerializeContext::ClassElement::FLG_POINTER)
  3552. {
  3553. // if dataAddress is a pointer in this case, cast it's value to a void* (or const void*) and dereference to get to the actual class.
  3554. instance = *(void**)(instance);
  3555. if (instance && classElement->m_azRtti)
  3556. {
  3557. AZ::Uuid actualClassId = classElement->m_azRtti->GetActualUuid(instance);
  3558. if (actualClassId != classElement->m_typeId)
  3559. {
  3560. // we are pointing to derived type, adjust class data, uuid and pointer.
  3561. classData = sc->FindClassData(actualClassId);
  3562. if (classData)
  3563. {
  3564. instance = classElement->m_azRtti->Cast(instance, classData->m_azRtti->GetTypeId());
  3565. }
  3566. }
  3567. }
  3568. }
  3569. }
  3570. if (strcmp(classData->m_name, "MyEditStruct") == 0)
  3571. {
  3572. EXPECT_TRUE(classData->m_editData != nullptr);
  3573. EXPECT_EQ( 0, strcmp(classData->m_editData->m_name, "MyEditStruct") );
  3574. EXPECT_EQ( 0, strcmp(classData->m_editData->m_description, "My edit struct class used for ...") );
  3575. EXPECT_EQ( 2, classData->m_editData->m_elements.size() );
  3576. EXPECT_EQ( 0, strcmp(classData->m_editData->m_elements.front().m_description, "Special data group") );
  3577. EXPECT_EQ( 1, classData->m_editData->m_elements.front().m_attributes.size() );
  3578. EXPECT_TRUE(classData->m_editData->m_elements.front().m_attributes[0].first == AZ_CRC("Callback", 0x79f97426) );
  3579. }
  3580. else if (classElement && classElement->m_editData && strcmp(classElement->m_editData->m_description, "Type") == 0)
  3581. {
  3582. EXPECT_EQ( 2, classElement->m_editData->m_attributes.size() );
  3583. // Number of options attribute
  3584. EXPECT_EQ(classElement->m_editData->m_attributes[0].first, AZ_CRC("NumOptions", 0x90274abc));
  3585. Edit::AttributeData<int>* intData = azrtti_cast<Edit::AttributeData<int>*>(classElement->m_editData->m_attributes[0].second);
  3586. EXPECT_TRUE(intData != nullptr);
  3587. EXPECT_EQ( 3, intData->Get(instance) );
  3588. // Get options attribute
  3589. EXPECT_EQ( classElement->m_editData->m_attributes[1].first, AZ_CRC("Options", 0xd035fa87));
  3590. Edit::AttributeFunction<int(int)>* funcData = azrtti_cast<Edit::AttributeFunction<int(int)>*>(classElement->m_editData->m_attributes[1].second);
  3591. EXPECT_TRUE(funcData != nullptr);
  3592. EXPECT_EQ( 20, funcData->Invoke(instance, 10) );
  3593. }
  3594. return true;
  3595. }
  3596. bool EndSerializationElement()
  3597. {
  3598. return true;
  3599. }
  3600. void run()
  3601. {
  3602. SerializeContext serializeContext;
  3603. // We must expose the class for serialization first.
  3604. serializeContext.Class<MyEditStruct>()->
  3605. Field("data", &MyEditStruct::m_data);
  3606. serializeContext.Class<MyEditStruct2>()->
  3607. Field("m_myEditStruct", &MyEditStruct2::m_myEditStruct);
  3608. serializeContext.Class<MyEditStruct3>()->
  3609. Field("m_enum", &MyEditStruct3::m_enum)->
  3610. Field("m_enum2", &MyEditStruct3::m_enum2)->
  3611. Field("m_enumClass", &MyEditStruct3::m_enumClass);
  3612. // create edit context
  3613. serializeContext.CreateEditContext();
  3614. EditContext* editContext = serializeContext.GetEditContext();
  3615. // reflect the class for editing
  3616. editContext->Class<MyEditStruct>("MyEditStruct", "My edit struct class used for ...")->
  3617. ClassElement(AZ::Edit::ClassElements::Group, "Special data group")->
  3618. Attribute("Callback", &MyEditStruct::IsShowSpecialData)->
  3619. DataElement("ComboSelector", &MyEditStruct::m_data, "Name", "Type")->
  3620. Attribute("NumOptions", 3)->
  3621. Attribute("Options", &MyEditStruct::GetDataOption);
  3622. // reflect class by using the element edit reflection as name/descriptor
  3623. editContext->Class<MyEditStruct2>("MyEditStruct2", "My edit struct class 2 with redirected data element...")->
  3624. DataElement("ComboSelector", &MyEditStruct2::m_myEditStruct)->
  3625. Attribute("NumOptions", 3);
  3626. // enumerate elements and verify the class reflection..
  3627. MyEditStruct myObj;
  3628. serializeContext.EnumerateObject(&myObj,
  3629. AZStd::bind(&EditContextTest::BeginSerializationElement, this, &serializeContext, AZStd::placeholders::_1, AZStd::placeholders::_2, AZStd::placeholders::_3),
  3630. AZStd::bind(&EditContextTest::EndSerializationElement, this),
  3631. SerializeContext::ENUM_ACCESS_FOR_READ);
  3632. editContext->Enum<MyEditStruct3::EditEnum>("EditEnum", "The enum for testing the Enum<>() call")->
  3633. Value("Test1", MyEditStruct3::EditEnum::ENUM_Test1)->
  3634. Value("Test2", MyEditStruct3::EditEnum::ENUM_Test2)->
  3635. Value("Test3", MyEditStruct3::EditEnum::ENUM_Test3)->
  3636. Value("Test4", MyEditStruct3::EditEnum::ENUM_Test4);
  3637. editContext->Enum<MyEditStruct3::EditEnumClass>("EditEnumClass", "The enum class for testing the Enum<>() call")->
  3638. Value("One", MyEditStruct3::EditEnumClass::EEC_1)->
  3639. Value("Two", MyEditStruct3::EditEnumClass::EEC_2)->
  3640. Value("TwoFiftyFive", MyEditStruct3::EditEnumClass::EEC_255);
  3641. AZ_TEST_START_TRACE_SUPPRESSION;
  3642. editContext->Class<MyEditStruct3>("MyEditStruct3", "Used to test enum global reflection")->
  3643. DataElement("Enum", &MyEditStruct3::m_enum)-> // safe
  3644. DataElement("Enum2", &MyEditStruct3::m_enum2)-> // safe
  3645. EnumAttribute(MyEditStruct3::EditEnum::ENUM_Test1, "THIS SHOULD CAUSE AN ERROR")->
  3646. Attribute(AZ::Edit::Attributes::EnumValues, AZStd::vector<AZ::Edit::EnumConstant<MyEditStruct3::EditEnum>> {
  3647. AZ::Edit::EnumConstant<MyEditStruct3::EditEnum>(MyEditStruct3::EditEnum::ENUM_Test1, "EnumTest1 - ERROR"),
  3648. AZ::Edit::EnumConstant<MyEditStruct3::EditEnum>(MyEditStruct3::EditEnum::ENUM_Test2, "EnumTest2 - ERROR"),
  3649. AZ::Edit::EnumConstant<MyEditStruct3::EditEnum>(MyEditStruct3::EditEnum::ENUM_Test3, "EnumTest3 - ERROR"),
  3650. AZ::Edit::EnumConstant<MyEditStruct3::EditEnum>(MyEditStruct3::EditEnum::ENUM_Test4, "EnumTest4 - ERROR"),
  3651. })->
  3652. ElementAttribute(AZ::Edit::InternalAttributes::EnumValue, AZStd::make_pair(MyEditStruct3::EditEnum::ENUM_Test1, "THIS SHOULD ALSO CAUSE AN ERROR"));
  3653. AZ_TEST_STOP_TRACE_SUPPRESSION(0);
  3654. }
  3655. };
  3656. EditContextTest test;
  3657. test.run();
  3658. }
  3659. /**
  3660. * Test cases when (usually with DLLs) we have to unload parts of the reflected context
  3661. */
  3662. TEST_F(Serialization, UnregisterTest)
  3663. {
  3664. using namespace EditTest;
  3665. auto reflectClasses = [](SerializeContext* context)
  3666. {
  3667. context->Class<MyEditStruct>()->
  3668. Field("data", &MyEditStruct::m_data);
  3669. };
  3670. SerializeContext serializeContext;
  3671. // Register class
  3672. reflectClasses(&serializeContext);
  3673. // enumerate elements and verify the class reflection..
  3674. MyEditStruct myObj;
  3675. EXPECT_TRUE(serializeContext.FindClassData(AzTypeInfo<MyEditStruct>::Uuid()) != nullptr);
  3676. EXPECT_EQ( 0, strcmp(serializeContext.FindClassData(AzTypeInfo<MyEditStruct>::Uuid())->m_name, "MyEditStruct") );
  3677. // remove the class from the context
  3678. serializeContext.EnableRemoveReflection();
  3679. reflectClasses(&serializeContext);
  3680. serializeContext.DisableRemoveReflection();
  3681. EXPECT_EQ( nullptr, serializeContext.FindClassData(AzTypeInfo<MyEditStruct>::Uuid()) );
  3682. // Register class again
  3683. reflectClasses(&serializeContext);
  3684. EXPECT_EQ( nullptr, serializeContext.FindClassData(AzTypeInfo<MyEditStruct>::Uuid())->m_editData ); // no edit data yet
  3685. // create edit context
  3686. serializeContext.CreateEditContext();
  3687. EditContext* editContext = serializeContext.GetEditContext();
  3688. // reflect the class for editing
  3689. editContext->Class<MyEditStruct>("MyEditStruct", "My edit struct class used for ...")->
  3690. ClassElement(AZ::Edit::ClassElements::Group, "Special data group")->
  3691. Attribute("Callback", &MyEditStruct::IsShowSpecialData)->
  3692. DataElement("ComboSelector", &MyEditStruct::m_data, "Name", "Type")->
  3693. Attribute("NumOptions", 3)->
  3694. Attribute("Options", &MyEditStruct::GetDataOption);
  3695. editContext->Enum<MyEditStruct3::EditEnumClass>("Load Type", "Automatic or Manual loading and unloading")
  3696. ->Value("EEC_1", MyEditStruct3::EditEnumClass::EEC_1)
  3697. ->Value("EEC_2", MyEditStruct3::EditEnumClass::EEC_2)
  3698. ->Value("EEC_255", MyEditStruct3::EditEnumClass::EEC_255);
  3699. EXPECT_TRUE(serializeContext.FindClassData(AzTypeInfo<MyEditStruct>::Uuid())->m_editData != nullptr);
  3700. EXPECT_EQ( 0, strcmp(serializeContext.FindClassData(AzTypeInfo<MyEditStruct>::Uuid())->m_editData->m_name, "MyEditStruct") );
  3701. // remove the class from the context
  3702. serializeContext.EnableRemoveReflection();
  3703. reflectClasses(&serializeContext);
  3704. serializeContext.DisableRemoveReflection();
  3705. EXPECT_EQ( nullptr, serializeContext.FindClassData(AzTypeInfo<MyEditStruct>::Uuid()) );
  3706. }
  3707. namespace LargeData
  3708. {
  3709. class InnerPayload
  3710. {
  3711. public:
  3712. AZ_CLASS_ALLOCATOR(InnerPayload, AZ::SystemAllocator);
  3713. AZ_RTTI(InnerPayload, "{3423157C-C6C5-4914-BB5C-B656439B8D3D}");
  3714. AZStd::string m_textData;
  3715. InnerPayload()
  3716. {
  3717. m_textData = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sed pellentesque nibh. Mauris ac ipsum ante. Mauris dignissim vehicula dui, et mollis mauris tincidunt non. Aliquam sodales diam ante, in vestibulum nibh ultricies et. Pellentesque accumsan porta vulputate. Donec vel fringilla sem. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nam eu erat eu est mollis condimentum ut eget metus."
  3718. "Sed nec felis enim.Ut auctor arcu nec tristique volutpat.Nulla viverra vulputate nibh et fringilla.Curabitur sagittis eu libero ullamcorper porta.Ut ac nisi vitae massa luctus tristique.Donec scelerisque, odio at pharetra consectetur, nunc urna porta ligula, tincidunt auctor orci purus non nisi.Nulla at risus at lacus vestibulum varius vitae ac tellus.Etiam ut sem commodo justo tempor congue vel id odio.Duis erat sem, condimentum a neque id, bibendum consectetur ligula.In eget massa lectus.Interdum et malesuada fames ac ante ipsum primis in faucibus.Ut ornare lectus at sem condimentum gravida vel ut est."
  3719. "Curabitur nisl metus, euismod in enim eu, pulvinar ullamcorper lorem.Morbi et adipiscing nisi.Aliquam id dapibus sapien.Aliquam facilisis, lacus porta interdum mattis, erat metus tempus ligula, nec cursus augue tellus ut urna.Sed sagittis arcu vel magna consequat, eget eleifend quam tincidunt.Maecenas non ornare nisi, placerat ornare orci.Proin auctor in nunc eu ultrices.Vivamus interdum imperdiet sapien nec cursus."
  3720. "Etiam et iaculis tortor.Nam lacus risus, rutrum a mollis quis, accumsan quis risus.Mauris ac fringilla lectus.Cras posuere massa ultricies libero fermentum, in convallis metus porttitor.Duis hendrerit gravida neque at ultricies.Vestibulum semper congue gravida.Etiam vel mi quis risus ornare convallis nec et elit.Praesent a mollis erat, in eleifend libero.Fusce porttitor malesuada velit, nec pharetra justo rutrum sit amet.Ut vel egestas lacus, sit amet posuere nunc."
  3721. "Maecenas in eleifend risus.Integer volutpat sodales massa vitae consequat.Cras urna turpis, laoreet sed ante sit amet, dictum commodo sem.Vivamus porta, neque vel blandit dictum, enim metus molestie nisl, a consectetur libero odio eu magna.Maecenas nisi nibh, dignissim et nisi eget, adipiscing auctor ligula.Sed in nisl libero.Maecenas aliquam urna orci, ac ultrices massa sollicitudin vitae.Donec ullamcorper suscipit viverra.Praesent dolor ipsum, tincidunt eu quam sit amet, aliquam cursus orci.Praesent elementum est sit amet lectus imperdiet interdum.Pellentesque et sem et nulla tempus cursus.Sed enim dolor, viverra eu mauris id, ornare congue urna."
  3722. "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sed pellentesque nibh. Mauris ac ipsum ante. Mauris dignissim vehicula dui, et mollis mauris tincidunt non. Aliquam sodales diam ante, in vestibulum nibh ultricies et. Pellentesque accumsan porta vulputate. Donec vel fringilla sem. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nam eu erat eu est mollis condimentum ut eget metus."
  3723. "Sed nec felis enim.Ut auctor arcu nec tristique volutpat.Nulla viverra vulputate nibh et fringilla.Curabitur sagittis eu libero ullamcorper porta.Ut ac nisi vitae massa luctus tristique.Donec scelerisque, odio at pharetra consectetur, nunc urna porta ligula, tincidunt auctor orci purus non nisi.Nulla at risus at lacus vestibulum varius vitae ac tellus.Etiam ut sem commodo justo tempor congue vel id odio.Duis erat sem, condimentum a neque id, bibendum consectetur ligula.In eget massa lectus.Interdum et malesuada fames ac ante ipsum primis in faucibus.Ut ornare lectus at sem condimentum gravida vel ut est."
  3724. "Curabitur nisl metus, euismod in enim eu, pulvinar ullamcorper lorem.Morbi et adipiscing nisi.Aliquam id dapibus sapien.Aliquam facilisis, lacus porta interdum mattis, erat metus tempus ligula, nec cursus augue tellus ut urna.Sed sagittis arcu vel magna consequat, eget eleifend quam tincidunt.Maecenas non ornare nisi, placerat ornare orci.Proin auctor in nunc eu ultrices.Vivamus interdum imperdiet sapien nec cursus."
  3725. "Etiam et iaculis tortor.Nam lacus risus, rutrum a mollis quis, accumsan quis risus.Mauris ac fringilla lectus.Cras posuere massa ultricies libero fermentum, in convallis metus porttitor.Duis hendrerit gravida neque at ultricies.Vestibulum semper congue gravida.Etiam vel mi quis risus ornare convallis nec et elit.Praesent a mollis erat, in eleifend libero.Fusce porttitor malesuada velit, nec pharetra justo rutrum sit amet.Ut vel egestas lacus, sit amet posuere nunc."
  3726. "Maecenas in eleifend risus.Integer volutpat sodales massa vitae consequat.Cras urna turpis, laoreet sed ante sit amet, dictum commodo sem.Vivamus porta, neque vel blandit dictum, enim metus molestie nisl, a consectetur libero odio eu magna.Maecenas nisi nibh, dignissim et nisi eget, adipiscing auctor ligula.Sed in nisl libero.Maecenas aliquam urna orci, ac ultrices massa sollicitudin vitae.Donec ullamcorper suscipit viverra.Praesent dolor ipsum, tincidunt eu quam sit amet, aliquam cursus orci.Praesent elementum est sit amet lectus imperdiet interdum.Pellentesque et sem et nulla tempus cursus.Sed enim dolor, viverra eu mauris id, ornare congue urna."
  3727. ;
  3728. }
  3729. virtual ~InnerPayload()
  3730. {}
  3731. static void Reflect(AZ::SerializeContext& sc)
  3732. {
  3733. sc.Class<InnerPayload>()->
  3734. Version(5, &InnerPayload::ConvertOldVersions)->
  3735. Field("m_textData", &InnerPayload::m_textData)
  3736. ;
  3737. }
  3738. static bool ConvertOldVersions(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
  3739. {
  3740. (void)context;
  3741. (void)classElement;
  3742. return false;
  3743. }
  3744. };
  3745. class Payload
  3746. {
  3747. public:
  3748. AZ_CLASS_ALLOCATOR(Payload, AZ::SystemAllocator);
  3749. AZ_RTTI(Payload, "{7A14FC65-44FB-4956-B5BC-4CFCBF36E1AE}");
  3750. AZStd::string m_textData;
  3751. AZStd::string m_newTextData;
  3752. InnerPayload m_payload;
  3753. SerializeContext m_context;
  3754. Payload()
  3755. {
  3756. m_textData = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sed pellentesque nibh. Mauris ac ipsum ante. Mauris dignissim vehicula dui, et mollis mauris tincidunt non. Aliquam sodales diam ante, in vestibulum nibh ultricies et. Pellentesque accumsan porta vulputate. Donec vel fringilla sem. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nam eu erat eu est mollis condimentum ut eget metus."
  3757. "Sed nec felis enim.Ut auctor arcu nec tristique volutpat.Nulla viverra vulputate nibh et fringilla.Curabitur sagittis eu libero ullamcorper porta.Ut ac nisi vitae massa luctus tristique.Donec scelerisque, odio at pharetra consectetur, nunc urna porta ligula, tincidunt auctor orci purus non nisi.Nulla at risus at lacus vestibulum varius vitae ac tellus.Etiam ut sem commodo justo tempor congue vel id odio.Duis erat sem, condimentum a neque id, bibendum consectetur ligula.In eget massa lectus.Interdum et malesuada fames ac ante ipsum primis in faucibus.Ut ornare lectus at sem condimentum gravida vel ut est."
  3758. "Curabitur nisl metus, euismod in enim eu, pulvinar ullamcorper lorem.Morbi et adipiscing nisi.Aliquam id dapibus sapien.Aliquam facilisis, lacus porta interdum mattis, erat metus tempus ligula, nec cursus augue tellus ut urna.Sed sagittis arcu vel magna consequat, eget eleifend quam tincidunt.Maecenas non ornare nisi, placerat ornare orci.Proin auctor in nunc eu ultrices.Vivamus interdum imperdiet sapien nec cursus."
  3759. "Etiam et iaculis tortor.Nam lacus risus, rutrum a mollis quis, accumsan quis risus.Mauris ac fringilla lectus.Cras posuere massa ultricies libero fermentum, in convallis metus porttitor.Duis hendrerit gravida neque at ultricies.Vestibulum semper congue gravida.Etiam vel mi quis risus ornare convallis nec et elit.Praesent a mollis erat, in eleifend libero.Fusce porttitor malesuada velit, nec pharetra justo rutrum sit amet.Ut vel egestas lacus, sit amet posuere nunc."
  3760. "Maecenas in eleifend risus.Integer volutpat sodales massa vitae consequat.Cras urna turpis, laoreet sed ante sit amet, dictum commodo sem.Vivamus porta, neque vel blandit dictum, enim metus molestie nisl, a consectetur libero odio eu magna.Maecenas nisi nibh, dignissim et nisi eget, adipiscing auctor ligula.Sed in nisl libero.Maecenas aliquam urna orci, ac ultrices massa sollicitudin vitae.Donec ullamcorper suscipit viverra.Praesent dolor ipsum, tincidunt eu quam sit amet, aliquam cursus orci.Praesent elementum est sit amet lectus imperdiet interdum.Pellentesque et sem et nulla tempus cursus.Sed enim dolor, viverra eu mauris id, ornare congue urna."
  3761. "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sed pellentesque nibh. Mauris ac ipsum ante. Mauris dignissim vehicula dui, et mollis mauris tincidunt non. Aliquam sodales diam ante, in vestibulum nibh ultricies et. Pellentesque accumsan porta vulputate. Donec vel fringilla sem. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nam eu erat eu est mollis condimentum ut eget metus."
  3762. "Sed nec felis enim.Ut auctor arcu nec tristique volutpat.Nulla viverra vulputate nibh et fringilla.Curabitur sagittis eu libero ullamcorper porta.Ut ac nisi vitae massa luctus tristique.Donec scelerisque, odio at pharetra consectetur, nunc urna porta ligula, tincidunt auctor orci purus non nisi.Nulla at risus at lacus vestibulum varius vitae ac tellus.Etiam ut sem commodo justo tempor congue vel id odio.Duis erat sem, condimentum a neque id, bibendum consectetur ligula.In eget massa lectus.Interdum et malesuada fames ac ante ipsum primis in faucibus.Ut ornare lectus at sem condimentum gravida vel ut est."
  3763. "Curabitur nisl metus, euismod in enim eu, pulvinar ullamcorper lorem.Morbi et adipiscing nisi.Aliquam id dapibus sapien.Aliquam facilisis, lacus porta interdum mattis, erat metus tempus ligula, nec cursus augue tellus ut urna.Sed sagittis arcu vel magna consequat, eget eleifend quam tincidunt.Maecenas non ornare nisi, placerat ornare orci.Proin auctor in nunc eu ultrices.Vivamus interdum imperdiet sapien nec cursus."
  3764. "Etiam et iaculis tortor.Nam lacus risus, rutrum a mollis quis, accumsan quis risus.Mauris ac fringilla lectus.Cras posuere massa ultricies libero fermentum, in convallis metus porttitor.Duis hendrerit gravida neque at ultricies.Vestibulum semper congue gravida.Etiam vel mi quis risus ornare convallis nec et elit.Praesent a mollis erat, in eleifend libero.Fusce porttitor malesuada velit, nec pharetra justo rutrum sit amet.Ut vel egestas lacus, sit amet posuere nunc."
  3765. "Maecenas in eleifend risus.Integer volutpat sodales massa vitae consequat.Cras urna turpis, laoreet sed ante sit amet, dictum commodo sem.Vivamus porta, neque vel blandit dictum, enim metus molestie nisl, a consectetur libero odio eu magna.Maecenas nisi nibh, dignissim et nisi eget, adipiscing auctor ligula.Sed in nisl libero.Maecenas aliquam urna orci, ac ultrices massa sollicitudin vitae.Donec ullamcorper suscipit viverra.Praesent dolor ipsum, tincidunt eu quam sit amet, aliquam cursus orci.Praesent elementum est sit amet lectus imperdiet interdum.Pellentesque et sem et nulla tempus cursus.Sed enim dolor, viverra eu mauris id, ornare congue urna."
  3766. ;
  3767. }
  3768. virtual ~Payload() {}
  3769. static bool ConvertOldVersions(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
  3770. {
  3771. (void)classElement;
  3772. (void)context;
  3773. if (classElement.GetVersion() == 4)
  3774. {
  3775. // convert from version 0
  3776. AZStd::string newData;
  3777. for (int i = 0; i < classElement.GetNumSubElements(); ++i)
  3778. {
  3779. AZ::SerializeContext::DataElementNode& elementNode = classElement.GetSubElement(i);
  3780. if (elementNode.GetName() == AZ_CRC("m_textData", 0xfc7870e5))
  3781. {
  3782. bool result = elementNode.GetData(newData);
  3783. EXPECT_TRUE(result);
  3784. classElement.RemoveElement(i);
  3785. break;
  3786. }
  3787. }
  3788. for (int i = 0; i < classElement.GetNumSubElements(); ++i)
  3789. {
  3790. AZ::SerializeContext::DataElementNode& elementNode = classElement.GetSubElement(i);
  3791. if (elementNode.GetName() == AZ_CRC("m_newTextData", 0x3feafc3d))
  3792. {
  3793. elementNode.SetData(context, newData);
  3794. break;
  3795. }
  3796. }
  3797. return true;
  3798. }
  3799. return false; // just discard unknown versions
  3800. }
  3801. static void Reflect(AZ::SerializeContext& sc)
  3802. {
  3803. sc.Class<Payload>()->
  3804. Version(5, &Payload::ConvertOldVersions)->
  3805. Field("m_textData", &Payload::m_textData)->
  3806. Field("m_newTextData", &Payload::m_newTextData)->
  3807. Field("m_payload", &Payload::m_payload)
  3808. ;
  3809. }
  3810. void SaveObjects(ObjectStream* writer)
  3811. {
  3812. bool success = true;
  3813. success = writer->WriteClass(this);
  3814. EXPECT_TRUE(success);
  3815. }
  3816. void TestSave(IO::GenericStream* stream, ObjectStream::StreamType format)
  3817. {
  3818. ObjectStream* objStream = ObjectStream::Create(stream, m_context, format);
  3819. SaveObjects(objStream);
  3820. bool done = objStream->Finalize();
  3821. EXPECT_TRUE(done);
  3822. }
  3823. };
  3824. }
  3825. /*
  3826. * Test serialization using FileUtil.
  3827. * FileUtil interacts with the serialization context through the ComponentApplicationBus.
  3828. */
  3829. class SerializationFileUtil
  3830. : public Serialization
  3831. {
  3832. public:
  3833. void SetUp() override
  3834. {
  3835. Serialization::SetUp();
  3836. m_prevFileIO = AZ::IO::FileIOBase::GetInstance();
  3837. AZ::IO::FileIOBase::SetInstance(&m_fileIO);
  3838. BaseRtti::Reflect(*m_serializeContext);
  3839. }
  3840. void TearDown() override
  3841. {
  3842. AZ::IO::FileIOBase::SetInstance(m_prevFileIO);
  3843. Serialization::TearDown();
  3844. }
  3845. void TestFileUtilsStream(AZ::DataStream::StreamType streamType)
  3846. {
  3847. BaseRtti toSerialize;
  3848. toSerialize.m_data = false;
  3849. // Test Stream Write
  3850. AZStd::vector<char> charBuffer;
  3851. IO::ByteContainerStream<AZStd::vector<char> > charStream(&charBuffer);
  3852. bool success = AZ::Utils::SaveObjectToStream(charStream, streamType, &toSerialize);
  3853. EXPECT_TRUE(success);
  3854. // Test Stream Read
  3855. // Set the stream to the beginning so what was written can be read.
  3856. charStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  3857. BaseRtti* deserialized = AZ::Utils::LoadObjectFromStream<BaseRtti>(charStream);
  3858. EXPECT_TRUE(deserialized);
  3859. EXPECT_EQ( toSerialize.m_data, deserialized->m_data );
  3860. delete deserialized;
  3861. deserialized = nullptr;
  3862. // Test LoadObjectFromBuffer
  3863. // First, save the object to a u8 buffer.
  3864. AZStd::vector<u8> u8Buffer;
  3865. IO::ByteContainerStream<AZStd::vector<u8> > u8Stream(&u8Buffer);
  3866. success = AZ::Utils::SaveObjectToStream(u8Stream, streamType, &toSerialize);
  3867. EXPECT_TRUE(success);
  3868. u8Stream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  3869. deserialized = AZ::Utils::LoadObjectFromBuffer<BaseRtti>(&u8Buffer[0], u8Buffer.size());
  3870. EXPECT_TRUE(deserialized);
  3871. EXPECT_EQ( toSerialize.m_data, deserialized->m_data );
  3872. delete deserialized;
  3873. deserialized = nullptr;
  3874. // Write to stream twice, read once.
  3875. // Note that subsequent calls to write to stream will be ignored.
  3876. // Note that many asserts here are commented out because the stream functionality was giving
  3877. // unexpected results. There are rally stories on the backlog backlog (I e-mailed someone to put them on the backlog)
  3878. // related to this.
  3879. AZStd::vector<char> charBufferWriteTwice;
  3880. IO::ByteContainerStream<AZStd::vector<char> > charStreamWriteTwice(&charBufferWriteTwice);
  3881. success = AZ::Utils::SaveObjectToStream(charStreamWriteTwice, streamType, &toSerialize);
  3882. EXPECT_TRUE(success);
  3883. BaseRtti secondSerializedObject;
  3884. secondSerializedObject.m_data = true;
  3885. success = AZ::Utils::SaveObjectToStream(charStreamWriteTwice, streamType, &secondSerializedObject);
  3886. // SaveObjectToStream currently returns success after attempting to save a second object.
  3887. // This does not match up with the later behavior of loading from this stream.
  3888. // Currently, saving twice returns a success on each save, and loading once returns the first object.
  3889. // What should happen, is either the attempt to save onto the stream again should return false,
  3890. // or the read should return the second object first.
  3891. //EXPECT_TRUE(success);
  3892. charStreamWriteTwice.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  3893. deserialized = AZ::Utils::LoadObjectFromStream<BaseRtti>(charStreamWriteTwice);
  3894. EXPECT_TRUE(deserialized);
  3895. // Read the above text. This is here for whoever addresses these backlog items.
  3896. //EXPECT_EQ( toSerialize.m_data, deserialized->m_data );
  3897. //EXPECT_EQ( secondSerializedObject.m_data, deserialized->m_data );
  3898. delete deserialized;
  3899. deserialized = nullptr;
  3900. }
  3901. void TestFileUtilsFile(AZ::DataStream::StreamType streamType)
  3902. {
  3903. BaseRtti toSerialize;
  3904. toSerialize.m_data = false;
  3905. // Test save once, read once.
  3906. AZ::IO::Path filePath = GetTestFolderPath() / "FileUtilsTest";
  3907. bool success = AZ::Utils::SaveObjectToFile(filePath.Native(), streamType, &toSerialize);
  3908. EXPECT_TRUE(success);
  3909. BaseRtti* deserialized = AZ::Utils::LoadObjectFromFile<BaseRtti>(filePath.Native());
  3910. EXPECT_TRUE(deserialized);
  3911. EXPECT_EQ( toSerialize.m_data, deserialized->m_data );
  3912. delete deserialized;
  3913. deserialized = nullptr;
  3914. // Test save twice, read once.
  3915. // This is valid with files because saving a file again will overwrite it. Note that streams function differently.
  3916. success = AZ::Utils::SaveObjectToFile(filePath.Native(), streamType, &toSerialize);
  3917. EXPECT_TRUE(success);
  3918. success = AZ::Utils::SaveObjectToFile(filePath.Native(), streamType, &toSerialize);
  3919. EXPECT_TRUE(success);
  3920. deserialized = AZ::Utils::LoadObjectFromFile<BaseRtti>(filePath.Native());
  3921. EXPECT_TRUE(deserialized);
  3922. EXPECT_EQ( toSerialize.m_data, deserialized->m_data );
  3923. delete deserialized;
  3924. deserialized = nullptr;
  3925. // Test reading from an invalid file. The system should return 'nullptr' when given a bad file path.
  3926. AZ::IO::SystemFile::Delete(filePath.c_str());
  3927. deserialized = AZ::Utils::LoadObjectFromFile<BaseRtti>(filePath.Native());
  3928. EXPECT_EQ(nullptr, deserialized);
  3929. }
  3930. TestFileIOBase m_fileIO;
  3931. AZ::IO::FileIOBase* m_prevFileIO;
  3932. };
  3933. TEST_F(SerializationFileUtil, TestFileUtilsStream_XML)
  3934. {
  3935. TestFileUtilsStream(ObjectStream::ST_XML);
  3936. }
  3937. TEST_F(SerializationFileUtil, TestFileUtilsStream_Binary)
  3938. {
  3939. TestFileUtilsStream(ObjectStream::ST_BINARY);
  3940. }
  3941. TEST_F(SerializationFileUtil, DISABLED_TestFileUtilsFile_XML)
  3942. {
  3943. TestFileUtilsFile(ObjectStream::ST_XML);
  3944. }
  3945. TEST_F(SerializationFileUtil, DISABLED_TestFileUtilsFile_Binary)
  3946. {
  3947. TestFileUtilsFile(ObjectStream::ST_BINARY);
  3948. }
  3949. /*
  3950. *
  3951. */
  3952. class SerializeDescendentDataElementTest
  3953. : public LeakDetectionFixture
  3954. {
  3955. public:
  3956. struct DataElementTestClass
  3957. {
  3958. AZ_CLASS_ALLOCATOR(DataElementTestClass, AZ::SystemAllocator);
  3959. AZ_TYPE_INFO(DataElementTestClass, "{F515B922-BBB9-4216-A2C9-FD665AA30046}");
  3960. DataElementTestClass() {}
  3961. AZStd::unique_ptr<AZ::Entity> m_data;
  3962. AZStd::vector<AZ::Vector2> m_positions;
  3963. private:
  3964. DataElementTestClass(const DataElementTestClass&) = delete;
  3965. };
  3966. void SetUp() override
  3967. {
  3968. LeakDetectionFixture::SetUp();
  3969. m_dataElementClass = AZStd::make_unique<DataElementTestClass>();
  3970. }
  3971. void TearDown() override
  3972. {
  3973. m_dataElementClass.reset(); // reset it before the allocators are destroyed
  3974. LeakDetectionFixture::TearDown();
  3975. }
  3976. static bool VersionConverter(AZ::SerializeContext& sc, AZ::SerializeContext::DataElementNode& classElement)
  3977. {
  3978. if (classElement.GetVersion() == 0)
  3979. {
  3980. auto entityIdElements = AZ::Utils::FindDescendantElements(sc, classElement, AZStd::vector<AZ::Crc32>({ AZ_CRC("m_data"), AZ_CRC("element"), AZ_CRC("Id"), AZ_CRC("id") }));
  3981. EXPECT_EQ(1, entityIdElements.size());
  3982. AZ::u64 id1;
  3983. EXPECT_TRUE(entityIdElements.front()->GetData(id1));
  3984. EXPECT_EQ(47, id1);
  3985. auto vector2Elements = AZ::Utils::FindDescendantElements(sc, classElement, AZStd::vector<AZ::Crc32>({ AZ_CRC("m_positions"), AZ_CRC("element") }));
  3986. EXPECT_EQ(2, vector2Elements.size());
  3987. AZ::Vector2 position;
  3988. EXPECT_TRUE(vector2Elements[0]->GetData(position));
  3989. EXPECT_FLOAT_EQ(1.0f, position.GetX());
  3990. EXPECT_FLOAT_EQ(2.0f, position.GetY());
  3991. EXPECT_TRUE(vector2Elements[1]->GetData(position));
  3992. EXPECT_FLOAT_EQ(2.0f, position.GetX());
  3993. EXPECT_FLOAT_EQ(4.0f, position.GetY());
  3994. }
  3995. return true;
  3996. }
  3997. AZStd::unique_ptr<DataElementTestClass> m_dataElementClass;
  3998. void run()
  3999. {
  4000. m_dataElementClass->m_data = AZStd::make_unique<AZ::Entity>("DataElement");
  4001. m_dataElementClass->m_data->SetId(AZ::EntityId(47));
  4002. m_dataElementClass->m_positions.emplace_back(1.0f, 2.0f);
  4003. m_dataElementClass->m_positions.emplace_back(2.0f, 4.0f);
  4004. // Write original data
  4005. AZStd::vector<AZ::u8> binaryBuffer;
  4006. {
  4007. AZ::SerializeContext sc;
  4008. AZ::Entity::Reflect(&sc);
  4009. sc.Class<DataElementTestClass>()
  4010. ->Version(0)
  4011. ->Field("m_data", &DataElementTestClass::m_data)
  4012. ->Field("m_positions", &DataElementTestClass::m_positions);
  4013. // Binary
  4014. AZ::IO::ByteContainerStream<AZStd::vector<AZ::u8> > binaryStream(&binaryBuffer);
  4015. AZ::ObjectStream* binaryObjStream = ObjectStream::Create(&binaryStream, sc, ObjectStream::ST_BINARY);
  4016. binaryObjStream->WriteClass(m_dataElementClass.get());
  4017. EXPECT_TRUE(binaryObjStream->Finalize());
  4018. }
  4019. // Test find descendant version converter
  4020. {
  4021. AZ::SerializeContext sc;
  4022. AZ::Entity::Reflect(&sc);
  4023. sc.Class<DataElementTestClass>()
  4024. ->Version(1, &VersionConverter)
  4025. ->Field("m_data", &DataElementTestClass::m_data)
  4026. ->Field("m_positions", &DataElementTestClass::m_positions);
  4027. // Binary
  4028. IO::ByteContainerStream<const AZStd::vector<AZ::u8> > binaryStream(&binaryBuffer);
  4029. binaryStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  4030. AZ::ObjectStream::ClassReadyCB readyCB([&](void* classPtr, const AZ::Uuid& classId, AZ::SerializeContext* sc)
  4031. {
  4032. AZ_UNUSED(classId);
  4033. AZ_UNUSED(sc);
  4034. delete reinterpret_cast<DataElementTestClass*>(classPtr);
  4035. });
  4036. ObjectStream::LoadBlocking(&binaryStream, sc, readyCB);
  4037. }
  4038. }
  4039. };
  4040. TEST_F(SerializeDescendentDataElementTest, FindTest)
  4041. {
  4042. run();
  4043. }
  4044. class SerializeDataElementNodeTreeTest
  4045. : public LeakDetectionFixture
  4046. {
  4047. public:
  4048. struct EntityWrapperTest
  4049. {
  4050. AZ_CLASS_ALLOCATOR(EntityWrapperTest, AZ::SystemAllocator);
  4051. AZ_TYPE_INFO(EntityWrapperTest, "{BCBC25C3-3D6F-4FC4-B73D-51E6FBD38730}");
  4052. AZ::Entity* m_entity = nullptr;
  4053. };
  4054. struct ContainerTest
  4055. {
  4056. AZ_CLASS_ALLOCATOR(ContainerTest, AZ::SystemAllocator);
  4057. AZ_TYPE_INFO(ContainerTest, "{88FD1BBA-EE9C-4165-8C66-B8B5F28B9205}");
  4058. AZStd::vector<int> m_addedVector;
  4059. AZStd::unordered_set<int> m_removedSet;
  4060. AZStd::vector<int> m_changedVector;
  4061. AZStd::string m_addedString;
  4062. };
  4063. struct EntityContainerTest
  4064. {
  4065. AZ_CLASS_ALLOCATOR(EntityContainerTest, AZ::SystemAllocator);
  4066. AZ_TYPE_INFO(EntityContainerTest, "{A1145D9A-402F-4A40-9B59-52DEAE1070DA}");
  4067. AZStd::unordered_set<AZ::Entity*> m_entitySet;
  4068. };
  4069. struct UnorderedMapContainerTest
  4070. {
  4071. AZ_CLASS_ALLOCATOR(UnorderedMapContainerTest, AZ::SystemAllocator);
  4072. AZ_TYPE_INFO(UnorderedMapContainerTest, "{744ADFE1-4BFF-4F3F-8ED0-EA1BDC4A0D2F}");
  4073. AZStd::unordered_map<AZStd::string, int> m_stringIntMap;
  4074. };
  4075. void SetUp() override
  4076. {
  4077. LeakDetectionFixture::SetUp();
  4078. SerializeDataElementNodeTreeTest::m_wrappedBuffer = AZStd::make_unique<AZStd::vector<AZ::u8>>();
  4079. }
  4080. void TearDown() override
  4081. {
  4082. SerializeDataElementNodeTreeTest::m_wrappedBuffer.reset();
  4083. LeakDetectionFixture::TearDown();
  4084. }
  4085. static bool GetDataHierachyVersionConverter(AZ::SerializeContext& sc, AZ::SerializeContext::DataElementNode& rootElement)
  4086. {
  4087. if (rootElement.GetVersion() == 0)
  4088. {
  4089. int entityIndex = rootElement.FindElement(AZ_CRC("m_entity"));
  4090. EXPECT_NE(-1, entityIndex);
  4091. AZ::SerializeContext::DataElementNode& entityElement = rootElement.GetSubElement(entityIndex);
  4092. AZ::Entity newEntity;
  4093. EXPECT_TRUE(entityElement.GetData(newEntity));
  4094. EXPECT_EQ(AZ::EntityId(21434), newEntity.GetId());
  4095. AZStd::vector<AZ::u8> newEntityBuffer;
  4096. {
  4097. // Binary
  4098. AZ::IO::ByteContainerStream<AZStd::vector<AZ::u8> > binaryStream(&newEntityBuffer);
  4099. AZ::ObjectStream* binaryObjStream = ObjectStream::Create(&binaryStream, sc, ObjectStream::ST_BINARY);
  4100. binaryObjStream->WriteClass(&newEntity);
  4101. EXPECT_TRUE(binaryObjStream->Finalize());
  4102. }
  4103. // Validate the newEntityBuffer against the wrapped entity.
  4104. EXPECT_EQ(*SerializeDataElementNodeTreeTest::m_wrappedBuffer, newEntityBuffer);
  4105. }
  4106. return true;
  4107. }
  4108. static bool ContainerTestVersionConverter(AZ::SerializeContext& sc, AZ::SerializeContext::DataElementNode& rootElement)
  4109. {
  4110. if (rootElement.GetVersion() == 0)
  4111. {
  4112. int removedSetIndex = rootElement.FindElement(AZ_CRC("m_removedSet"));
  4113. EXPECT_NE(-1, removedSetIndex);
  4114. int changedVectorIndex = rootElement.FindElement(AZ_CRC("m_changedVector"));
  4115. EXPECT_NE(-1, changedVectorIndex);
  4116. auto changedVectorInts = AZ::Utils::FindDescendantElements(sc, rootElement.GetSubElement(changedVectorIndex), { AZ_CRC("element") });
  4117. EXPECT_EQ(2, changedVectorInts.size());
  4118. EXPECT_TRUE(changedVectorInts[0]->SetData(sc, 75));
  4119. EXPECT_TRUE(changedVectorInts[1]->SetData(sc, 50));
  4120. int addedVectorIndex = rootElement.FindElement(AZ_CRC("m_addedVector"));
  4121. EXPECT_EQ(-1, addedVectorIndex);
  4122. ContainerTest containerTest;
  4123. EXPECT_TRUE(rootElement.GetData(containerTest));
  4124. EXPECT_TRUE(containerTest.m_removedSet.empty());
  4125. EXPECT_TRUE(containerTest.m_addedVector.empty());
  4126. EXPECT_EQ(2, containerTest.m_changedVector.size());
  4127. EXPECT_EQ(75, containerTest.m_changedVector[0]);
  4128. EXPECT_EQ(50, containerTest.m_changedVector[1]);
  4129. rootElement.RemoveElement(removedSetIndex);
  4130. // Add an m_addedVector array and remove the zeroth element from the m_changedVector array
  4131. AZStd::vector<int> newInts;
  4132. newInts.push_back(200);
  4133. newInts.push_back(-265);
  4134. newInts.push_back(9451);
  4135. AZStd::string newString("Test");
  4136. AZ::GenericClassInfo* containerGenericInfo = sc.FindGenericClassInfo(azrtti_typeid<AZStd::string>());
  4137. EXPECT_NE(nullptr, containerGenericInfo);
  4138. int addedStringIndex = rootElement.AddElement(sc, "m_addedString", containerGenericInfo); // Add String Element
  4139. EXPECT_NE(-1, addedStringIndex);
  4140. rootElement.GetSubElement(addedStringIndex).SetData(sc, newString); // Set string element data
  4141. rootElement.AddElementWithData(sc, "m_addedVector", newInts); // Add the addedVector vector<int> with initialized data
  4142. AZ::SerializeContext::DataElementNode* changedVectorElementNode = rootElement.FindSubElement(AZ_CRC("m_changedVector"));
  4143. EXPECT_NE(nullptr, changedVectorElementNode);
  4144. changedVectorElementNode->RemoveElement(0);
  4145. ContainerTest containerTest2;
  4146. EXPECT_TRUE(rootElement.GetData(containerTest2));
  4147. EXPECT_TRUE(containerTest2.m_removedSet.empty());
  4148. EXPECT_EQ(3, containerTest2.m_addedVector.size());
  4149. EXPECT_EQ(1, containerTest2.m_changedVector.size());
  4150. EXPECT_EQ(200, containerTest2.m_addedVector[0]);
  4151. EXPECT_EQ(-265, containerTest2.m_addedVector[1]);
  4152. EXPECT_EQ(9451, containerTest2.m_addedVector[2]);
  4153. EXPECT_EQ(50, containerTest2.m_changedVector[0]);
  4154. EXPECT_EQ("Test", containerTest2.m_addedString);
  4155. }
  4156. return true;
  4157. }
  4158. static bool ContainerOfEntitiesVersionConverter(AZ::SerializeContext&, AZ::SerializeContext::DataElementNode& rootElement)
  4159. {
  4160. if (rootElement.GetVersion() == 0)
  4161. {
  4162. int entityContainerIndex = rootElement.FindElement(AZ_CRC("m_entitySet"));
  4163. EXPECT_NE(-1, entityContainerIndex);
  4164. AZ::SerializeContext::DataElementNode& entityContainerElement = rootElement.GetSubElement(entityContainerIndex);
  4165. AZStd::unordered_set<AZ::Entity*> newContainerEntities;
  4166. EXPECT_TRUE(entityContainerElement.GetData(newContainerEntities));
  4167. for (AZ::Entity* entity : newContainerEntities)
  4168. {
  4169. delete entity;
  4170. }
  4171. }
  4172. return true;
  4173. }
  4174. static bool StringIntMapVersionConverter(AZ::SerializeContext& sc, AZ::SerializeContext::DataElementNode& rootElement)
  4175. {
  4176. if (rootElement.GetVersion() == 0)
  4177. {
  4178. int stringIntMapIndex = rootElement.FindElement(AZ_CRC("m_stringIntMap"));
  4179. EXPECT_NE(-1, stringIntMapIndex);
  4180. UnorderedMapContainerTest containerTest;
  4181. EXPECT_TRUE(rootElement.GetDataHierarchy(sc, containerTest));
  4182. EXPECT_EQ(4, containerTest.m_stringIntMap.size());
  4183. auto foundIt = containerTest.m_stringIntMap.find("Source");
  4184. EXPECT_NE(foundIt, containerTest.m_stringIntMap.end());
  4185. EXPECT_EQ(0, foundIt->second);
  4186. foundIt = containerTest.m_stringIntMap.find("Target");
  4187. EXPECT_NE(containerTest.m_stringIntMap.end(), foundIt);
  4188. EXPECT_EQ(2, foundIt->second);
  4189. foundIt = containerTest.m_stringIntMap.find("In");
  4190. EXPECT_NE(containerTest.m_stringIntMap.end(), foundIt);
  4191. EXPECT_EQ(1, foundIt->second);
  4192. foundIt = containerTest.m_stringIntMap.find("Out");
  4193. EXPECT_NE(containerTest.m_stringIntMap.end(), foundIt);
  4194. EXPECT_EQ(4, foundIt->second);
  4195. }
  4196. return true;
  4197. }
  4198. protected:
  4199. static AZStd::unique_ptr<AZStd::vector<AZ::u8>> m_wrappedBuffer;
  4200. };
  4201. AZStd::unique_ptr<AZStd::vector<AZ::u8>> SerializeDataElementNodeTreeTest::m_wrappedBuffer;
  4202. TEST_F(SerializeDataElementNodeTreeTest, GetDataHierarchyTest)
  4203. {
  4204. EntityWrapperTest entityWrapperTest;
  4205. entityWrapperTest.m_entity = aznew Entity("DataElement");
  4206. entityWrapperTest.m_entity->SetId(AZ::EntityId(21434));
  4207. // Write original data
  4208. AZStd::vector<AZ::u8> binaryBuffer;
  4209. {
  4210. AZ::SerializeContext sc;
  4211. AZ::Entity::Reflect(&sc);
  4212. sc.Class<EntityWrapperTest>()
  4213. ->Version(0)
  4214. ->Field("m_entity", &EntityWrapperTest::m_entity);
  4215. // Binary
  4216. AZ::IO::ByteContainerStream<AZStd::vector<AZ::u8>> binaryStream(&binaryBuffer);
  4217. AZ::ObjectStream* binaryObjStream = ObjectStream::Create(&binaryStream, sc, ObjectStream::ST_BINARY);
  4218. binaryObjStream->WriteClass(&entityWrapperTest);
  4219. EXPECT_TRUE(binaryObjStream->Finalize());
  4220. // Write static buffer for wrapped entity data
  4221. binaryStream = AZ::IO::ByteContainerStream<AZStd::vector<AZ::u8>>(SerializeDataElementNodeTreeTest::m_wrappedBuffer.get());
  4222. binaryObjStream = ObjectStream::Create(&binaryStream, sc, ObjectStream::ST_BINARY);
  4223. binaryObjStream->WriteClass(entityWrapperTest.m_entity); // Serialize out the wrapped entity.
  4224. EXPECT_TRUE(binaryObjStream->Finalize());
  4225. }
  4226. // GetDataHierarhyVersionConverter version converter
  4227. {
  4228. AZ::SerializeContext sc;
  4229. AZ::Entity::Reflect(&sc);
  4230. sc.Class<EntityWrapperTest>()
  4231. ->Version(1, &GetDataHierachyVersionConverter)
  4232. ->Field("m_entity", &EntityWrapperTest::m_entity);
  4233. // Binary
  4234. IO::ByteContainerStream<const AZStd::vector<AZ::u8> > binaryStream(&binaryBuffer);
  4235. binaryStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  4236. AZ::ObjectStream::ClassReadyCB readyCB([&](void* classPtr, const AZ::Uuid& classId, AZ::SerializeContext* sc)
  4237. {
  4238. AZ_UNUSED(classId);
  4239. AZ_UNUSED(sc);
  4240. EntityWrapperTest* entityWrapper = reinterpret_cast<EntityWrapperTest*>(classPtr);
  4241. delete entityWrapper->m_entity;
  4242. delete entityWrapper;
  4243. });
  4244. ObjectStream::LoadBlocking(&binaryStream, sc, readyCB);
  4245. }
  4246. delete entityWrapperTest.m_entity;
  4247. }
  4248. TEST_F(SerializeDataElementNodeTreeTest, ContainerElementTest)
  4249. {
  4250. ContainerTest containerTest;
  4251. containerTest.m_addedVector.push_back(10);
  4252. containerTest.m_addedVector.push_back(15);
  4253. containerTest.m_removedSet.emplace(25);
  4254. containerTest.m_removedSet.emplace(30);
  4255. containerTest.m_changedVector.push_back(40);
  4256. containerTest.m_changedVector.push_back(45);
  4257. // Write original data
  4258. AZStd::vector<AZ::u8> binaryBuffer;
  4259. {
  4260. AZ::SerializeContext sc;
  4261. sc.Class<ContainerTest>()
  4262. ->Version(0)
  4263. ->Field("m_removedSet", &ContainerTest::m_removedSet)
  4264. ->Field("m_changedVector", &ContainerTest::m_changedVector);
  4265. // Binary
  4266. AZ::IO::ByteContainerStream<AZStd::vector<AZ::u8>> binaryStream(&binaryBuffer);
  4267. AZ::ObjectStream* binaryObjStream = ObjectStream::Create(&binaryStream, sc, ObjectStream::ST_BINARY);
  4268. binaryObjStream->WriteClass(&containerTest);
  4269. EXPECT_TRUE(binaryObjStream->Finalize());
  4270. }
  4271. // Test container version converter
  4272. {
  4273. ContainerTest loadedContainer;
  4274. AZ::SerializeContext sc;
  4275. AZ::GenericClassInfo* genericClassInfo = AZ::SerializeGenericTypeInfo<AZStd::unordered_set<int>>::GetGenericInfo();
  4276. genericClassInfo->Reflect(&sc);
  4277. sc.Class<ContainerTest>()
  4278. ->Version(1, &ContainerTestVersionConverter)
  4279. ->Field("m_addedVector", &ContainerTest::m_addedVector)
  4280. ->Field("m_changedVector", &ContainerTest::m_changedVector)
  4281. ->Field("m_addedString", &ContainerTest::m_addedString);
  4282. // Binary
  4283. IO::ByteContainerStream<const AZStd::vector<AZ::u8> > binaryStream(&binaryBuffer);
  4284. binaryStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  4285. ObjectStream::LoadBlocking(&binaryStream, sc, [&loadedContainer](void* objectPtr, const AZ::Uuid typeId, AZ::SerializeContext* serializeContext)
  4286. {
  4287. auto containerTestPtr = static_cast<ContainerTest*>(serializeContext->DownCast(objectPtr, typeId, azrtti_typeid<ContainerTest>()));
  4288. if (containerTestPtr)
  4289. {
  4290. loadedContainer = *containerTestPtr;
  4291. }
  4292. auto classData = serializeContext->FindClassData(typeId);
  4293. if (classData && classData->m_factory)
  4294. {
  4295. classData->m_factory->Destroy(objectPtr);
  4296. }
  4297. });
  4298. EXPECT_TRUE(loadedContainer.m_removedSet.empty());
  4299. EXPECT_EQ(1, loadedContainer.m_changedVector.size());
  4300. EXPECT_EQ(3, loadedContainer.m_addedVector.size());
  4301. EXPECT_EQ(50, loadedContainer.m_changedVector[0]);
  4302. EXPECT_EQ(200, loadedContainer.m_addedVector[0]);
  4303. EXPECT_EQ(-265, loadedContainer.m_addedVector[1]);
  4304. EXPECT_EQ(9451, loadedContainer.m_addedVector[2]);
  4305. EXPECT_EQ("Test", loadedContainer.m_addedString);
  4306. }
  4307. }
  4308. TEST_F(SerializeDataElementNodeTreeTest, EntityContainerElementTest)
  4309. {
  4310. EntityContainerTest containerTest;
  4311. containerTest.m_entitySet.insert(aznew AZ::Entity("Test"));
  4312. // Write original data
  4313. AZStd::vector<AZ::u8> binaryBuffer;
  4314. {
  4315. AZ::SerializeContext sc;
  4316. AZ::Entity::Reflect(&sc);
  4317. sc.Class<EntityContainerTest>()
  4318. ->Version(0)
  4319. ->Field("m_entitySet", &EntityContainerTest::m_entitySet);
  4320. // Binary
  4321. AZ::IO::ByteContainerStream<AZStd::vector<AZ::u8>> binaryStream(&binaryBuffer);
  4322. AZ::ObjectStream* binaryObjStream = ObjectStream::Create(&binaryStream, sc, ObjectStream::ST_BINARY);
  4323. binaryObjStream->WriteClass(&containerTest);
  4324. EXPECT_TRUE(binaryObjStream->Finalize());
  4325. }
  4326. // Test container version converter
  4327. {
  4328. EntityContainerTest loadedContainer;
  4329. AZ::SerializeContext sc;
  4330. AZ::Entity::Reflect(&sc);
  4331. sc.Class<EntityContainerTest>()
  4332. ->Version(1, &ContainerOfEntitiesVersionConverter)
  4333. ->Field("m_entitySet", &EntityContainerTest::m_entitySet);
  4334. // Binary
  4335. IO::ByteContainerStream<const AZStd::vector<AZ::u8> > binaryStream(&binaryBuffer);
  4336. binaryStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  4337. ObjectStream::LoadBlocking(&binaryStream, sc, [&loadedContainer](void* objectPtr, const AZ::Uuid typeId, AZ::SerializeContext* serializeContext)
  4338. {
  4339. auto containerTestPtr = static_cast<EntityContainerTest*>(serializeContext->DownCast(objectPtr, typeId, azrtti_typeid<EntityContainerTest>()));
  4340. if (containerTestPtr)
  4341. {
  4342. loadedContainer = *containerTestPtr;
  4343. }
  4344. auto classData = serializeContext->FindClassData(typeId);
  4345. if (classData && classData->m_factory)
  4346. {
  4347. classData->m_factory->Destroy(objectPtr);
  4348. }
  4349. });
  4350. for (auto&& entityContainer : { containerTest.m_entitySet, loadedContainer.m_entitySet })
  4351. {
  4352. for (AZ::Entity* entity : entityContainer)
  4353. {
  4354. delete entity;
  4355. }
  4356. }
  4357. }
  4358. }
  4359. TEST_F(SerializeDataElementNodeTreeTest, UnorderedMapContainerElementTest)
  4360. {
  4361. UnorderedMapContainerTest containerTest;
  4362. containerTest.m_stringIntMap.emplace("Source", 0);
  4363. containerTest.m_stringIntMap.emplace("Target", 2);
  4364. containerTest.m_stringIntMap.emplace("In", 1);
  4365. containerTest.m_stringIntMap.emplace("Out", 4);
  4366. // Write original data
  4367. AZStd::vector<AZ::u8> binaryBuffer;
  4368. {
  4369. AZ::SerializeContext sc;
  4370. sc.Class<UnorderedMapContainerTest>()
  4371. ->Version(0)
  4372. ->Field("m_stringIntMap", &UnorderedMapContainerTest::m_stringIntMap);
  4373. // Binary
  4374. AZ::IO::ByteContainerStream<AZStd::vector<AZ::u8>> binaryStream(&binaryBuffer);
  4375. AZ::ObjectStream* binaryObjStream = ObjectStream::Create(&binaryStream, sc, ObjectStream::ST_BINARY);
  4376. binaryObjStream->WriteClass(&containerTest);
  4377. EXPECT_TRUE(binaryObjStream->Finalize());
  4378. }
  4379. // Test container version converter
  4380. {
  4381. UnorderedMapContainerTest loadedContainer;
  4382. AZ::SerializeContext sc;
  4383. sc.Class<UnorderedMapContainerTest>()
  4384. ->Version(1, &StringIntMapVersionConverter)
  4385. ->Field("m_stringIntMap", &UnorderedMapContainerTest::m_stringIntMap);
  4386. // Binary
  4387. IO::ByteContainerStream<const AZStd::vector<AZ::u8> > binaryStream(&binaryBuffer);
  4388. binaryStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  4389. EXPECT_TRUE(Utils::LoadObjectFromStreamInPlace(binaryStream, loadedContainer, &sc));
  4390. }
  4391. }
  4392. class SerializeDataElementNodeGetDataTest
  4393. : public LeakDetectionFixture
  4394. {
  4395. public:
  4396. struct TemporarilyReflected
  4397. {
  4398. AZ_CLASS_ALLOCATOR(TemporarilyReflected, AZ::SystemAllocator);
  4399. AZ_TYPE_INFO(TemporarilyReflected, "{F0909A1D-09BF-44D5-A1D8-E27C8E45579D}");
  4400. AZ::u64 m_num{};
  4401. };
  4402. struct ReflectionWrapper
  4403. {
  4404. AZ_CLASS_ALLOCATOR(ReflectionWrapper, AZ::SystemAllocator);
  4405. AZ_TYPE_INFO(ReflectionWrapper, "{EACE8B18-CC31-4E7F-A34C-2A6AA8EB998D}");
  4406. TemporarilyReflected m_tempReflected;
  4407. };
  4408. static bool GetDataOnNonReflectedClassVersionConverter(AZ::SerializeContext& sc, AZ::SerializeContext::DataElementNode& rootElement)
  4409. {
  4410. (void)sc;
  4411. if (rootElement.GetVersion() == 0)
  4412. {
  4413. // The GetData should not crash
  4414. ReflectionWrapper reflectionWrapper;
  4415. EXPECT_FALSE(rootElement.GetData(reflectionWrapper));
  4416. // Drop the m_tempReflectedElement from the ReflectionWrapper
  4417. EXPECT_TRUE(rootElement.RemoveElementByName(AZ_CRC("m_tempReflected")));
  4418. EXPECT_TRUE(rootElement.GetData(reflectionWrapper));
  4419. }
  4420. return true;
  4421. }
  4422. };
  4423. TEST_F(SerializeDataElementNodeGetDataTest, GetDataOnNonReflectedClassTest)
  4424. {
  4425. ReflectionWrapper testReflectionWrapper;
  4426. AZ::SerializeContext sc;
  4427. sc.Class<TemporarilyReflected>()
  4428. ->Version(0)
  4429. ->Field("m_num", &TemporarilyReflected::m_num)
  4430. ;
  4431. sc.Class<ReflectionWrapper>()
  4432. ->Version(0)
  4433. ->Field("m_tempReflected", &ReflectionWrapper::m_tempReflected)
  4434. ;
  4435. AZStd::vector<AZ::u8> binaryBuffer;
  4436. AZ::IO::ByteContainerStream<AZStd::vector<AZ::u8>> binaryStream(&binaryBuffer);
  4437. AZ::ObjectStream* binaryObjStream = ObjectStream::Create(&binaryStream, sc, ObjectStream::ST_BINARY);
  4438. binaryObjStream->WriteClass(&testReflectionWrapper);
  4439. EXPECT_TRUE(binaryObjStream->Finalize());
  4440. sc.EnableRemoveReflection();
  4441. // Remove the TemporarilyReflected struct so that it is not found when loading
  4442. sc.Class<TemporarilyReflected>()
  4443. ->Version(0)
  4444. ->Field("m_num", &TemporarilyReflected::m_num)
  4445. ;
  4446. // Unreflect ReflectionWrapper version 0 and Reflect it again as version 1
  4447. sc.Class<ReflectionWrapper>()
  4448. ->Version(0)
  4449. ->Field("m_tempReflected", &ReflectionWrapper::m_tempReflected)
  4450. ;
  4451. sc.DisableRemoveReflection();
  4452. sc.Class<ReflectionWrapper>()
  4453. ->Version(1, &GetDataOnNonReflectedClassVersionConverter)
  4454. ->Field("m_tempReflected", &ReflectionWrapper::m_tempReflected)
  4455. ;
  4456. ReflectionWrapper loadReflectionWrapper;
  4457. binaryStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  4458. AZ_TEST_START_TRACE_SUPPRESSION;
  4459. EXPECT_TRUE(Utils::LoadObjectFromStreamInPlace(binaryStream, loadReflectionWrapper, &sc));
  4460. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  4461. }
  4462. class SerializableAnyFieldTest
  4463. : public LeakDetectionFixture
  4464. {
  4465. public:
  4466. struct AnyMemberClass
  4467. {
  4468. AZ_TYPE_INFO(AnyMemberClass, "{67F73D37-5F9E-42FE-AFC9-9867924D87DD}");
  4469. AZ_CLASS_ALLOCATOR(AnyMemberClass, AZ::SystemAllocator);
  4470. static void Reflect(ReflectContext* context)
  4471. {
  4472. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  4473. {
  4474. serializeContext->Class<AnyMemberClass>()
  4475. ->Field("Any", &AnyMemberClass::m_any)
  4476. ;
  4477. }
  4478. }
  4479. AZStd::any m_any;
  4480. };
  4481. // We must expose the class for serialization first.
  4482. void SetUp() override
  4483. {
  4484. LeakDetectionFixture::SetUp();
  4485. m_serializeContext = AZStd::make_unique<SerializeContext>();
  4486. AnyMemberClass::Reflect(m_serializeContext.get());
  4487. MyClassBase1::Reflect(*m_serializeContext);
  4488. MyClassBase2::Reflect(*m_serializeContext);
  4489. MyClassBase3::Reflect(*m_serializeContext);
  4490. SerializeTestClasses::MyClassMix::Reflect(*m_serializeContext);
  4491. ReflectedString::Reflect(m_serializeContext.get());
  4492. ReflectedSmartPtr::Reflect(m_serializeContext.get());
  4493. NonCopyableClass::Reflect(m_serializeContext.get());
  4494. m_serializeContext->RegisterGenericType<AZStd::shared_ptr<NonCopyableClass>>();
  4495. }
  4496. void TearDown() override
  4497. {
  4498. m_serializeContext->EnableRemoveReflection();
  4499. AnyMemberClass::Reflect(m_serializeContext.get());
  4500. MyClassBase1::Reflect(*m_serializeContext);
  4501. MyClassBase2::Reflect(*m_serializeContext);
  4502. MyClassBase3::Reflect(*m_serializeContext);
  4503. SerializeTestClasses::MyClassMix::Reflect(*m_serializeContext);
  4504. ReflectedString::Reflect(m_serializeContext.get());
  4505. ReflectedSmartPtr::Reflect(m_serializeContext.get());
  4506. NonCopyableClass::Reflect(m_serializeContext.get());
  4507. m_serializeContext->RegisterGenericType<AZStd::shared_ptr<NonCopyableClass>>();
  4508. m_serializeContext->DisableRemoveReflection();
  4509. m_serializeContext.reset();
  4510. LeakDetectionFixture::TearDown();
  4511. }
  4512. struct ReflectedString
  4513. {
  4514. AZ_TYPE_INFO(ReflectedString, "{5DE01DEA-119F-43E9-B87C-BF980EBAD896}");
  4515. AZ_CLASS_ALLOCATOR(ReflectedString, AZ::SystemAllocator);
  4516. static void Reflect(ReflectContext* context)
  4517. {
  4518. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  4519. {
  4520. //String class must reflected in at least one field
  4521. serializeContext->Class<ReflectedString>()
  4522. ->Field("String", &ReflectedString::m_name)
  4523. ;
  4524. }
  4525. }
  4526. AZStd::string m_name;
  4527. };
  4528. struct ReflectedSmartPtr
  4529. {
  4530. AZ_TYPE_INFO(ReflectedSmartPtr, "{3EAA2B56-A6A8-46E0-9869-DA4A15AE6704}");
  4531. AZ_CLASS_ALLOCATOR(ReflectedSmartPtr, AZ::SystemAllocator);
  4532. ReflectedSmartPtr() = default;
  4533. static void Reflect(ReflectContext* context)
  4534. {
  4535. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  4536. {
  4537. //String class must reflected in at least one field
  4538. serializeContext->Class<ReflectedSmartPtr>()
  4539. ->Field("Field1", &ReflectedSmartPtr::m_uniqueString)
  4540. ->Field("Field2", &ReflectedSmartPtr::m_sharedString)
  4541. ;
  4542. }
  4543. }
  4544. AZStd::unique_ptr<ReflectedString> m_uniqueString;
  4545. AZStd::shared_ptr<ReflectedString> m_sharedString;
  4546. private:
  4547. ReflectedSmartPtr(const ReflectedSmartPtr&) = delete;
  4548. };
  4549. struct NonCopyableClass
  4550. {
  4551. AZ_TYPE_INFO(NonCopyableClass, "{5DE8EA5C-9F4A-43F6-9B8B-10EF06319972}");
  4552. AZ_CLASS_ALLOCATOR(NonCopyableClass, AZ::SystemAllocator);
  4553. NonCopyableClass() = default;
  4554. NonCopyableClass(const NonCopyableClass&) = delete;
  4555. NonCopyableClass& operator=(const NonCopyableClass&) = delete;
  4556. static void Reflect(ReflectContext* context)
  4557. {
  4558. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  4559. {
  4560. serializeContext->Class<NonCopyableClass>();
  4561. }
  4562. }
  4563. };
  4564. protected:
  4565. struct NonReflectedClass
  4566. {
  4567. AZ_TYPE_INFO(NonReflectedClass, "{13B8CFB0-601A-4C03-BC19-4EDC71156254}");
  4568. AZ_CLASS_ALLOCATOR(NonReflectedClass, AZ::SystemAllocator);
  4569. AZ::u64 m_num;
  4570. AZStd::string m_name;
  4571. };
  4572. AZStd::unique_ptr<SerializeContext> m_serializeContext;
  4573. };
  4574. TEST_F(SerializableAnyFieldTest, EmptyAnyTest)
  4575. {
  4576. AZStd::any emptyAny;
  4577. // BINARY
  4578. AZStd::vector<char> byteBuffer;
  4579. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  4580. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_BINARY);
  4581. byteObjStream->WriteClass(&emptyAny);
  4582. byteObjStream->Finalize();
  4583. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  4584. AZStd::any readAnyData;
  4585. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, readAnyData, m_serializeContext.get());
  4586. EXPECT_TRUE(readAnyData.empty());
  4587. // JSON
  4588. byteBuffer.clear();
  4589. IO::ByteContainerStream<AZStd::vector<char> > jsonStream(&byteBuffer);
  4590. ObjectStream* jsonObjStream = ObjectStream::Create(&jsonStream, *m_serializeContext, ObjectStream::ST_JSON);
  4591. jsonObjStream->WriteClass(&emptyAny);
  4592. jsonObjStream->Finalize();
  4593. jsonStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  4594. AZStd::any readAnyDataJson;
  4595. AZ::Utils::LoadObjectFromStreamInPlace(jsonStream, readAnyDataJson, m_serializeContext.get());
  4596. EXPECT_TRUE(readAnyDataJson.empty());
  4597. // JSON
  4598. byteBuffer.clear();
  4599. IO::ByteContainerStream<AZStd::vector<char> > xmlStream(&byteBuffer);
  4600. ObjectStream* xmlObjStream = ObjectStream::Create(&xmlStream, *m_serializeContext, ObjectStream::ST_XML);
  4601. xmlObjStream->WriteClass(&emptyAny);
  4602. xmlObjStream->Finalize();
  4603. xmlStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  4604. AZStd::any readAnyDataXml;
  4605. AZ::Utils::LoadObjectFromStreamInPlace(xmlStream, readAnyDataXml, m_serializeContext.get());
  4606. EXPECT_TRUE(readAnyDataXml.empty());
  4607. }
  4608. TEST_F(SerializableAnyFieldTest, MultipleContextsAnyTest)
  4609. {
  4610. SerializeTestClasses::MyClassMix obj;
  4611. obj.Set(5); // Initialize with some value
  4612. AZStd::any testData(obj);
  4613. AZStd::vector<char> byteBuffer;
  4614. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  4615. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_XML);
  4616. byteObjStream->WriteClass(&testData);
  4617. byteObjStream->Finalize();
  4618. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  4619. // create and destroy temporary context to test static context members
  4620. SerializeContext* tmpContext = aznew SerializeContext();
  4621. delete tmpContext;
  4622. AZStd::any readAnyData;
  4623. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, readAnyData, m_serializeContext.get());
  4624. EXPECT_EQ(SerializeTypeInfo<SerializeTestClasses::MyClassMix>::GetUuid(), readAnyData.type());
  4625. EXPECT_NE(nullptr, AZStd::any_cast<void>(&readAnyData));
  4626. const SerializeTestClasses::MyClassMix& anyMixRef = *AZStd::any_cast<SerializeTestClasses::MyClassMix>(&testData);
  4627. const SerializeTestClasses::MyClassMix& readAnyMixRef = *AZStd::any_cast<SerializeTestClasses::MyClassMix>(&readAnyData);
  4628. EXPECT_EQ(anyMixRef.m_dataMix, readAnyMixRef.m_dataMix);
  4629. }
  4630. TEST_F(SerializableAnyFieldTest, ReflectedFieldTest)
  4631. {
  4632. SerializeTestClasses::MyClassMix obj;
  4633. obj.Set(5); // Initialize with some value
  4634. AZStd::any testData(obj);
  4635. // BINARY
  4636. AZStd::vector<char> byteBuffer;
  4637. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  4638. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_XML);
  4639. byteObjStream->WriteClass(&testData);
  4640. byteObjStream->Finalize();
  4641. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  4642. AZStd::any readAnyData;
  4643. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, readAnyData, m_serializeContext.get());
  4644. EXPECT_EQ(SerializeTypeInfo<SerializeTestClasses::MyClassMix>::GetUuid(), readAnyData.type());
  4645. EXPECT_NE(nullptr, AZStd::any_cast<void>(&readAnyData));
  4646. const SerializeTestClasses::MyClassMix& anyMixRef = *AZStd::any_cast<SerializeTestClasses::MyClassMix>(&testData);
  4647. const SerializeTestClasses::MyClassMix& readAnyMixRef = *AZStd::any_cast<SerializeTestClasses::MyClassMix>(&readAnyData);
  4648. EXPECT_EQ(anyMixRef.m_dataMix, readAnyMixRef.m_dataMix);
  4649. }
  4650. TEST_F(SerializableAnyFieldTest, NonReflectedFieldTest)
  4651. {
  4652. NonReflectedClass notReflected;
  4653. notReflected.m_num = 17;
  4654. notReflected.m_name = "Test";
  4655. AZStd::any testData(notReflected);
  4656. // BINARY
  4657. AZStd::vector<char> byteBuffer;
  4658. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  4659. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_BINARY);
  4660. AZ_TEST_START_TRACE_SUPPRESSION;
  4661. byteObjStream->WriteClass(&testData);
  4662. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  4663. byteObjStream->Finalize();
  4664. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  4665. AZStd::any readAnyData;
  4666. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, readAnyData, m_serializeContext.get());
  4667. EXPECT_EQ(AZ::Uuid::CreateNull(), readAnyData.type());
  4668. EXPECT_TRUE(readAnyData.empty());
  4669. }
  4670. TEST_F(SerializableAnyFieldTest, EnumerateFieldTest)
  4671. {
  4672. SerializeTestClasses::MyClassMix obj;
  4673. obj.m_dataMix = 5.;
  4674. m_serializeContext->EnumerateObject(&obj,
  4675. [](void* classPtr, const SerializeContext::ClassData* classData, const SerializeContext::ClassElement*)
  4676. {
  4677. if (classData->m_typeId == azrtti_typeid<SerializeTestClasses::MyClassMix>())
  4678. {
  4679. auto mixinClassPtr = reinterpret_cast<SerializeTestClasses::MyClassMix*>(classPtr);
  4680. EXPECT_NE(nullptr, mixinClassPtr);
  4681. EXPECT_DOUBLE_EQ(5.0, mixinClassPtr->m_dataMix);
  4682. }
  4683. return true;
  4684. },
  4685. []() -> bool
  4686. {
  4687. return true;
  4688. },
  4689. SerializeContext::ENUM_ACCESS_FOR_READ);
  4690. }
  4691. TEST_F(SerializableAnyFieldTest, MemberFieldTest)
  4692. {
  4693. SerializeTestClasses::MyClassMix mixedClass;
  4694. mixedClass.m_enum = MyClassBase3::Option3;
  4695. AnyMemberClass anyWrapper;
  4696. anyWrapper.m_any = AZStd::any(mixedClass);
  4697. // BINARY
  4698. AZStd::vector<char> byteBuffer;
  4699. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  4700. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_BINARY);
  4701. byteObjStream->WriteClass(&anyWrapper);
  4702. byteObjStream->Finalize();
  4703. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  4704. AnyMemberClass readAnyWrapper;
  4705. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, readAnyWrapper, m_serializeContext.get());
  4706. EXPECT_EQ(SerializeTypeInfo<SerializeTestClasses::MyClassMix>::GetUuid(), readAnyWrapper.m_any.type());
  4707. EXPECT_NE(nullptr, AZStd::any_cast<void>(&readAnyWrapper.m_any));
  4708. auto* readMixedClass = AZStd::any_cast<SerializeTestClasses::MyClassMix>(&readAnyWrapper.m_any);
  4709. EXPECT_NE(nullptr, readMixedClass);
  4710. EXPECT_EQ(MyClassBase3::Option3, readMixedClass->m_enum);
  4711. SerializeTestClasses::MyClassMix& anyMixRef = *AZStd::any_cast<SerializeTestClasses::MyClassMix>(&anyWrapper.m_any);
  4712. EXPECT_EQ(anyMixRef, *readMixedClass);
  4713. }
  4714. TEST_F(SerializableAnyFieldTest, AZStdStringFieldTest)
  4715. {
  4716. AZStd::string test("Canvas");
  4717. AZStd::any anyString(test);
  4718. // BINARY
  4719. AZStd::vector<char> byteBuffer;
  4720. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  4721. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_BINARY);
  4722. byteObjStream->WriteClass(&anyString);
  4723. byteObjStream->Finalize();
  4724. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  4725. AZStd::any readAnyString;
  4726. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, readAnyString, m_serializeContext.get());
  4727. EXPECT_EQ(azrtti_typeid<AZStd::string>(), readAnyString.type());
  4728. auto* serializedString = AZStd::any_cast<AZStd::string>(&readAnyString);
  4729. EXPECT_NE(nullptr, serializedString);
  4730. EXPECT_EQ(test, *serializedString);
  4731. }
  4732. TEST_F(SerializableAnyFieldTest, AZStdSmartPtrFieldTest)
  4733. {
  4734. /*
  4735. //For some reason that the static_assert inside of AZStd::any about only being able to be constructed with a copyable type
  4736. //or move only type is firing when attempting to move a unique_ptr into it.
  4737. {
  4738. auto testUniquePtr = AZStd::make_unique<ReflectedString>();
  4739. testUniquePtr->m_name = "Script";
  4740. AZStd::any anySmartPtr(AZStd::make_unique<ReflectedString>());
  4741. // BINARY
  4742. AZStd::vector<char> byteBuffer;
  4743. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  4744. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_BINARY);
  4745. byteObjStream->WriteClass(&anySmartPtr);
  4746. byteObjStream->Finalize();
  4747. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  4748. AZStd::any readAnySmartPtr;
  4749. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, readAnySmartPtr, m_serializeContext.get());
  4750. EXPECT_EQ(azrtti_typeid<AZStd::unique_ptr<ReflectedString>>(), readAnySmartPtr.type());
  4751. auto uniquePtrAny = AZStd::any_cast<AZStd::unique_ptr<ReflectedString>>(&readAnySmartPtr);
  4752. EXPECT_NE(nullptr, *uniquePtrAny);
  4753. auto testUniquePtrAny = AZStd::any_cast<AZStd::unique_ptr<ReflectedString>>(&anySmartPtr);
  4754. EXPECT_EQ((*testUniquePtrAny)->m_name, (*uniquePtrAny)->m_name);
  4755. }
  4756. */
  4757. {
  4758. auto testSharedPtr = AZStd::make_shared<ReflectedString>();
  4759. testSharedPtr->m_name = "Canvas";
  4760. AZStd::any anySmartPtr(testSharedPtr);
  4761. // BINARY
  4762. AZStd::vector<char> byteBuffer;
  4763. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  4764. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_BINARY);
  4765. byteObjStream->WriteClass(&anySmartPtr);
  4766. byteObjStream->Finalize();
  4767. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  4768. AZStd::any readAnySmartPtr;
  4769. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, readAnySmartPtr, m_serializeContext.get());
  4770. EXPECT_EQ(azrtti_typeid<AZStd::shared_ptr<ReflectedString>>(), readAnySmartPtr.type());
  4771. auto sharedPtrAny = AZStd::any_cast<AZStd::shared_ptr<ReflectedString>>(&readAnySmartPtr);
  4772. EXPECT_NE(nullptr, *sharedPtrAny);
  4773. EXPECT_EQ(testSharedPtr->m_name, (*sharedPtrAny)->m_name);
  4774. }
  4775. }
  4776. TEST_F(SerializableAnyFieldTest, ReflectedPointerFieldTest)
  4777. {
  4778. SerializeTestClasses::MyClassMix obj;
  4779. obj.Set(26); // Initialize with some value
  4780. AZStd::any testData(&obj);
  4781. // BINARY
  4782. AZStd::vector<char> byteBuffer;
  4783. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  4784. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_BINARY);
  4785. byteObjStream->WriteClass(&testData);
  4786. byteObjStream->Finalize();
  4787. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  4788. AZStd::any readAnyData;
  4789. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, readAnyData, m_serializeContext.get());
  4790. EXPECT_EQ(SerializeTypeInfo<SerializeTestClasses::MyClassMix>::GetUuid(), readAnyData.type());
  4791. EXPECT_NE(nullptr, AZStd::any_cast<void>(&readAnyData));
  4792. const SerializeTestClasses::MyClassMix* anyMixRef = AZStd::any_cast<SerializeTestClasses::MyClassMix*>(testData);
  4793. const SerializeTestClasses::MyClassMix& readAnyMixRef = *AZStd::any_cast<SerializeTestClasses::MyClassMix>(&readAnyData);
  4794. EXPECT_EQ(anyMixRef->m_dataMix, readAnyMixRef.m_dataMix);
  4795. }
  4796. TEST_F(SerializableAnyFieldTest, CreateAnyForSmartPtrWithNonCopyableSmartPtrDoesNotCrash)
  4797. {
  4798. AZStd::any nonCopyableSharedPtr = m_serializeContext->CreateAny(azrtti_typeid<AZStd::shared_ptr<NonCopyableClass>>());
  4799. EXPECT_FALSE(nonCopyableSharedPtr.empty());
  4800. }
  4801. class SerializableOptionalFixture
  4802. : public LeakDetectionFixture
  4803. {
  4804. public:
  4805. struct OptionalMemberClass
  4806. {
  4807. AZ_TYPE_INFO(OptionalMemberClass, "{6BC95A2D-FE6B-4FD8-9586-771F47C44C0B}");
  4808. AZ_CLASS_ALLOCATOR(OptionalMemberClass, AZ::SystemAllocator);
  4809. static void Reflect(ReflectContext* context)
  4810. {
  4811. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  4812. {
  4813. serializeContext->Class<OptionalMemberClass>()
  4814. ->Field("Optional", &OptionalMemberClass::m_optional)
  4815. ;
  4816. }
  4817. }
  4818. AZStd::optional<int> m_optional;
  4819. };
  4820. // We must expose the class for serialization first.
  4821. void SetUp() override
  4822. {
  4823. LeakDetectionFixture::SetUp();
  4824. m_serializeContext = AZStd::make_unique<SerializeContext>();
  4825. OptionalMemberClass::Reflect(m_serializeContext.get());
  4826. }
  4827. void TearDown() override
  4828. {
  4829. m_serializeContext->EnableRemoveReflection();
  4830. OptionalMemberClass::Reflect(m_serializeContext.get());
  4831. m_serializeContext.reset();
  4832. LeakDetectionFixture::TearDown();
  4833. }
  4834. protected:
  4835. AZStd::unique_ptr<SerializeContext> m_serializeContext;
  4836. };
  4837. TEST_F(SerializableOptionalFixture, TestHasValueOptionalSerialization)
  4838. {
  4839. AZStd::optional<int> theOpt {42};
  4840. AZStd::vector<char> byteBuffer;
  4841. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  4842. AZ::Utils::SaveObjectToStream(byteStream, ObjectStream::ST_XML, &theOpt, m_serializeContext.get());
  4843. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  4844. AZStd::optional<int> deserializedOptional;
  4845. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, deserializedOptional, m_serializeContext.get());
  4846. EXPECT_TRUE(deserializedOptional.has_value());
  4847. EXPECT_EQ(deserializedOptional.value(), 42);
  4848. }
  4849. TEST_F(SerializableOptionalFixture, TestNulloptOptionalSerialization)
  4850. {
  4851. AZStd::optional<int> theOpt;
  4852. AZStd::vector<char> byteBuffer;
  4853. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  4854. AZ::Utils::SaveObjectToStream(byteStream, ObjectStream::ST_XML, &theOpt, m_serializeContext.get());
  4855. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  4856. AZStd::optional<int> deserializedOptional;
  4857. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, deserializedOptional, m_serializeContext.get());
  4858. EXPECT_FALSE(deserializedOptional.has_value());
  4859. }
  4860. TEST_F(Serialization, AttributeTest)
  4861. {
  4862. const AZ::Crc32 attributeCrc = AZ_CRC("TestAttribute");
  4863. const int attributeValue = 5;
  4864. m_serializeContext->Class<SerializeTestClasses::BaseNoRtti>()
  4865. ->Attribute(attributeCrc, attributeValue)
  4866. ;
  4867. auto classData = m_serializeContext->FindClassData(azrtti_typeid<SerializeTestClasses::BaseNoRtti>());
  4868. ASSERT_NE(nullptr, classData);
  4869. auto attribute = AZ::FindAttribute(attributeCrc, classData->m_attributes);
  4870. ASSERT_NE(nullptr, attribute);
  4871. AZ::AttributeReader reader(nullptr, attribute);
  4872. int value = 0;
  4873. EXPECT_TRUE(reader.Read<int>(value));
  4874. EXPECT_EQ(attributeValue, value);
  4875. }
  4876. TEST_F(Serialization, AttributeData_WithCallableType_Succeeds)
  4877. {
  4878. static constexpr AZ::Crc32 invokableCrc = AZ_CRC_CE("Invokable");
  4879. static constexpr AZ::Crc32 nonInvokableCrc = AZ_CRC_CE("NonInvokable");
  4880. auto ReadFloat = [](SerializeTestClasses::BaseNoRtti* instance) -> float
  4881. {
  4882. auto noRttiInstance = instance;
  4883. if (!noRttiInstance)
  4884. {
  4885. ADD_FAILURE() << "BaseNoRtti instance object should not be nullptr";
  4886. return 0.0f;
  4887. }
  4888. EXPECT_FALSE(noRttiInstance->m_data);
  4889. return 2.0f;
  4890. };
  4891. m_serializeContext->Class<SerializeTestClasses::BaseNoRtti>()
  4892. ->Attribute(invokableCrc, ReadFloat)
  4893. ->Attribute(nonInvokableCrc, 4.0f)
  4894. ;
  4895. SerializeTestClasses::BaseNoRtti baseNoRttiInstance;
  4896. baseNoRttiInstance.Set();
  4897. auto classData = m_serializeContext->FindClassData(azrtti_typeid<SerializeTestClasses::BaseNoRtti>());
  4898. ASSERT_NE(nullptr, classData);
  4899. AZ::Attribute* attribute = AZ::FindAttribute(invokableCrc, classData->m_attributes);
  4900. ASSERT_NE(nullptr, attribute);
  4901. AZ::AttributeInvoker invoker(&baseNoRttiInstance, attribute);
  4902. float value = 0;
  4903. EXPECT_TRUE(invoker.Read<float>(value));
  4904. EXPECT_FLOAT_EQ(2.0f, value);
  4905. AZ::Attribute* nonInvokeAttribute = AZ::FindAttribute(nonInvokableCrc, classData->m_attributes);
  4906. ASSERT_NE(nullptr, nonInvokeAttribute);
  4907. invoker = { &baseNoRttiInstance, nonInvokeAttribute };
  4908. value = {};
  4909. EXPECT_TRUE(invoker.Read<float>(value));
  4910. EXPECT_FLOAT_EQ(4.0f, value);
  4911. }
  4912. TEST_F(Serialization, AttributeInvocable_UsingVoidPointerInstance_Succeeds)
  4913. {
  4914. static constexpr AZ::Crc32 invokableCrc = AZ_CRC_CE("Invokable");
  4915. auto ReadFloat = [](SerializeTestClasses::BaseNoRtti* instance) -> float
  4916. {
  4917. auto noRttiInstance = instance;
  4918. if (!noRttiInstance)
  4919. {
  4920. ADD_FAILURE() << "BaseNoRtti instance object should not be nullptr";
  4921. return 0.0f;
  4922. }
  4923. EXPECT_FALSE(noRttiInstance->m_data);
  4924. return 2.0f;
  4925. };
  4926. m_serializeContext->Class<SerializeTestClasses::BaseNoRtti>()
  4927. ->Attribute(invokableCrc, ReadFloat)
  4928. ;
  4929. SerializeTestClasses::BaseNoRtti baseNoRttiInstance;
  4930. baseNoRttiInstance.Set();
  4931. auto classData = m_serializeContext->FindClassData(azrtti_typeid<SerializeTestClasses::BaseNoRtti>());
  4932. ASSERT_NE(nullptr, classData);
  4933. AZ::Attribute* attribute = AZ::FindAttribute(invokableCrc, classData->m_attributes);
  4934. ASSERT_NE(nullptr, attribute);
  4935. void* instance = &baseNoRttiInstance;
  4936. auto voidAttributeInvocable = attribute->GetVoidInstanceAttributeInvocable();
  4937. AZ::AttributeReader reader(instance, voidAttributeInvocable.get());
  4938. float value = 0;
  4939. EXPECT_TRUE(reader.Read<float>(value));
  4940. EXPECT_FLOAT_EQ(2.0f, value);
  4941. }
  4942. class ObjectStreamSerialization
  4943. : public LeakDetectionFixture
  4944. {
  4945. public:
  4946. void SetUp() override
  4947. {
  4948. LeakDetectionFixture::SetUp();
  4949. m_serializeContext = AZStd::make_unique<SerializeContext>();
  4950. TemplateInstantiationReflectedWrapper::Reflect(m_serializeContext.get());
  4951. }
  4952. void TearDown() override
  4953. {
  4954. m_serializeContext->EnableRemoveReflection();
  4955. TemplateInstantiationReflectedWrapper::Reflect(m_serializeContext.get());
  4956. m_serializeContext->DisableRemoveReflection();
  4957. m_serializeContext.reset();
  4958. LeakDetectionFixture::TearDown();
  4959. }
  4960. struct TemplateInstantiationReflectedWrapper
  4961. {
  4962. AZ_TYPE_INFO(TemplateInstantiationReflectedWrapper, "{5A2F60AA-F63E-4106-BD5E-0F77E01DDBAC}");
  4963. AZ_CLASS_ALLOCATOR(TemplateInstantiationReflectedWrapper, AZ::SystemAllocator);
  4964. static void Reflect(ReflectContext* context)
  4965. {
  4966. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  4967. {
  4968. //Reflected Template classes must be reflected in one field
  4969. serializeContext->Class<TemplateInstantiationReflectedWrapper>()
  4970. ->Field("m_name", &TemplateInstantiationReflectedWrapper::m_name)
  4971. ;
  4972. }
  4973. }
  4974. AZStd::string m_name;
  4975. };
  4976. struct DeprecatedClass
  4977. {
  4978. AZ_TYPE_INFO(DeprecatedClass, "{5AB3F3C9-21D9-4AA8-84B2-9ACCC81C77B6}");
  4979. static void Reflect(ReflectContext* context)
  4980. {
  4981. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  4982. {
  4983. //Reflected Template classes must be reflected in one field
  4984. serializeContext->Class<DeprecatedClass>()
  4985. ->Field("m_value", &DeprecatedClass::m_value)
  4986. ->Field("m_testFlag", &DeprecatedClass::m_testFlag)
  4987. ;
  4988. }
  4989. }
  4990. int64_t m_value;
  4991. bool m_testFlag;
  4992. };
  4993. struct ConvertedClass
  4994. {
  4995. AZ_TYPE_INFO(ConvertedClass, "{97733A6F-98B5-4EB7-B782-9F8F69FBD581}");
  4996. static void Reflect(ReflectContext* context)
  4997. {
  4998. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  4999. {
  5000. //Reflected Template classes must be reflected in one field
  5001. serializeContext->Class<ConvertedClass>()
  5002. ->Field("m_value", &ConvertedClass::m_value)
  5003. ->Field("m_testString", &ConvertedClass::m_testString)
  5004. ;
  5005. }
  5006. }
  5007. int64_t m_value;
  5008. AZStd::string m_testString;
  5009. };
  5010. static bool DeprecatedClassConverter(SerializeContext& serializeContext, SerializeContext::DataElementNode& deprecatedNode)
  5011. {
  5012. return deprecatedNode.Convert<ConvertedClass>(serializeContext) && deprecatedNode.SetData(serializeContext, ConvertedClass{});
  5013. }
  5014. static constexpr const char* c_reflectedFieldNameTypeId{ "{78469836-4D08-42CE-AC22-B2056442D5AF}" };
  5015. static constexpr const char* c_rootReflectedClassTypeId{ "{DED0BFF5-84A8-47E5-8AFB-73B6BED56F0C}" };
  5016. static constexpr unsigned int c_reflectedFieldNameVersion{ 0 };
  5017. // Wraps a DeprecatedClass element that gets written to an ObjectStream
  5018. // and but loaded with a version change using the same typeid into a structure
  5019. // that no longer contains the deprecated class field
  5020. struct ReflectedFieldNameOldVersion1
  5021. {
  5022. AZ_TYPE_INFO(ReflectedFieldNameOldVersion1, c_reflectedFieldNameTypeId);
  5023. static void Reflect(ReflectContext* context)
  5024. {
  5025. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  5026. {
  5027. //Reflected Template classes must be reflected in one field
  5028. serializeContext->Class<ReflectedFieldNameOldVersion1>()
  5029. ->Version(c_reflectedFieldNameVersion)
  5030. ->Field("m_deprecatedElement", &ReflectedFieldNameOldVersion1::m_deprecatedElement)
  5031. ;
  5032. }
  5033. }
  5034. DeprecatedClass m_deprecatedElement;
  5035. };
  5036. struct ReflectedFieldNameNewVersion1
  5037. {
  5038. AZ_TYPE_INFO(ReflectedFieldNameNewVersion1, c_reflectedFieldNameTypeId);
  5039. static void Reflect(ReflectContext* context)
  5040. {
  5041. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  5042. {
  5043. //Reflected Template classes must be reflected in one field
  5044. serializeContext->Class<ReflectedFieldNameNewVersion1>()
  5045. ->Version(c_reflectedFieldNameVersion)
  5046. ->Field("newElement", &ReflectedFieldNameNewVersion1::m_newElement)
  5047. ;
  5048. }
  5049. }
  5050. int m_newElement{};
  5051. };
  5052. struct RootFieldNameV1
  5053. {
  5054. AZ_TYPE_INFO(RootFieldNameV1, c_rootReflectedClassTypeId);
  5055. static void Reflect(ReflectContext* context)
  5056. {
  5057. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  5058. {
  5059. //Reflected Template classes must be reflected in one field
  5060. serializeContext->Class<RootFieldNameV1>()
  5061. ->Version(c_reflectedFieldNameVersion)
  5062. ->Field("m_reflectedField", &RootFieldNameV1::m_reflectedField)
  5063. ->Field("m_rootName", &RootFieldNameV1::m_rootName)
  5064. ;
  5065. }
  5066. }
  5067. ReflectedFieldNameOldVersion1 m_reflectedField;
  5068. AZStd::string m_rootName;
  5069. };
  5070. struct RootFieldNameV2
  5071. {
  5072. AZ_TYPE_INFO(RootFieldNameV2, c_rootReflectedClassTypeId);
  5073. static void Reflect(ReflectContext* context)
  5074. {
  5075. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  5076. {
  5077. //Reflected Template classes must be reflected in one field
  5078. serializeContext->Class<RootFieldNameV2>()
  5079. ->Version(c_reflectedFieldNameVersion)
  5080. ->Field("m_reflectedField", &RootFieldNameV2::m_reflectedField)
  5081. ->Field("m_rootName", &RootFieldNameV2::m_rootName)
  5082. ;
  5083. }
  5084. }
  5085. ReflectedFieldNameNewVersion1 m_reflectedField;
  5086. AZStd::string m_rootName;
  5087. };
  5088. struct RootElementMemoryTracker
  5089. {
  5090. AZ_TYPE_INFO(RootElementMemoryTracker, "{772D354F-F6EB-467F-8FA7-9086DDD58324}");
  5091. AZ_CLASS_ALLOCATOR(RootElementMemoryTracker, AZ::SystemAllocator);
  5092. RootElementMemoryTracker()
  5093. {
  5094. ++s_allocatedInstance;
  5095. }
  5096. ~RootElementMemoryTracker()
  5097. {
  5098. --s_allocatedInstance;
  5099. }
  5100. static void Reflect(ReflectContext* context)
  5101. {
  5102. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  5103. {
  5104. //Reflected Template classes must be reflected in one field
  5105. serializeContext->Class<RootElementMemoryTracker>();
  5106. }
  5107. }
  5108. static int32_t s_allocatedInstance;
  5109. };
  5110. protected:
  5111. AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
  5112. };
  5113. int32_t ObjectStreamSerialization::RootElementMemoryTracker::s_allocatedInstance;
  5114. TEST_F(ObjectStreamSerialization, NewerVersionThanSupportedTest)
  5115. {
  5116. AZStd::string loadString;
  5117. // Set the object stream version to numeric_limits<AZ::u32>::max() "4294967295"
  5118. {
  5119. AZStd::string_view versionMaxStringXml = R"(<ObjectStream version="4294967295">
  5120. <Class name="AZStd::string" field="Name" type="{EF8FF807-DDEE-4EB0-B678-4CA3A2C490A4}" value="Test" specializationTypeId="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
  5121. </ObjectStream>
  5122. )";
  5123. AZ::IO::MemoryStream versionMaxStream(versionMaxStringXml.data(), versionMaxStringXml.size());
  5124. AZ_TEST_START_TRACE_SUPPRESSION;
  5125. bool result = AZ::Utils::LoadObjectFromStreamInPlace(versionMaxStream, loadString, m_serializeContext.get());
  5126. EXPECT_FALSE(result);
  5127. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  5128. EXPECT_EQ("", loadString);
  5129. }
  5130. {
  5131. AZStd::string_view versionMaxStringJson = R"({
  5132. "name": "ObjectStream",
  5133. "version": 4294967295,
  5134. "Objects": [
  5135. {
  5136. "field": "m_textData",
  5137. "typeName": "AZStd::string",
  5138. "typeId": "{EF8FF807-DDEE-4EB0-B678-4CA3A2C490A4}",
  5139. "specializationTypeId": "{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}",
  5140. "value": "Test"
  5141. }
  5142. ]
  5143. })";
  5144. AZ::IO::MemoryStream versionMaxStream(versionMaxStringJson.data(), versionMaxStringJson.size());
  5145. AZ_TEST_START_TRACE_SUPPRESSION;
  5146. bool result = AZ::Utils::LoadObjectFromStreamInPlace(versionMaxStream, loadString, m_serializeContext.get());
  5147. EXPECT_FALSE(result);
  5148. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  5149. EXPECT_EQ("", loadString);
  5150. }
  5151. {
  5152. AZStd::string_view versionMaxStringBinary = "00FFFFFFFF18EF8FF807DDEE4EB0B6784CA3A2C490A40000";
  5153. AZStd::vector<AZ::u8> byteArray;
  5154. AZ::IO::ByteContainerStream<AZStd::vector<AZ::u8>> binaryStream(&byteArray);
  5155. AZStd::unique_ptr<AZ::SerializeContext::IDataSerializer> binarySerializer = AZStd::make_unique<AZ::Internal::AZByteStream<AZStd::allocator>>();
  5156. binarySerializer->TextToData(versionMaxStringBinary.data(), 0, binaryStream);
  5157. binarySerializer.reset();
  5158. binaryStream.Seek(0, AZ::IO::GenericStream::SeekMode::ST_SEEK_BEGIN);
  5159. AZ_TEST_START_TRACE_SUPPRESSION;
  5160. bool result = AZ::Utils::LoadObjectFromStreamInPlace(binaryStream, loadString, m_serializeContext.get());
  5161. EXPECT_FALSE(result);
  5162. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  5163. EXPECT_EQ("", loadString);
  5164. }
  5165. }
  5166. TEST_F(ObjectStreamSerialization, V1ToCurrentVersionTest)
  5167. {
  5168. // Set the object stream version to "1"
  5169. {
  5170. TemplateInstantiationReflectedWrapper loadXmlWrapper;
  5171. AZStd::string_view versionStringXml = R"(<ObjectStream version="1">
  5172. <Class name="TemplateInstantiationReflectedWrapper" type="{5A2F60AA-F63E-4106-BD5E-0F77E01DDBAC}">
  5173. <Class name="AZStd::string" field="m_name" type="{EF8FF807-DDEE-4EB0-B678-4CA3A2C490A4}" value="Test"/>
  5174. </Class>
  5175. </ObjectStream>
  5176. )";
  5177. AZ::IO::MemoryStream versionStream(versionStringXml.data(), versionStringXml.size());
  5178. AZ::Utils::LoadObjectFromStreamInPlace(versionStream, loadXmlWrapper, m_serializeContext.get());
  5179. EXPECT_EQ("Test", loadXmlWrapper.m_name);
  5180. }
  5181. {
  5182. TemplateInstantiationReflectedWrapper loadJsonWrapper;
  5183. AZStd::string_view versionStringJson = R"({
  5184. "name": "ObjectStream",
  5185. "version": 1,
  5186. "Objects": [
  5187. {
  5188. "typeName": "TemplateInstantiationReflectedWrapper",
  5189. "typeId": "{5A2F60AA-F63E-4106-BD5E-0F77E01DDBAC}",
  5190. "Objects": [
  5191. {
  5192. "field": "m_name",
  5193. "typeName": "AZStd::string",
  5194. "typeId": "{EF8FF807-DDEE-4EB0-B678-4CA3A2C490A4}",
  5195. "value": "Test"
  5196. }
  5197. ]
  5198. }
  5199. ]
  5200. })";
  5201. AZ::IO::MemoryStream versionStream(versionStringJson.data(), versionStringJson.size());
  5202. AZ::Utils::LoadObjectFromStreamInPlace(versionStream, loadJsonWrapper, m_serializeContext.get());
  5203. EXPECT_EQ("Test", loadJsonWrapper.m_name);
  5204. }
  5205. {
  5206. TemplateInstantiationReflectedWrapper loadBinaryWrapper;
  5207. AZStd::string_view version1StringBinary = "0000000001085A2F60AAF63E4106BD5E0F77E01DDBAC5CC08C4427EF8FF807DDEE4EB0B6784CA3A2C490A454657374000000";
  5208. AZStd::vector<AZ::u8> byteArray;
  5209. AZ::IO::ByteContainerStream<AZStd::vector<AZ::u8>> binaryStream(&byteArray);
  5210. AZStd::unique_ptr<AZ::SerializeContext::IDataSerializer> binarySerializer = AZStd::make_unique<AZ::Internal::AZByteStream<AZStd::allocator>>();
  5211. binarySerializer->TextToData(version1StringBinary.data(), 0, binaryStream);
  5212. binarySerializer.reset();
  5213. binaryStream.Seek(0, AZ::IO::GenericStream::SeekMode::ST_SEEK_BEGIN);
  5214. AZ::Utils::LoadObjectFromStreamInPlace(binaryStream, loadBinaryWrapper, m_serializeContext.get());
  5215. EXPECT_EQ("Test", loadBinaryWrapper.m_name);
  5216. }
  5217. }
  5218. TEST_F(ObjectStreamSerialization, V2ToCurrentVersionTest)
  5219. {
  5220. AZStd::string loadJsonString;
  5221. // Set the object stream version to "2"
  5222. {
  5223. AZStd::string_view version2StringXml = R"(<ObjectStream version="2">
  5224. <Class name="AZStd::string" type="{EF8FF807-DDEE-4EB0-B678-4CA3A2C490A4}" value="Test" specializationTypeId="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
  5225. </ObjectStream>
  5226. )";
  5227. AZ::IO::MemoryStream version2Stream(version2StringXml.data(), version2StringXml.size());
  5228. AZ::Utils::LoadObjectFromStreamInPlace(version2Stream, loadJsonString, m_serializeContext.get());
  5229. }
  5230. EXPECT_EQ("Test", loadJsonString);
  5231. AZStd::string loadXmlString;
  5232. {
  5233. AZStd::string_view version2StringJson = R"({
  5234. "name": "ObjectStream",
  5235. "version": 2,
  5236. "Objects": [
  5237. {
  5238. "typeName": "AZStd::string",
  5239. "typeId": "{EF8FF807-DDEE-4EB0-B678-4CA3A2C490A4}",
  5240. "specializationTypeId": "{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}",
  5241. "value": "Test"
  5242. }
  5243. ]
  5244. })";
  5245. AZ::IO::MemoryStream version2Stream(version2StringJson.data(), version2StringJson.size());
  5246. AZ::Utils::LoadObjectFromStreamInPlace(version2Stream, loadXmlString, m_serializeContext.get());
  5247. }
  5248. EXPECT_EQ("Test", loadXmlString);
  5249. AZStd::string testString = "Test";
  5250. AZStd::vector<AZ::u8> stringArray;
  5251. AZ::IO::ByteContainerStream<AZStd::vector<AZ::u8>> byteStream(&stringArray);
  5252. AZ::Utils::SaveObjectToStream(byteStream, AZ::DataStream::ST_BINARY, &testString, m_serializeContext.get());
  5253. AZStd::string loadBinaryString;
  5254. {
  5255. AZStd::string_view version2StringBinary = "00000000021CEF8FF807DDEE4EB0B6784CA3A2C490A403AAAB3F5C475A669EBCD5FA4DB353C9546573740000";
  5256. AZStd::vector<AZ::u8> byteArray;
  5257. AZ::IO::ByteContainerStream<AZStd::vector<AZ::u8>> binaryStream(&byteArray);
  5258. AZStd::unique_ptr<AZ::SerializeContext::IDataSerializer> binarySerializer = AZStd::make_unique<AZ::Internal::AZByteStream<AZStd::allocator>>();
  5259. binarySerializer->TextToData(version2StringBinary.data(), 0, binaryStream);
  5260. binarySerializer.reset();
  5261. binaryStream.Seek(0, AZ::IO::GenericStream::SeekMode::ST_SEEK_BEGIN);
  5262. AZ::Utils::LoadObjectFromStreamInPlace(binaryStream, loadBinaryString, m_serializeContext.get());
  5263. }
  5264. EXPECT_EQ("Test", loadBinaryString);
  5265. }
  5266. TEST_F(ObjectStreamSerialization, UnreflectedChildElementAndDeprecatedClass_XmlTest)
  5267. {
  5268. // Reflect the Deprecated class and the wrapper class
  5269. // with the deprecated class as a field
  5270. DeprecatedClass::Reflect(m_serializeContext.get());
  5271. ReflectedFieldNameOldVersion1::Reflect(m_serializeContext.get());
  5272. RootFieldNameV1::Reflect(m_serializeContext.get());
  5273. ConvertedClass::Reflect(m_serializeContext.get());
  5274. RootFieldNameV1 oldDeprecatedElement;
  5275. // Test Saving and Loading XML
  5276. AZStd::vector<AZ::u8> byteBuffer;
  5277. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  5278. EXPECT_TRUE(AZ::Utils::SaveObjectToStream(byteStream, AZ::DataStream::ST_XML, &oldDeprecatedElement, m_serializeContext.get()));
  5279. // Un-reflect both the deprecated class and the wrapper class with the deprecated field
  5280. {
  5281. m_serializeContext->EnableRemoveReflection();
  5282. DeprecatedClass::Reflect(m_serializeContext.get());
  5283. ReflectedFieldNameOldVersion1::Reflect(m_serializeContext.get());
  5284. RootFieldNameV1::Reflect(m_serializeContext.get());
  5285. m_serializeContext->DisableRemoveReflection();
  5286. }
  5287. // Reflect the Deprecation Converter for the DeprecatedClass and the wrapper class
  5288. // with the converter class as a field
  5289. m_serializeContext->ClassDeprecate("DeprecatedClass", AzTypeInfo<DeprecatedClass>::Uuid(), &ObjectStreamSerialization::DeprecatedClassConverter);
  5290. ReflectedFieldNameNewVersion1::Reflect(m_serializeContext.get());
  5291. RootFieldNameV2::Reflect(m_serializeContext.get());
  5292. byteStream.Seek(0, AZ::IO::GenericStream::SeekMode::ST_SEEK_BEGIN);
  5293. RootFieldNameV2 newConvertedElement;
  5294. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, newConvertedElement, m_serializeContext.get());
  5295. // Un-reflect remaining classes
  5296. {
  5297. m_serializeContext->EnableRemoveReflection();
  5298. ConvertedClass::Reflect(m_serializeContext.get());
  5299. m_serializeContext->ClassDeprecate("DeprecatedClass", AzTypeInfo<DeprecatedClass>::Uuid(), &ObjectStreamSerialization::DeprecatedClassConverter);
  5300. ReflectedFieldNameNewVersion1::Reflect(m_serializeContext.get());
  5301. RootFieldNameV2::Reflect(m_serializeContext.get());
  5302. m_serializeContext->DisableRemoveReflection();
  5303. }
  5304. }
  5305. TEST_F(ObjectStreamSerialization, UnreflectedChildElementAndDeprecatedClass_BinaryTest)
  5306. {
  5307. // Reflect the Deprecated class and the wrapper class
  5308. // with the deprecated class as a field
  5309. DeprecatedClass::Reflect(m_serializeContext.get());
  5310. ReflectedFieldNameOldVersion1::Reflect(m_serializeContext.get());
  5311. RootFieldNameV1::Reflect(m_serializeContext.get());
  5312. ConvertedClass::Reflect(m_serializeContext.get());
  5313. RootFieldNameV1 oldDeprecatedElement;
  5314. // Test Saving and Loading XML
  5315. AZStd::vector<AZ::u8> byteBuffer;
  5316. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  5317. EXPECT_TRUE(AZ::Utils::SaveObjectToStream(byteStream, AZ::DataStream::ST_BINARY, &oldDeprecatedElement, m_serializeContext.get()));
  5318. // Un-reflect both the deprecated class and the wrapper class with the deprecated field
  5319. {
  5320. m_serializeContext->EnableRemoveReflection();
  5321. DeprecatedClass::Reflect(m_serializeContext.get());
  5322. ReflectedFieldNameOldVersion1::Reflect(m_serializeContext.get());
  5323. RootFieldNameV1::Reflect(m_serializeContext.get());
  5324. m_serializeContext->DisableRemoveReflection();
  5325. }
  5326. // Reflect the Deprecation Converter for the DeprecatedClass and the wrapper class
  5327. // with the converter class as a field
  5328. m_serializeContext->ClassDeprecate("DeprecatedClass", AzTypeInfo<DeprecatedClass>::Uuid(), &ObjectStreamSerialization::DeprecatedClassConverter);
  5329. ReflectedFieldNameNewVersion1::Reflect(m_serializeContext.get());
  5330. RootFieldNameV2::Reflect(m_serializeContext.get());
  5331. byteStream.Seek(0, AZ::IO::GenericStream::SeekMode::ST_SEEK_BEGIN);
  5332. RootFieldNameV2 newConvertedElement;
  5333. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, newConvertedElement, m_serializeContext.get());
  5334. // Un-reflect remaining classes
  5335. {
  5336. m_serializeContext->EnableRemoveReflection();
  5337. ConvertedClass::Reflect(m_serializeContext.get());
  5338. m_serializeContext->ClassDeprecate("DeprecatedClass", AzTypeInfo<DeprecatedClass>::Uuid(), &ObjectStreamSerialization::DeprecatedClassConverter);
  5339. ReflectedFieldNameNewVersion1::Reflect(m_serializeContext.get());
  5340. RootFieldNameV2::Reflect(m_serializeContext.get());
  5341. m_serializeContext->DisableRemoveReflection();
  5342. }
  5343. }
  5344. TEST_F(ObjectStreamSerialization, UnreflectedChildElementAndDeprecatedClass_JSONTest)
  5345. {
  5346. // Reflect the Deprecated class and the wrapper class
  5347. // with the deprecated class as a field
  5348. DeprecatedClass::Reflect(m_serializeContext.get());
  5349. ReflectedFieldNameOldVersion1::Reflect(m_serializeContext.get());
  5350. RootFieldNameV1::Reflect(m_serializeContext.get());
  5351. ConvertedClass::Reflect(m_serializeContext.get());
  5352. RootFieldNameV1 oldDeprecatedElement;
  5353. // Test Saving and Loading XML
  5354. AZStd::vector<AZ::u8> byteBuffer;
  5355. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  5356. EXPECT_TRUE(AZ::Utils::SaveObjectToStream(byteStream, AZ::DataStream::ST_JSON, &oldDeprecatedElement, m_serializeContext.get()));
  5357. // Un-reflect both the deprecated class and the wrapper class with the deprecated field
  5358. {
  5359. m_serializeContext->EnableRemoveReflection();
  5360. DeprecatedClass::Reflect(m_serializeContext.get());
  5361. ReflectedFieldNameOldVersion1::Reflect(m_serializeContext.get());
  5362. RootFieldNameV1::Reflect(m_serializeContext.get());
  5363. m_serializeContext->DisableRemoveReflection();
  5364. }
  5365. // Reflect the Deprecation Converter for the DeprecatedClass and the wrapper class
  5366. // with the converter class as a field
  5367. m_serializeContext->ClassDeprecate("DeprecatedClass", AzTypeInfo<DeprecatedClass>::Uuid(), &ObjectStreamSerialization::DeprecatedClassConverter);
  5368. ReflectedFieldNameNewVersion1::Reflect(m_serializeContext.get());
  5369. RootFieldNameV2::Reflect(m_serializeContext.get());
  5370. byteStream.Seek(0, AZ::IO::GenericStream::SeekMode::ST_SEEK_BEGIN);
  5371. RootFieldNameV2 newConvertedElement;
  5372. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, newConvertedElement, m_serializeContext.get());
  5373. // Un-reflect remaining classes
  5374. {
  5375. m_serializeContext->EnableRemoveReflection();
  5376. ConvertedClass::Reflect(m_serializeContext.get());
  5377. m_serializeContext->ClassDeprecate("DeprecatedClass", AzTypeInfo<DeprecatedClass>::Uuid(), &ObjectStreamSerialization::DeprecatedClassConverter);
  5378. ReflectedFieldNameNewVersion1::Reflect(m_serializeContext.get());
  5379. RootFieldNameV1::Reflect(m_serializeContext.get());
  5380. m_serializeContext->DisableRemoveReflection();
  5381. }
  5382. }
  5383. // Prove that if a member of a vector of baseclass pointers is unreadable, the container
  5384. // removes the element instead of leaving a null. This is an arbitrary choice (to remove or leave
  5385. // the null) and this test exists just to prove that the chosen way functions as expected.
  5386. TEST_F(ObjectStreamSerialization, UnreadableVectorElements_LeaveNoGaps_Errors)
  5387. {
  5388. using namespace ContainerElementDeprecationTestData;
  5389. // make sure that when a component is deprecated, it is removed during deserialization
  5390. // and does not leave a hole that is a nullptr.
  5391. ClassWithAVectorOfBaseClasses::Reflect(m_serializeContext.get());
  5392. ClassWithAVectorOfBaseClasses vectorContainer;
  5393. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass1());
  5394. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass2());
  5395. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass1());
  5396. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass2());
  5397. AZStd::vector<char> charBuffer;
  5398. AZ::IO::ByteContainerStream<AZStd::vector<char> > containerStream(&charBuffer);
  5399. bool success = AZ::Utils::SaveObjectToStream(containerStream, AZ::ObjectStream::ST_XML, &vectorContainer, m_serializeContext.get());
  5400. EXPECT_TRUE(success);
  5401. // (remove it, but without deprecating)
  5402. m_serializeContext->EnableRemoveReflection();
  5403. DerivedClass2::Reflect(m_serializeContext.get());
  5404. m_serializeContext->DisableRemoveReflection();
  5405. // load it, we expect errors:
  5406. ClassWithAVectorOfBaseClasses loadedContainer;
  5407. AZ_TEST_START_TRACE_SUPPRESSION;
  5408. success = AZ::Utils::LoadObjectFromBufferInPlace(charBuffer.data(), charBuffer.size(), loadedContainer, m_serializeContext.get());
  5409. AZ_TEST_STOP_TRACE_SUPPRESSION(2); // 2 classes should have failed and generated warnings/errors
  5410. EXPECT_TRUE(success);
  5411. EXPECT_EQ(loadedContainer.m_vectorOfBaseClasses.size(), 2); // we still preserve the ones we CAN read.
  5412. for (auto baseclass : loadedContainer.m_vectorOfBaseClasses)
  5413. {
  5414. // we should only have baseclass1's in there.
  5415. EXPECT_EQ(baseclass->RTTI_GetType(), azrtti_typeid<DerivedClass1>());
  5416. }
  5417. }
  5418. // Prove that if you properly deprecate a member of a vector of baseclass pointers, the container
  5419. // removes the element instead of leaving a null and does not emit an error
  5420. TEST_F(ObjectStreamSerialization, DeprecatedVectorElements_LeaveNoGaps_DoesNotError)
  5421. {
  5422. using namespace ContainerElementDeprecationTestData;
  5423. // make sure that when a component is deprecated, it is removed during deserialization,
  5424. // and does not leave a hole that is a nullptr.
  5425. ClassWithAVectorOfBaseClasses::Reflect(m_serializeContext.get());
  5426. ClassWithAVectorOfBaseClasses vectorContainer;
  5427. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass1());
  5428. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass2());
  5429. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass1());
  5430. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass2());
  5431. AZStd::vector<char> charBuffer;
  5432. AZ::IO::ByteContainerStream<AZStd::vector<char> > containerStream(&charBuffer);
  5433. bool success = AZ::Utils::SaveObjectToStream(containerStream, AZ::ObjectStream::ST_XML, &vectorContainer, m_serializeContext.get());
  5434. EXPECT_TRUE(success);
  5435. // remove it and properly deprecate it
  5436. m_serializeContext->EnableRemoveReflection();
  5437. DerivedClass2::Reflect(m_serializeContext.get());
  5438. m_serializeContext->DisableRemoveReflection();
  5439. m_serializeContext->ClassDeprecate("Dummy UUID", azrtti_typeid<DerivedClass2>());
  5440. ClassWithAVectorOfBaseClasses loadedContainer;
  5441. // it should generate no warnings but the deprecated ones should not be there.
  5442. success = AZ::Utils::LoadObjectFromBufferInPlace(charBuffer.data(), charBuffer.size(), loadedContainer, m_serializeContext.get());
  5443. EXPECT_TRUE(success);
  5444. EXPECT_EQ(loadedContainer.m_vectorOfBaseClasses.size(), 2); // we still preserve the ones we CAN read.
  5445. for (auto baseclass : loadedContainer.m_vectorOfBaseClasses)
  5446. {
  5447. // we should only have baseclass1's in there.
  5448. EXPECT_EQ(baseclass->RTTI_GetType(), azrtti_typeid<DerivedClass1>());
  5449. }
  5450. }
  5451. // Prove that if you deprecate but upgrade a member of a vector of baseclass pointers, the container
  5452. // contains the freshly upgraded element instead of leaving a null and does not emit an error
  5453. TEST_F(ObjectStreamSerialization, DeprecatedVectorElements_ConvertedClass_DoesNotError_DoesNotDiscardData)
  5454. {
  5455. using namespace ContainerElementDeprecationTestData;
  5456. // make sure that when a component is deprecated, it is removed during deserialization
  5457. // and does not leave a hole that is a nullptr.
  5458. ClassWithAVectorOfBaseClasses::Reflect(m_serializeContext.get());
  5459. ClassWithAVectorOfBaseClasses vectorContainer;
  5460. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass1());
  5461. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass2());
  5462. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass1());
  5463. vectorContainer.m_vectorOfBaseClasses.push_back(new DerivedClass2());
  5464. AZStd::vector<char> charBuffer;
  5465. AZ::IO::ByteContainerStream<AZStd::vector<char> > containerStream(&charBuffer);
  5466. bool success = AZ::Utils::SaveObjectToStream(containerStream, AZ::ObjectStream::ST_XML, &vectorContainer, m_serializeContext.get());
  5467. EXPECT_TRUE(success);
  5468. // remove it and properly deprecate it with a converter that will upgrade it.
  5469. m_serializeContext->EnableRemoveReflection();
  5470. DerivedClass2::Reflect(m_serializeContext.get());
  5471. m_serializeContext->DisableRemoveReflection();
  5472. m_serializeContext->ClassDeprecate("Dummy UUID", azrtti_typeid<DerivedClass2>(), ConvertDerivedClass2ToDerivedClass3);
  5473. ClassWithAVectorOfBaseClasses loadedContainer;
  5474. // it should generate no warnings but the deprecated ones should not be there.
  5475. success = AZ::Utils::LoadObjectFromBufferInPlace(charBuffer.data(), charBuffer.size(), loadedContainer, m_serializeContext.get());
  5476. EXPECT_TRUE(success);
  5477. ASSERT_EQ(loadedContainer.m_vectorOfBaseClasses.size(), 4); // we still preserve the ones we CAN read.
  5478. // this also proves it does not shuffle elements around.
  5479. EXPECT_EQ(loadedContainer.m_vectorOfBaseClasses[0]->RTTI_GetType(), azrtti_typeid<DerivedClass1>());
  5480. EXPECT_EQ(loadedContainer.m_vectorOfBaseClasses[1]->RTTI_GetType(), azrtti_typeid<DerivedClass3>());
  5481. EXPECT_EQ(loadedContainer.m_vectorOfBaseClasses[2]->RTTI_GetType(), azrtti_typeid<DerivedClass1>());
  5482. EXPECT_EQ(loadedContainer.m_vectorOfBaseClasses[3]->RTTI_GetType(), azrtti_typeid<DerivedClass3>());
  5483. }
  5484. TEST_F(ObjectStreamSerialization, LoadObjectFromStreamInPlaceFailureDoesNotLeak)
  5485. {
  5486. RootElementMemoryTracker::Reflect(m_serializeContext.get());
  5487. AZStd::vector<AZ::u8> byteBuffer;
  5488. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  5489. {
  5490. RootElementMemoryTracker saveTracker;
  5491. EXPECT_TRUE(AZ::Utils::SaveObjectToStream(byteStream, AZ::DataStream::ST_BINARY, &saveTracker, m_serializeContext.get()));
  5492. byteStream.Seek(0, AZ::IO::GenericStream::SeekMode::ST_SEEK_BEGIN);
  5493. }
  5494. // Attempt to load a RootElementMemoryTracker into an int64_t
  5495. int64_t loadTracker;
  5496. AZ_TEST_START_TRACE_SUPPRESSION;
  5497. EXPECT_FALSE(AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadTracker, m_serializeContext.get()));
  5498. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  5499. EXPECT_EQ(0U, RootElementMemoryTracker::s_allocatedInstance);
  5500. }
  5501. struct EmptyDeprecatedClass
  5502. {
  5503. AZ_TYPE_INFO(EmptyDeprecatedClass, "{73890A64-9ADB-4639-B0E0-93294CE81B19}");
  5504. };
  5505. struct ConvertedNewClass
  5506. {
  5507. AZ_TYPE_INFO(ConvertedNewClass, "{BE892776-3830-43E5-873C-38A1CA6EF4BB}");
  5508. int32_t m_value{ 5 };
  5509. };
  5510. struct AggregateTestClassV1
  5511. {
  5512. AZ_TYPE_INFO(AggregateTestClassV1, "{088E3B16-4D93-4116-A747-706BE132AF5F}");
  5513. EmptyDeprecatedClass m_testField;
  5514. AZ::Vector3 m_position = AZ::Vector3::CreateZero();
  5515. EmptyDeprecatedClass m_value;
  5516. };
  5517. struct AggregateTestClassV2
  5518. {
  5519. // AggregateTestClassV2 Uuid should match version 1, It isn't the class that
  5520. // is being converted, but it's m_value that is.
  5521. AZ_TYPE_INFO(AggregateTestClassV2, "{088E3B16-4D93-4116-A747-706BE132AF5F}");
  5522. ConvertedNewClass m_testField;
  5523. AZ::Vector3 m_position = AZ::Vector3::CreateZero();
  5524. ConvertedNewClass m_value;
  5525. };
  5526. TEST_F(ObjectStreamSerialization, LoadNonDeprecatedElement_FollowedByZeroSizeDeprecatedElement_DoesNotAssert)
  5527. {
  5528. m_serializeContext->Class<EmptyDeprecatedClass>();
  5529. m_serializeContext->Class<AggregateTestClassV1>()
  5530. ->Field("m_testField", &AggregateTestClassV1::m_testField)
  5531. ->Field("m_position", &AggregateTestClassV1::m_position)
  5532. ->Field("m_value", &AggregateTestClassV1::m_value)
  5533. ;
  5534. // Write out AggrgateTestClassV1 instance
  5535. AggregateTestClassV1 testData;
  5536. testData.m_position = AZ::Vector3(1.0f, 2.0f, 3.0f);
  5537. AZStd::vector<AZ::u8> byteBuffer;
  5538. AZ::IO::ByteContainerStream<decltype(byteBuffer)> saveStream(&byteBuffer);
  5539. {
  5540. EXPECT_TRUE(AZ::Utils::SaveObjectToStream(saveStream, AZ::DataStream::ST_XML, &testData, m_serializeContext.get()));
  5541. saveStream.Seek(0, AZ::IO::GenericStream::SeekMode::ST_SEEK_BEGIN);
  5542. }
  5543. // Unreflect AggregateTestClassV1
  5544. m_serializeContext->EnableRemoveReflection();
  5545. m_serializeContext->Class<EmptyDeprecatedClass>();
  5546. m_serializeContext->Class<AggregateTestClassV1>();
  5547. m_serializeContext->DisableRemoveReflection();
  5548. // Reflect AggregateTestClassV2 and load the AggregateTestClassV1 data into memory
  5549. m_serializeContext->Class<ConvertedNewClass>()
  5550. ->Field("m_value", &ConvertedNewClass::m_value)
  5551. ;
  5552. m_serializeContext->Class<AggregateTestClassV2>()
  5553. ->Field("m_testField", &AggregateTestClassV2::m_testField)
  5554. ->Field("m_position", &AggregateTestClassV2::m_position)
  5555. ->Field("m_value", &AggregateTestClassV2::m_value)
  5556. ;
  5557. m_serializeContext->ClassDeprecate("EmptyDeprecatedClass", AZ::Uuid("{73890A64-9ADB-4639-B0E0-93294CE81B19}"),
  5558. [](AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& rootElementNode) -> bool
  5559. {
  5560. rootElementNode.Convert<ConvertedNewClass>(context);
  5561. return true;
  5562. });
  5563. AggregateTestClassV2 resultData;
  5564. EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(saveStream, resultData, m_serializeContext.get()));
  5565. EXPECT_TRUE(testData.m_position.IsClose(resultData.m_position));
  5566. EXPECT_EQ(5, resultData.m_value.m_value);
  5567. // Cleanup - Unreflect the AggregateTestClassV2, ConvertedNewClass and the EmptyDeprecatedClass
  5568. m_serializeContext->EnableRemoveReflection();
  5569. m_serializeContext->Class<ConvertedNewClass>();
  5570. m_serializeContext->Class<AggregateTestClassV2>();
  5571. m_serializeContext->ClassDeprecate("EmptyDeprecatedClass", AZ::Uuid("{73890A64-9ADB-4639-B0E0-93294CE81B19}"),
  5572. [](AZ::SerializeContext&, AZ::SerializeContext::DataElementNode&) -> bool
  5573. {
  5574. return true;
  5575. });
  5576. m_serializeContext->DisableRemoveReflection();
  5577. }
  5578. struct ClassWithObjectStreamCallback
  5579. {
  5580. AZ_TYPE_INFO(ClassWithObjectStreamCallback, "{780F96D2-9907-439D-94B2-60B915BC12F6}");
  5581. AZ_CLASS_ALLOCATOR(ClassWithObjectStreamCallback, AZ::SystemAllocator);
  5582. ClassWithObjectStreamCallback() = default;
  5583. ClassWithObjectStreamCallback(int32_t value)
  5584. : m_value{ value }
  5585. {}
  5586. static void ReflectWithEventHandler(ReflectContext* context, SerializeContext::IEventHandler* eventHandler)
  5587. {
  5588. if (auto serializeContext = azrtti_cast<SerializeContext*>(context))
  5589. {
  5590. //Reflected Template classes must be reflected in one field
  5591. serializeContext->Class<ClassWithObjectStreamCallback>()
  5592. ->EventHandler(eventHandler)
  5593. ->Field("m_value", &ClassWithObjectStreamCallback::m_value)
  5594. ;
  5595. }
  5596. }
  5597. class ObjectStreamEventHandler
  5598. : public SerializeContext::IEventHandler
  5599. {
  5600. public:
  5601. MOCK_METHOD1(OnLoadedFromObjectStream, void(void*));
  5602. MOCK_METHOD1(OnObjectCloned, void(void*));
  5603. };
  5604. int32_t m_value{};
  5605. };
  5606. TEST_F(ObjectStreamSerialization, OnLoadedFromObjectStreamIsInvokedForObjectStreamLoading)
  5607. {
  5608. ClassWithObjectStreamCallback::ObjectStreamEventHandler mockEventHandler;
  5609. EXPECT_CALL(mockEventHandler, OnLoadedFromObjectStream(testing::_)).Times(1);
  5610. ClassWithObjectStreamCallback::ReflectWithEventHandler(m_serializeContext.get(), &mockEventHandler);
  5611. AZStd::vector<AZ::u8> byteBuffer;
  5612. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  5613. {
  5614. ClassWithObjectStreamCallback saveObject{ 1234349 };
  5615. AZ::Utils::SaveObjectToStream(byteStream, AZ::DataStream::ST_BINARY, &saveObject, m_serializeContext.get());
  5616. byteStream.Seek(0, AZ::IO::GenericStream::SeekMode::ST_SEEK_BEGIN);
  5617. }
  5618. ClassWithObjectStreamCallback loadObject;
  5619. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadObject, m_serializeContext.get());
  5620. }
  5621. TEST_F(ObjectStreamSerialization, OnLoadedFromObjectStreamIsNotInvokedForCloneObject)
  5622. {
  5623. ClassWithObjectStreamCallback::ObjectStreamEventHandler mockEventHandler;
  5624. EXPECT_CALL(mockEventHandler, OnLoadedFromObjectStream(testing::_)).Times(0);
  5625. EXPECT_CALL(mockEventHandler, OnObjectCloned(testing::_)).Times(1);
  5626. ClassWithObjectStreamCallback::ReflectWithEventHandler(m_serializeContext.get(), &mockEventHandler);
  5627. AZStd::vector<AZ::u8> byteBuffer;
  5628. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  5629. ClassWithObjectStreamCallback saveObject{ 5 };
  5630. ClassWithObjectStreamCallback cloneObject;
  5631. m_serializeContext->CloneObjectInplace(cloneObject, &saveObject);
  5632. }
  5633. TEST_F(ObjectStreamSerialization, OnClonedObjectIsInvokedForCloneObject)
  5634. {
  5635. ClassWithObjectStreamCallback::ObjectStreamEventHandler mockEventHandler;
  5636. EXPECT_CALL(mockEventHandler, OnObjectCloned(testing::_)).Times(2);
  5637. ClassWithObjectStreamCallback::ReflectWithEventHandler(m_serializeContext.get(), &mockEventHandler);
  5638. AZStd::vector<AZ::u8> byteBuffer;
  5639. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  5640. ClassWithObjectStreamCallback saveObject{ 5 };
  5641. ClassWithObjectStreamCallback cloneObject;
  5642. m_serializeContext->CloneObjectInplace(cloneObject, &saveObject);
  5643. // Cloning the cloned object should increase the newly cloned object m_value by one again
  5644. ClassWithObjectStreamCallback secondCloneObject;
  5645. m_serializeContext->CloneObjectInplace(secondCloneObject, &cloneObject);
  5646. }
  5647. TEST_F(ObjectStreamSerialization, OnClonedObjectIsNotInvokedForObjectStreamLoading)
  5648. {
  5649. ClassWithObjectStreamCallback::ObjectStreamEventHandler mockEventHandler;
  5650. EXPECT_CALL(mockEventHandler, OnObjectCloned(testing::_)).Times(0);
  5651. EXPECT_CALL(mockEventHandler, OnLoadedFromObjectStream(testing::_)).Times(1);
  5652. ClassWithObjectStreamCallback::ReflectWithEventHandler(m_serializeContext.get(), &mockEventHandler);
  5653. AZStd::vector<AZ::u8> byteBuffer;
  5654. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  5655. {
  5656. ClassWithObjectStreamCallback saveObject{ -396320 };
  5657. AZ::Utils::SaveObjectToStream(byteStream, AZ::DataStream::ST_BINARY, &saveObject, m_serializeContext.get());
  5658. byteStream.Seek(0, AZ::IO::GenericStream::SeekMode::ST_SEEK_BEGIN);
  5659. }
  5660. ClassWithObjectStreamCallback loadObject;
  5661. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadObject, m_serializeContext.get());
  5662. }
  5663. class GenericClassInfoExplicitReflectFixture
  5664. : public LeakDetectionFixture
  5665. {
  5666. public:
  5667. void SetUp() override
  5668. {
  5669. LeakDetectionFixture::SetUp();
  5670. m_serializeContext = AZStd::make_unique<SerializeContext>();
  5671. AZ::GenericClassInfo* genericInfo = SerializeGenericTypeInfo<AZStd::vector<AZ::u32>>::GetGenericInfo();
  5672. if (genericInfo)
  5673. {
  5674. genericInfo->Reflect(m_serializeContext.get());
  5675. }
  5676. genericInfo = SerializeGenericTypeInfo<AZStd::string>::GetGenericInfo();
  5677. if (genericInfo)
  5678. {
  5679. genericInfo->Reflect(m_serializeContext.get());
  5680. }
  5681. genericInfo = SerializeGenericTypeInfo<AZStd::unordered_map<float, float>>::GetGenericInfo();
  5682. if (genericInfo)
  5683. {
  5684. genericInfo->Reflect(m_serializeContext.get());
  5685. }
  5686. }
  5687. void TearDown() override
  5688. {
  5689. m_serializeContext->EnableRemoveReflection();
  5690. AZ::GenericClassInfo* genericInfo = SerializeGenericTypeInfo<AZStd::vector<AZ::u32>>::GetGenericInfo();
  5691. if (genericInfo)
  5692. {
  5693. genericInfo->Reflect(m_serializeContext.get());
  5694. }
  5695. genericInfo = SerializeGenericTypeInfo<AZStd::string>::GetGenericInfo();
  5696. if (genericInfo)
  5697. {
  5698. genericInfo->Reflect(m_serializeContext.get());
  5699. }
  5700. genericInfo = SerializeGenericTypeInfo<AZStd::unordered_map<float, float>>::GetGenericInfo();
  5701. if (genericInfo)
  5702. {
  5703. genericInfo->Reflect(m_serializeContext.get());
  5704. }
  5705. m_serializeContext->DisableRemoveReflection();
  5706. m_serializeContext.reset();
  5707. LeakDetectionFixture::TearDown();
  5708. }
  5709. protected:
  5710. AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
  5711. };
  5712. TEST_F(GenericClassInfoExplicitReflectFixture, RootVectorTest)
  5713. {
  5714. AZStd::vector<AZ::u32> rootVector{ 7, 3, 5, 7 };
  5715. {
  5716. // Serializing vector as root class
  5717. AZStd::vector<char> byteBuffer;
  5718. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  5719. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_BINARY);
  5720. byteObjStream->WriteClass(&rootVector);
  5721. byteObjStream->Finalize();
  5722. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  5723. AZStd::vector<AZ::u32> loadedVector;
  5724. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadedVector, m_serializeContext.get());
  5725. EXPECT_EQ(rootVector, loadedVector);
  5726. }
  5727. }
  5728. TEST_F(GenericClassInfoExplicitReflectFixture, RootStringTest)
  5729. {
  5730. AZStd::string rootString("TestString");
  5731. {
  5732. // Serializing string as root class
  5733. AZStd::vector<char> byteBuffer;
  5734. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  5735. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_BINARY);
  5736. byteObjStream->WriteClass(&rootString);
  5737. byteObjStream->Finalize();
  5738. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  5739. AZStd::string loadedString;
  5740. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadedString, m_serializeContext.get());
  5741. EXPECT_EQ(rootString, loadedString);
  5742. }
  5743. }
  5744. TEST_F(GenericClassInfoExplicitReflectFixture, RootUnorderedMapTest)
  5745. {
  5746. AZStd::unordered_map<float, float> rootMap;
  5747. rootMap.emplace(7.0f, 20.1f);
  5748. rootMap.emplace(0.0f, 17.0f);
  5749. {
  5750. // Serializing vector as root class
  5751. AZStd::vector<char> byteBuffer;
  5752. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  5753. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_BINARY);
  5754. byteObjStream->WriteClass(&rootMap);
  5755. byteObjStream->Finalize();
  5756. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  5757. AZStd::unordered_map<float, float> loadedMap;
  5758. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadedMap, m_serializeContext.get());
  5759. EXPECT_EQ(rootMap, loadedMap);
  5760. }
  5761. }
  5762. class GenericClassInfoInheritanceFixture
  5763. : public LeakDetectionFixture
  5764. {
  5765. public:
  5766. void SetUp() override
  5767. {
  5768. LeakDetectionFixture::SetUp();
  5769. m_serializeContext = AZStd::make_unique<SerializeContext>();
  5770. StringUtils::Reflect(m_serializeContext.get());
  5771. }
  5772. void TearDown() override
  5773. {
  5774. m_serializeContext->EnableRemoveReflection();
  5775. StringUtils::Reflect(m_serializeContext.get());
  5776. m_serializeContext->DisableRemoveReflection();
  5777. m_serializeContext.reset();
  5778. LeakDetectionFixture::TearDown();
  5779. }
  5780. class StringUtils : public AZStd::string
  5781. {
  5782. public:
  5783. StringUtils() = default;
  5784. StringUtils(const char* constString)
  5785. : AZStd::string(constString)
  5786. {}
  5787. AZ_TYPE_INFO(StringUtils, "{F3CCCFC0-7890-46A4-9246-067E8A9D2FDE}");
  5788. static void Reflect(AZ::ReflectContext* context)
  5789. {
  5790. if (auto serialize = azrtti_cast<AZ::SerializeContext*>(context))
  5791. {
  5792. serialize->Class<StringUtils, AZStd::string>();
  5793. }
  5794. }
  5795. // ... useful string manipulation functions ...
  5796. };
  5797. protected:
  5798. AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
  5799. };
  5800. TEST_F(GenericClassInfoInheritanceFixture, StringInheritanceTest)
  5801. {
  5802. StringUtils testStringUtils("Custom String");
  5803. // BINARY
  5804. AZStd::vector<char> byteBuffer;
  5805. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  5806. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_BINARY);
  5807. byteObjStream->WriteClass(&testStringUtils);
  5808. byteObjStream->Finalize();
  5809. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  5810. StringUtils loadStringUtils;
  5811. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadStringUtils, m_serializeContext.get());
  5812. EXPECT_EQ(testStringUtils, loadStringUtils);
  5813. }
  5814. class SerializableTupleTest
  5815. : public LeakDetectionFixture
  5816. {
  5817. public:
  5818. using FloatStringIntTuple = std::tuple<float, AZStd::string, int>;
  5819. using EntityIdEntityTuple = std::tuple<AZ::EntityId, AZ::Entity*>;
  5820. using AnyAnyAnyTuple = std::tuple<AZStd::any, AZStd::any, AZStd::any>;
  5821. using SmartPtrAnyTuple = std::tuple<AZStd::shared_ptr<AZStd::any>>;
  5822. using EmptyTuple = std::tuple<>;
  5823. using TupleCeption = std::tuple<std::tuple<AZStd::string>>;
  5824. using EntityIdVectorStringMap = AZStd::unordered_map<AZ::EntityId, AZStd::vector<AZStd::string>>;
  5825. // We must expose the class for serialization first.
  5826. void SetUp() override
  5827. {
  5828. LeakDetectionFixture::SetUp();
  5829. m_serializeContext = AZStd::make_unique<SerializeContext>();
  5830. AZ::Entity::Reflect(m_serializeContext.get());
  5831. AZ::GenericClassInfo* genericClassInfo = SerializeGenericTypeInfo<FloatStringIntTuple>::GetGenericInfo();
  5832. if (genericClassInfo)
  5833. {
  5834. genericClassInfo->Reflect(m_serializeContext.get());
  5835. }
  5836. genericClassInfo = SerializeGenericTypeInfo<EntityIdEntityTuple>::GetGenericInfo();
  5837. if (genericClassInfo)
  5838. {
  5839. genericClassInfo->Reflect(m_serializeContext.get());
  5840. }
  5841. genericClassInfo = SerializeGenericTypeInfo<AnyAnyAnyTuple>::GetGenericInfo();
  5842. if (genericClassInfo)
  5843. {
  5844. genericClassInfo->Reflect(m_serializeContext.get());
  5845. }
  5846. genericClassInfo = SerializeGenericTypeInfo<SmartPtrAnyTuple>::GetGenericInfo();
  5847. if (genericClassInfo)
  5848. {
  5849. genericClassInfo->Reflect(m_serializeContext.get());
  5850. }
  5851. genericClassInfo = SerializeGenericTypeInfo<EntityIdVectorStringMap>::GetGenericInfo();
  5852. if (genericClassInfo)
  5853. {
  5854. genericClassInfo->Reflect(m_serializeContext.get());
  5855. }
  5856. genericClassInfo = SerializeGenericTypeInfo<EmptyTuple>::GetGenericInfo();
  5857. if (genericClassInfo)
  5858. {
  5859. genericClassInfo->Reflect(m_serializeContext.get());
  5860. }
  5861. genericClassInfo = SerializeGenericTypeInfo<TupleCeption>::GetGenericInfo();
  5862. if (genericClassInfo)
  5863. {
  5864. genericClassInfo->Reflect(m_serializeContext.get());
  5865. }
  5866. }
  5867. void TearDown() override
  5868. {
  5869. m_serializeContext->EnableRemoveReflection();
  5870. AZ::Entity::Reflect(m_serializeContext.get());
  5871. AZ::GenericClassInfo* genericClassInfo = SerializeGenericTypeInfo<FloatStringIntTuple>::GetGenericInfo();
  5872. if (genericClassInfo)
  5873. {
  5874. genericClassInfo->Reflect(m_serializeContext.get());
  5875. }
  5876. genericClassInfo = SerializeGenericTypeInfo<EntityIdEntityTuple>::GetGenericInfo();
  5877. if (genericClassInfo)
  5878. {
  5879. genericClassInfo->Reflect(m_serializeContext.get());
  5880. }
  5881. genericClassInfo = SerializeGenericTypeInfo<AnyAnyAnyTuple>::GetGenericInfo();
  5882. if (genericClassInfo)
  5883. {
  5884. genericClassInfo->Reflect(m_serializeContext.get());
  5885. }
  5886. genericClassInfo = SerializeGenericTypeInfo<SmartPtrAnyTuple>::GetGenericInfo();
  5887. if (genericClassInfo)
  5888. {
  5889. genericClassInfo->Reflect(m_serializeContext.get());
  5890. }
  5891. genericClassInfo = SerializeGenericTypeInfo<EntityIdVectorStringMap>::GetGenericInfo();
  5892. if (genericClassInfo)
  5893. {
  5894. genericClassInfo->Reflect(m_serializeContext.get());
  5895. }
  5896. genericClassInfo = SerializeGenericTypeInfo<EmptyTuple>::GetGenericInfo();
  5897. if (genericClassInfo)
  5898. {
  5899. genericClassInfo->Reflect(m_serializeContext.get());
  5900. }
  5901. genericClassInfo = SerializeGenericTypeInfo<TupleCeption>::GetGenericInfo();
  5902. if (genericClassInfo)
  5903. {
  5904. genericClassInfo->Reflect(m_serializeContext.get());
  5905. }
  5906. m_serializeContext->DisableRemoveReflection();
  5907. m_serializeContext.reset();
  5908. LeakDetectionFixture::TearDown();
  5909. }
  5910. protected:
  5911. AZStd::unique_ptr<SerializeContext> m_serializeContext;
  5912. };
  5913. TEST_F(SerializableTupleTest, EmptyTupleTest)
  5914. {
  5915. EmptyTuple testTuple;
  5916. AZStd::vector<char> byteBuffer;
  5917. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  5918. auto objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_XML);
  5919. objStream->WriteClass(&testTuple);
  5920. objStream->Finalize();
  5921. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  5922. EmptyTuple loadTuple;
  5923. EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadTuple, m_serializeContext.get()));
  5924. EXPECT_EQ(testTuple, loadTuple);
  5925. }
  5926. TEST_F(SerializableTupleTest, BasicTypeTest)
  5927. {
  5928. FloatStringIntTuple testTuple{ 3.14f, "Tuple", -1 };
  5929. AZStd::vector<char> byteBuffer;
  5930. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  5931. auto objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_XML);
  5932. objStream->WriteClass(&testTuple);
  5933. objStream->Finalize();
  5934. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  5935. FloatStringIntTuple loadTuple;
  5936. EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadTuple, m_serializeContext.get()));
  5937. EXPECT_EQ(testTuple, loadTuple);
  5938. }
  5939. TEST_F(SerializableTupleTest, PointerTupleTest)
  5940. {
  5941. EntityIdEntityTuple testTuple{ AZ::Entity::MakeId(), aznew AZ::Entity("Tuple") };
  5942. AZStd::vector<char> byteBuffer;
  5943. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  5944. auto objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_XML);
  5945. objStream->WriteClass(&testTuple);
  5946. objStream->Finalize();
  5947. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  5948. EntityIdEntityTuple loadTuple;
  5949. EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadTuple, m_serializeContext.get()));
  5950. EXPECT_EQ(std::get<0>(testTuple), std::get<0>(loadTuple));
  5951. EXPECT_EQ(std::get<1>(testTuple)->GetId(), std::get<1>(loadTuple)->GetId());
  5952. delete std::get<1>(testTuple);
  5953. delete std::get<1>(loadTuple);
  5954. }
  5955. TEST_F(SerializableTupleTest, TupleAnyTest)
  5956. {
  5957. AnyAnyAnyTuple testTuple{ AZStd::make_any<AZStd::string>("FirstAny"), AZStd::any(EntityIdVectorStringMap()), AZStd::make_any<AZ::Entity>("Tuple") };
  5958. AZStd::vector<char> byteBuffer;
  5959. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  5960. auto objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_XML);
  5961. objStream->WriteClass(&testTuple);
  5962. objStream->Finalize();
  5963. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  5964. AnyAnyAnyTuple loadTuple;
  5965. EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadTuple, m_serializeContext.get()));
  5966. auto testStringPtr = AZStd::any_cast<AZStd::string>(&std::get<0>(testTuple));
  5967. ASSERT_NE(nullptr, testStringPtr);
  5968. auto loadStringPtr = AZStd::any_cast<AZStd::string>(&std::get<0>(loadTuple));
  5969. ASSERT_NE(nullptr, loadStringPtr);
  5970. auto testMapPtr = AZStd::any_cast<EntityIdVectorStringMap>(&std::get<1>(testTuple));
  5971. ASSERT_NE(nullptr, testMapPtr);
  5972. auto loadMapPtr = AZStd::any_cast<EntityIdVectorStringMap>(&std::get<1>(loadTuple));
  5973. ASSERT_NE(nullptr, loadMapPtr);
  5974. auto testEntityPtr = AZStd::any_cast<AZ::Entity>(&std::get<2>(testTuple));
  5975. ASSERT_NE(nullptr, testEntityPtr);
  5976. auto loadEntityPtr = AZStd::any_cast<AZ::Entity>(&std::get<2>(loadTuple));
  5977. ASSERT_NE(nullptr, loadEntityPtr);
  5978. EXPECT_EQ(*testStringPtr, *loadStringPtr);
  5979. EXPECT_EQ(*testMapPtr, *loadMapPtr);
  5980. EXPECT_EQ(testEntityPtr->GetId(), loadEntityPtr->GetId());
  5981. }
  5982. TEST_F(SerializableTupleTest, UniquePtrAnyTupleTest)
  5983. {
  5984. SmartPtrAnyTuple testTuple{ AZStd::make_shared<AZStd::any>(AZStd::make_any<AZStd::string>("SuperWrappedString")) };
  5985. AZStd::vector<char> byteBuffer;
  5986. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  5987. auto objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_XML);
  5988. objStream->WriteClass(&testTuple);
  5989. objStream->Finalize();
  5990. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  5991. SmartPtrAnyTuple loadTuple;
  5992. EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadTuple, m_serializeContext.get()));
  5993. auto rawTestPtr = std::get<0>(testTuple).get();
  5994. auto rawLoadPtr = std::get<0>(loadTuple).get();
  5995. ASSERT_NE(nullptr, rawLoadPtr);
  5996. auto testStringPtr = AZStd::any_cast<AZStd::string>(rawTestPtr);
  5997. ASSERT_NE(nullptr, testStringPtr);
  5998. auto loadStringPtr = AZStd::any_cast<AZStd::string>(rawLoadPtr);
  5999. ASSERT_NE(nullptr, loadStringPtr);
  6000. EXPECT_EQ(*testStringPtr, *loadStringPtr);
  6001. }
  6002. TEST_F(SerializableTupleTest, 2Fast2TuplesTest)
  6003. {
  6004. TupleCeption testTuple{ AZStd::make_tuple(AZStd::string("InnerTupleString")) };
  6005. AZStd::vector<char> byteBuffer;
  6006. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  6007. auto objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_XML);
  6008. objStream->WriteClass(&testTuple);
  6009. objStream->Finalize();
  6010. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  6011. TupleCeption loadTuple;
  6012. EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadTuple, m_serializeContext.get()));
  6013. EXPECT_EQ(testTuple, loadTuple);
  6014. }
  6015. class SerializableAZStdArrayTest
  6016. : public LeakDetectionFixture
  6017. {
  6018. public:
  6019. using ZeroArray = AZStd::array<float, 0>;
  6020. using FloatFourArray = AZStd::array<float, 4>;
  6021. using ZeroNestedArray = AZStd::array<AZStd::array<float, 0>, 0>;
  6022. using NestedArray = AZStd::array<AZStd::array<FloatFourArray, 3>, 2>;
  6023. // We must expose the class for serialization first.
  6024. void SetUp() override
  6025. {
  6026. LeakDetectionFixture::SetUp();
  6027. m_serializeContext = AZStd::make_unique<SerializeContext>();
  6028. AZ::GenericClassInfo* genericClassInfo = SerializeGenericTypeInfo<ZeroArray>::GetGenericInfo();
  6029. if (genericClassInfo)
  6030. {
  6031. genericClassInfo->Reflect(m_serializeContext.get());
  6032. }
  6033. genericClassInfo = SerializeGenericTypeInfo<FloatFourArray>::GetGenericInfo();
  6034. if (genericClassInfo)
  6035. {
  6036. genericClassInfo->Reflect(m_serializeContext.get());
  6037. }
  6038. genericClassInfo = SerializeGenericTypeInfo<ZeroNestedArray>::GetGenericInfo();
  6039. if (genericClassInfo)
  6040. {
  6041. genericClassInfo->Reflect(m_serializeContext.get());
  6042. }
  6043. genericClassInfo = SerializeGenericTypeInfo<NestedArray>::GetGenericInfo();
  6044. if (genericClassInfo)
  6045. {
  6046. genericClassInfo->Reflect(m_serializeContext.get());
  6047. }
  6048. }
  6049. void TearDown() override
  6050. {
  6051. m_serializeContext->EnableRemoveReflection();
  6052. AZ::GenericClassInfo* genericClassInfo = SerializeGenericTypeInfo<ZeroArray>::GetGenericInfo();
  6053. if (genericClassInfo)
  6054. {
  6055. genericClassInfo->Reflect(m_serializeContext.get());
  6056. }
  6057. genericClassInfo = SerializeGenericTypeInfo<FloatFourArray>::GetGenericInfo();
  6058. if (genericClassInfo)
  6059. {
  6060. genericClassInfo->Reflect(m_serializeContext.get());
  6061. }
  6062. genericClassInfo = SerializeGenericTypeInfo<ZeroNestedArray>::GetGenericInfo();
  6063. if (genericClassInfo)
  6064. {
  6065. genericClassInfo->Reflect(m_serializeContext.get());
  6066. }
  6067. genericClassInfo = SerializeGenericTypeInfo<NestedArray>::GetGenericInfo();
  6068. if (genericClassInfo)
  6069. {
  6070. genericClassInfo->Reflect(m_serializeContext.get());
  6071. }
  6072. m_serializeContext->DisableRemoveReflection();
  6073. m_serializeContext.reset();
  6074. LeakDetectionFixture::TearDown();
  6075. }
  6076. protected:
  6077. FloatFourArray m_array;
  6078. AZStd::unique_ptr<SerializeContext> m_serializeContext;
  6079. };
  6080. TEST_F(SerializableAZStdArrayTest, SingleEntryCount)
  6081. {
  6082. Internal::AZStdArrayEvents events;
  6083. events.OnWriteBegin(&m_array);
  6084. for (size_t i = 0; i < 16; ++i)
  6085. {
  6086. EXPECT_EQ(i, events.GetIndex());
  6087. events.Increment();
  6088. }
  6089. for (size_t i = 16; i > 8; --i)
  6090. {
  6091. EXPECT_EQ(i, events.GetIndex());
  6092. events.Decrement();
  6093. }
  6094. events.OnWriteEnd(&m_array);
  6095. EXPECT_TRUE(events.IsEmpty());
  6096. }
  6097. TEST_F(SerializableAZStdArrayTest, MultipleEntriesCount)
  6098. {
  6099. Internal::AZStdArrayEvents events;
  6100. events.OnWriteBegin(&m_array);
  6101. for (size_t i = 0; i < 8; ++i)
  6102. {
  6103. events.Increment();
  6104. }
  6105. for (size_t i = 8; i > 4; --i)
  6106. {
  6107. EXPECT_EQ(i, events.GetIndex());
  6108. events.Decrement();
  6109. }
  6110. events.OnWriteBegin(&m_array);
  6111. for (size_t i = 0; i < 16; ++i)
  6112. {
  6113. EXPECT_EQ(i, events.GetIndex());
  6114. events.Increment();
  6115. }
  6116. for (size_t i = 16; i > 8; --i)
  6117. {
  6118. EXPECT_EQ(i, events.GetIndex());
  6119. events.Decrement();
  6120. }
  6121. events.OnWriteEnd(&m_array);
  6122. EXPECT_EQ(4, events.GetIndex()); // The 8 entries on the first entry of the stack.
  6123. events.OnWriteEnd(&m_array);
  6124. EXPECT_TRUE(events.IsEmpty());
  6125. }
  6126. TEST_F(SerializableAZStdArrayTest, SingleEntryContainerInterface)
  6127. {
  6128. GenericClassInfo* containerInfo = SerializeGenericTypeInfo<decltype(m_array)>::GetGenericInfo();
  6129. ASSERT_NE(nullptr, containerInfo);
  6130. ASSERT_NE(nullptr, containerInfo->GetClassData());
  6131. SerializeContext::IDataContainer* container = containerInfo->GetClassData()->m_container;
  6132. ASSERT_NE(nullptr, container);
  6133. SerializeContext::IEventHandler* eventHandler = containerInfo->GetClassData()->m_eventHandler;
  6134. ASSERT_NE(nullptr, eventHandler);
  6135. eventHandler->OnWriteBegin(&m_array);
  6136. void* element0 = container->ReserveElement(&m_array, nullptr);
  6137. ASSERT_NE(nullptr, element0);
  6138. *reinterpret_cast<float*>(element0) = 42.0f;
  6139. container->StoreElement(&m_array, element0);
  6140. void* element1 = container->ReserveElement(&m_array, nullptr);
  6141. ASSERT_NE(nullptr, element1);
  6142. *reinterpret_cast<float*>(element1) = 142.0f;
  6143. container->StoreElement(&m_array, element1);
  6144. void* deletedElement = container->ReserveElement(&m_array, nullptr);
  6145. ASSERT_NE(nullptr, deletedElement);
  6146. *reinterpret_cast<float*>(deletedElement) = 9000.0f;
  6147. container->RemoveElement(&m_array, deletedElement, nullptr);
  6148. void* element2 = container->ReserveElement(&m_array, nullptr);
  6149. ASSERT_NE(nullptr, element2);
  6150. *reinterpret_cast<float*>(element2) = 242.0f;
  6151. container->StoreElement(&m_array, element2);
  6152. void* element3 = container->ReserveElement(&m_array, nullptr);
  6153. ASSERT_NE(nullptr, element3);
  6154. *reinterpret_cast<float*>(element3) = 342.0f;
  6155. container->StoreElement(&m_array, element2);
  6156. void* overflownElement = container->ReserveElement(&m_array, nullptr);
  6157. EXPECT_EQ(nullptr, overflownElement);
  6158. eventHandler->OnWriteEnd(&m_array);
  6159. eventHandler->OnLoadedFromObjectStream(&m_array);
  6160. EXPECT_FLOAT_EQ( 42.0f, m_array[0]);
  6161. EXPECT_FLOAT_EQ(142.0f, m_array[1]);
  6162. EXPECT_FLOAT_EQ(242.0f, m_array[2]);
  6163. EXPECT_FLOAT_EQ(342.0f, m_array[3]);
  6164. }
  6165. TEST_F(SerializableAZStdArrayTest, SimpleSerialization)
  6166. {
  6167. m_array[0] = 10.0f;
  6168. m_array[1] = 11.1f;
  6169. m_array[2] = 12.2f;
  6170. m_array[3] = 13.3f;
  6171. AZStd::vector<char> byteBuffer;
  6172. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  6173. auto objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_XML);
  6174. objStream->WriteClass(&m_array);
  6175. objStream->Finalize();
  6176. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  6177. FloatFourArray loadedArray;
  6178. ASSERT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadedArray, m_serializeContext.get()));
  6179. for (size_t i = 0; i < 4; ++i)
  6180. {
  6181. EXPECT_EQ(m_array[i], loadedArray[i]);
  6182. }
  6183. }
  6184. TEST_F(SerializableAZStdArrayTest, NestedSerialization)
  6185. {
  6186. NestedArray nested;
  6187. nested[0][0][0] = 0.0f;
  6188. nested[0][0][1] = 0.1f;
  6189. nested[0][0][2] = 0.2f;
  6190. nested[0][0][3] = 0.3f;
  6191. nested[0][1][0] = 1.0f;
  6192. nested[0][1][1] = 1.1f;
  6193. nested[0][1][2] = 1.2f;
  6194. nested[0][1][3] = 1.3f;
  6195. nested[0][2][0] = 2.0f;
  6196. nested[0][2][1] = 2.1f;
  6197. nested[0][2][2] = 2.2f;
  6198. nested[0][2][3] = 2.3f;
  6199. nested[1][0][0] = 10.0f;
  6200. nested[1][0][1] = 10.1f;
  6201. nested[1][0][2] = 10.2f;
  6202. nested[1][0][3] = 10.3f;
  6203. nested[1][1][0] = 11.0f;
  6204. nested[1][1][1] = 11.1f;
  6205. nested[1][1][2] = 11.2f;
  6206. nested[1][1][3] = 11.3f;
  6207. nested[1][2][0] = 12.0f;
  6208. nested[1][2][1] = 12.1f;
  6209. nested[1][2][2] = 12.2f;
  6210. nested[1][2][3] = 12.3f;
  6211. AZStd::vector<char> byteBuffer;
  6212. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  6213. auto objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_XML);
  6214. objStream->WriteClass(&nested);
  6215. objStream->Finalize();
  6216. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  6217. NestedArray loadedArray;
  6218. ASSERT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadedArray, m_serializeContext.get()));
  6219. for (size_t l = 0; l < 2; ++l)
  6220. {
  6221. for (size_t k = 0; k < 3; ++k)
  6222. {
  6223. for (size_t i = 0; i < 4; ++i)
  6224. {
  6225. EXPECT_EQ(nested[l][k][i], loadedArray[l][k][i]);
  6226. }
  6227. }
  6228. }
  6229. }
  6230. TEST_F(SerializableAZStdArrayTest, ZeroSerialization)
  6231. {
  6232. ZeroArray zerroArray;
  6233. AZStd::vector<char> byteBuffer;
  6234. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  6235. auto objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_XML);
  6236. objStream->WriteClass(&zerroArray);
  6237. objStream->Finalize();
  6238. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  6239. ZeroArray loadedArray;
  6240. EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadedArray, m_serializeContext.get()));
  6241. }
  6242. TEST_F(SerializableAZStdArrayTest, ZeroNestedSerialization)
  6243. {
  6244. ZeroNestedArray zerroArray;
  6245. AZStd::vector<char> byteBuffer;
  6246. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  6247. auto objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_XML);
  6248. objStream->WriteClass(&zerroArray);
  6249. objStream->Finalize();
  6250. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  6251. ZeroNestedArray loadedArray;
  6252. EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadedArray, m_serializeContext.get()));
  6253. }
  6254. struct VectorTest
  6255. {
  6256. AZ_RTTI(VectorTest, "{2BE9FC5C-14A6-49A7-9A2C-79F6C2F27221}");
  6257. virtual ~VectorTest() = default;
  6258. AZStd::vector<int> m_vec;
  6259. static bool Convert(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
  6260. {
  6261. AZStd::vector<int> vec;
  6262. AZ::SerializeContext::DataElementNode* vecElement = classElement.FindSubElement(AZ_CRC("m_vec"));
  6263. EXPECT_TRUE(vecElement != nullptr);
  6264. bool gotData = vecElement->GetData(vec);
  6265. EXPECT_TRUE(gotData);
  6266. vec.push_back(42);
  6267. bool setData = vecElement->SetData(context, vec);
  6268. EXPECT_TRUE(setData);
  6269. return true;
  6270. }
  6271. };
  6272. // Splitting these tests up to make it easier to find memory leaks for specific containers.
  6273. TEST_F(Serialization, ReserveAndFreeWithoutMemLeaks_Array) { ReserveAndFreeWithoutMemLeaks<AZStd::array<float, 5>>(); }
  6274. TEST_F(Serialization, ReserveAndFreeWithoutMemLeaks_FixedVector) { ReserveAndFreeWithoutMemLeaks<AZStd::fixed_vector<float, 5>>(); }
  6275. TEST_F(Serialization, ReserveAndFreeWithoutMemLeaks_ForwardList) { ReserveAndFreeWithoutMemLeaks<AZStd::forward_list<float>>(); }
  6276. TEST_F(Serialization, ReserveAndFreeWithoutMemLeaks_UnorderedSet) { ReserveAndFreeWithoutMemLeaks<AZStd::unordered_set<float>>(); }
  6277. TEST_F(Serialization, ReserveAndFreeWithoutMemLeaks_UnorderedMultiSet) { ReserveAndFreeWithoutMemLeaks<AZStd::unordered_multiset<float>>(); }
  6278. TEST_F(Serialization, ReserveAndFreeWithoutMemLeaks_List) { ReserveAndFreeWithoutMemLeaks<AZStd::list<float>>(); }
  6279. TEST_F(Serialization, ReserveAndFreeWithoutMemLeaks_Set) { ReserveAndFreeWithoutMemLeaks<AZStd::set<float>>(); }
  6280. TEST_F(Serialization, ReserveAndFreeWithoutMemLeaks_Vector) { ReserveAndFreeWithoutMemLeaks<AZStd::vector<float>>(); }
  6281. TEST_F(Serialization, ConvertVectorContainer)
  6282. {
  6283. // Reflect version 1
  6284. m_serializeContext->Class<VectorTest>()
  6285. ->Version(1)
  6286. ->Field("m_vec", &VectorTest::m_vec);
  6287. VectorTest test;
  6288. test.m_vec.push_back(1024);
  6289. // write test to an XML buffer
  6290. AZStd::vector<char> byteBuffer;
  6291. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  6292. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_XML);
  6293. byteObjStream->WriteClass(&test);
  6294. byteObjStream->Finalize();
  6295. // Update the version to 2 and add the converter
  6296. m_serializeContext->EnableRemoveReflection();
  6297. m_serializeContext->Class<VectorTest>();
  6298. m_serializeContext->DisableRemoveReflection();
  6299. m_serializeContext->Class<VectorTest>()
  6300. ->Version(2, &VectorTest::Convert)
  6301. ->Field("m_vec", &VectorTest::m_vec);
  6302. // Reset for read
  6303. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  6304. test = VectorTest{};
  6305. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, test, m_serializeContext.get());
  6306. EXPECT_EQ(2, test.m_vec.size());
  6307. }
  6308. class SerializeVectorWithInitialElementsTest
  6309. : public LeakDetectionFixture
  6310. {
  6311. public:
  6312. // We must expose the class for serialization first.
  6313. void SetUp() override
  6314. {
  6315. LeakDetectionFixture::SetUp();
  6316. m_serializeContext = AZStd::make_unique<SerializeContext>();
  6317. VectorWrapper::Reflect(m_serializeContext.get());
  6318. }
  6319. void TearDown() override
  6320. {
  6321. m_serializeContext.reset();
  6322. LeakDetectionFixture::TearDown();
  6323. }
  6324. struct VectorWrapper
  6325. {
  6326. AZ_TYPE_INFO(VectorWrapper, "{91F69715-30C3-4F1A-90A0-5F5F7517F375}");
  6327. AZ_CLASS_ALLOCATOR(VectorWrapper, AZ::SystemAllocator);
  6328. VectorWrapper()
  6329. : m_fixedVectorInts(2, 412)
  6330. , m_vectorInts(2, 42)
  6331. {}
  6332. static void Reflect(AZ::ReflectContext* context)
  6333. {
  6334. if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  6335. {
  6336. serializeContext->Class<VectorWrapper>()
  6337. ->Field("fixedVectorInts", &VectorWrapper::m_fixedVectorInts)
  6338. ->Field("VectorInts", &VectorWrapper::m_vectorInts);
  6339. }
  6340. }
  6341. AZStd::fixed_vector<int, 2> m_fixedVectorInts;
  6342. AZStd::vector<int> m_vectorInts;
  6343. };
  6344. protected:
  6345. AZStd::unique_ptr<SerializeContext> m_serializeContext;
  6346. };
  6347. TEST_F(SerializeVectorWithInitialElementsTest, CloneObjectTest)
  6348. {
  6349. VectorWrapper vectorWrapper;
  6350. ASSERT_EQ(2, vectorWrapper.m_fixedVectorInts.size());
  6351. ASSERT_EQ(2, vectorWrapper.m_vectorInts.size());
  6352. vectorWrapper.m_fixedVectorInts[1] = 256;
  6353. vectorWrapper.m_vectorInts[0] = 5;
  6354. vectorWrapper.m_vectorInts[1] = 10;
  6355. VectorWrapper* clonedWrapper = m_serializeContext->CloneObject(&vectorWrapper);
  6356. ASSERT_NE(nullptr, clonedWrapper);
  6357. EXPECT_EQ(vectorWrapper.m_vectorInts.size(), clonedWrapper->m_vectorInts.size());
  6358. EXPECT_EQ(5, clonedWrapper->m_vectorInts[0]);
  6359. EXPECT_EQ(10, clonedWrapper->m_vectorInts[1]);
  6360. EXPECT_EQ(vectorWrapper.m_fixedVectorInts.size(), clonedWrapper->m_fixedVectorInts.size());
  6361. EXPECT_EQ(256, clonedWrapper->m_fixedVectorInts[1]);
  6362. delete clonedWrapper;
  6363. }
  6364. TEST_F(SerializeVectorWithInitialElementsTest, CloneObjectInplaceTest)
  6365. {
  6366. VectorWrapper vectorWrapper;
  6367. ASSERT_EQ(2, vectorWrapper.m_fixedVectorInts.size());
  6368. ASSERT_EQ(2, vectorWrapper.m_vectorInts.size());
  6369. vectorWrapper.m_fixedVectorInts[1] = 256;
  6370. vectorWrapper.m_vectorInts[0] = 5;
  6371. vectorWrapper.m_vectorInts[1] = 10;
  6372. VectorWrapper clonedWrapper;
  6373. m_serializeContext->CloneObjectInplace(clonedWrapper, &vectorWrapper);
  6374. EXPECT_EQ(vectorWrapper.m_vectorInts.size(), clonedWrapper.m_vectorInts.size());
  6375. EXPECT_EQ(5, clonedWrapper.m_vectorInts[0]);
  6376. EXPECT_EQ(10, clonedWrapper.m_vectorInts[1]);
  6377. EXPECT_EQ(vectorWrapper.m_fixedVectorInts.size(), clonedWrapper.m_fixedVectorInts.size());
  6378. EXPECT_EQ(256, clonedWrapper.m_fixedVectorInts[1]);
  6379. }
  6380. TEST_F(SerializeVectorWithInitialElementsTest, ObjectStreamTest)
  6381. {
  6382. VectorWrapper vectorWrapper;
  6383. ASSERT_EQ(2, vectorWrapper.m_fixedVectorInts.size());
  6384. ASSERT_EQ(2, vectorWrapper.m_vectorInts.size());
  6385. vectorWrapper.m_fixedVectorInts[1] = 256;
  6386. vectorWrapper.m_vectorInts[0] = 5;
  6387. vectorWrapper.m_vectorInts[1] = 10;
  6388. AZStd::vector<char> byteBuffer;
  6389. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  6390. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_XML);
  6391. byteObjStream->WriteClass(&vectorWrapper);
  6392. byteObjStream->Finalize();
  6393. byteStream.Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  6394. VectorWrapper loadedWrapper;
  6395. bool loadSuccess = AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadedWrapper, m_serializeContext.get());
  6396. EXPECT_TRUE(loadSuccess);
  6397. EXPECT_EQ(vectorWrapper.m_vectorInts.size(), loadedWrapper.m_vectorInts.size());
  6398. EXPECT_EQ(5, loadedWrapper.m_vectorInts[0]);
  6399. EXPECT_EQ(10, loadedWrapper.m_vectorInts[1]);
  6400. EXPECT_EQ(vectorWrapper.m_fixedVectorInts.size(), loadedWrapper.m_fixedVectorInts.size());
  6401. EXPECT_EQ(256, loadedWrapper.m_fixedVectorInts[1]);
  6402. }
  6403. TEST_F(SerializeVectorWithInitialElementsTest, DataPatchTest)
  6404. {
  6405. VectorWrapper modifiedWrapper;
  6406. ASSERT_EQ(2, modifiedWrapper.m_fixedVectorInts.size());
  6407. ASSERT_EQ(2, modifiedWrapper.m_vectorInts.size());
  6408. modifiedWrapper.m_fixedVectorInts[1] = 256;
  6409. modifiedWrapper.m_vectorInts[0] = 5;
  6410. modifiedWrapper.m_vectorInts[1] = 10;
  6411. modifiedWrapper.m_vectorInts.push_back(15);
  6412. VectorWrapper initialWrapper;
  6413. DataPatch patch;
  6414. patch.Create(&initialWrapper, azrtti_typeid<VectorWrapper>(), &modifiedWrapper, azrtti_typeid<VectorWrapper>(), DataPatch::FlagsMap(), DataPatch::FlagsMap(), m_serializeContext.get());
  6415. VectorWrapper* patchedWrapper = patch.Apply(&initialWrapper, m_serializeContext.get());
  6416. ASSERT_NE(nullptr, patchedWrapper);
  6417. EXPECT_EQ(modifiedWrapper.m_vectorInts.size(), patchedWrapper->m_vectorInts.size());
  6418. EXPECT_EQ(5, patchedWrapper->m_vectorInts[0]);
  6419. EXPECT_EQ(10, patchedWrapper->m_vectorInts[1]);
  6420. EXPECT_EQ(15, patchedWrapper->m_vectorInts[2]);
  6421. EXPECT_EQ(modifiedWrapper.m_fixedVectorInts.size(), patchedWrapper->m_fixedVectorInts.size());
  6422. EXPECT_EQ(256, patchedWrapper->m_fixedVectorInts[1]);
  6423. delete patchedWrapper;
  6424. }
  6425. struct TestLeafNode
  6426. {
  6427. AZ_RTTI(TestLeafNode, "{D50B136B-82E1-414F-9D84-FEC3A75DC9DF}");
  6428. TestLeafNode() = default;
  6429. TestLeafNode(int field) : m_field(field)
  6430. {}
  6431. virtual ~TestLeafNode() = default;
  6432. int m_field = 0;
  6433. };
  6434. struct TestContainer
  6435. {
  6436. AZ_RTTI(TestContainer, "{6941B3D8-1EE9-4EBD-955A-AB55CFDEE77A}");
  6437. TestContainer() = default;
  6438. virtual ~TestContainer() = default;
  6439. TestLeafNode m_node;
  6440. };
  6441. class TestLeafNodeSerializer
  6442. : public SerializeContext::IDataSerializer
  6443. {
  6444. /// Store the class data into a stream.
  6445. size_t Save(const void* classPtr, IO::GenericStream& stream, bool isDataBigEndian /*= false*/) override
  6446. {
  6447. int tempData;
  6448. tempData = reinterpret_cast<const TestLeafNode*>(classPtr)->m_field;
  6449. AZ_SERIALIZE_SWAP_ENDIAN(tempData, isDataBigEndian);
  6450. return static_cast<size_t>(stream.Write(sizeof(tempData), reinterpret_cast<void*>(&tempData)));
  6451. }
  6452. size_t DataToText(IO::GenericStream& in, IO::GenericStream& out, bool isDataBigEndian /*= false*/) override
  6453. {
  6454. if (in.GetLength() < sizeof(int))
  6455. {
  6456. return 0;
  6457. }
  6458. int tempData;
  6459. in.Read(sizeof(int), reinterpret_cast<void*>(&tempData));
  6460. char textBuffer[256];
  6461. AZ_SERIALIZE_SWAP_ENDIAN(tempData, isDataBigEndian);
  6462. char* textData = &textBuffer[0];
  6463. azsnprintf(textData, sizeof(textBuffer), "%d", tempData);
  6464. AZStd::string outText = textBuffer;
  6465. return static_cast<size_t>(out.Write(outText.size(), outText.data()));
  6466. }
  6467. size_t TextToData(const char* text, unsigned int /*textVersion*/, IO::GenericStream& stream, bool isDataBigEndian /*= false*/) override
  6468. {
  6469. int value;
  6470. value = atoi(text);
  6471. AZ_SERIALIZE_SWAP_ENDIAN(value, isDataBigEndian);
  6472. stream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
  6473. return static_cast<size_t>(stream.Write(sizeof(value), reinterpret_cast<void*>(&value)));
  6474. }
  6475. bool Load(void* classPtr, IO::GenericStream& stream, unsigned int version, bool isDataBigEndian /*= false*/) override
  6476. {
  6477. int tempData = 0;
  6478. if (stream.GetLength() < sizeof(tempData))
  6479. {
  6480. return false;
  6481. }
  6482. stream.Read(sizeof(tempData), reinterpret_cast<void*>(&tempData));
  6483. EXPECT_EQ(version, 1);
  6484. AZ_SERIALIZE_SWAP_ENDIAN(tempData, isDataBigEndian);
  6485. *reinterpret_cast<TestLeafNode*>(classPtr) = TestLeafNode{ tempData };
  6486. return true;
  6487. }
  6488. bool CompareValueData(const void* lhs, const void* rhs) override
  6489. {
  6490. int tempDataLhs = reinterpret_cast<const TestLeafNode*>(lhs)->m_field;;
  6491. int tempDataRhs = reinterpret_cast<const TestLeafNode*>(rhs)->m_field;;
  6492. return tempDataLhs == tempDataRhs;
  6493. }
  6494. };
  6495. // Serializer which sets a reference bool to true on deletion to detect when it's lifetime ends.
  6496. class TestDeleterSerializer
  6497. : public SerializeContext::IDataSerializer
  6498. {
  6499. public:
  6500. TestDeleterSerializer(bool& serializerDeleted)
  6501. : m_serializerDeleted{ serializerDeleted }
  6502. {}
  6503. ~TestDeleterSerializer() override
  6504. {
  6505. m_serializerDeleted = true;
  6506. }
  6507. size_t Save(const void*, IO::GenericStream&, bool) override
  6508. {
  6509. return {};
  6510. }
  6511. size_t DataToText(IO::GenericStream&, IO::GenericStream&, bool) override
  6512. {
  6513. return {};
  6514. }
  6515. size_t TextToData(const char*, unsigned int , IO::GenericStream&, bool) override
  6516. {
  6517. return {};
  6518. }
  6519. bool Load(void*, IO::GenericStream&, unsigned int, bool) override
  6520. {
  6521. return true;
  6522. }
  6523. bool CompareValueData(const void* lhs, const void* rhs) override
  6524. {
  6525. AZ_UNUSED(lhs);
  6526. AZ_UNUSED(rhs);
  6527. return true;
  6528. }
  6529. private:
  6530. bool& m_serializerDeleted;
  6531. };
  6532. TEST_F(Serialization, ConvertWithCustomSerializer)
  6533. {
  6534. m_serializeContext->Class<TestContainer>()
  6535. ->Version(1)
  6536. ->Field("m_node", &TestContainer::m_node);
  6537. m_serializeContext->Class<TestLeafNode>()
  6538. ->Version(1)
  6539. ->Serializer<TestLeafNodeSerializer>();
  6540. const int testValue = 123;
  6541. TestContainer test;
  6542. test.m_node.m_field = testValue;
  6543. // write test to an XML buffer
  6544. AZStd::vector<char> byteBuffer;
  6545. IO::ByteContainerStream<AZStd::vector<char> > byteStream(&byteBuffer);
  6546. ObjectStream* byteObjStream = ObjectStream::Create(&byteStream, *m_serializeContext, ObjectStream::ST_XML);
  6547. byteObjStream->WriteClass(&test);
  6548. byteObjStream->Finalize();
  6549. // Update the version to 2
  6550. m_serializeContext->EnableRemoveReflection();
  6551. m_serializeContext->Class<TestContainer>();
  6552. m_serializeContext->Class<TestLeafNode>();
  6553. m_serializeContext->DisableRemoveReflection();
  6554. m_serializeContext->Class<TestContainer>()
  6555. ->Version(2)
  6556. ->Field("m_node", &TestContainer::m_node);
  6557. m_serializeContext->Class<TestLeafNode>()
  6558. ->Version(2)
  6559. ->Serializer<TestLeafNodeSerializer>();
  6560. // Reset for read
  6561. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  6562. test = {};
  6563. AZ::Utils::LoadObjectFromStreamInPlace(byteStream, test, m_serializeContext.get());
  6564. EXPECT_EQ(test.m_node.m_field, testValue);
  6565. }
  6566. TEST_F(Serialization, CustomSerializerWithDefaultDeleter_IsDeletedOnUnreflect)
  6567. {
  6568. bool serializerDeleted = false;
  6569. AZ::Serialize::IDataSerializerPtr customSerializer{ new TestDeleterSerializer{ serializerDeleted }, AZ::SerializeContext::IDataSerializer::CreateDefaultDeleteDeleter() };
  6570. m_serializeContext->Class<TestLeafNode>()
  6571. ->Version(1)
  6572. ->Serializer(AZStd::move(customSerializer));
  6573. EXPECT_FALSE(serializerDeleted);
  6574. m_serializeContext->EnableRemoveReflection();
  6575. m_serializeContext->Class<TestLeafNode>();
  6576. m_serializeContext->DisableRemoveReflection();
  6577. EXPECT_TRUE(serializerDeleted);
  6578. }
  6579. TEST_F(Serialization, CustomSerializerWithNoDeleteDeleter_IsNotDeletedOnUnreflect)
  6580. {
  6581. bool serializerDeleted = false;
  6582. TestDeleterSerializer* serializerInstance = new TestDeleterSerializer{ serializerDeleted };
  6583. AZ::Serialize::IDataSerializerPtr customSerializer{ serializerInstance, AZ::SerializeContext::IDataSerializer::CreateNoDeleteDeleter() };
  6584. m_serializeContext->Class<TestLeafNode>()
  6585. ->Version(1)
  6586. ->Serializer(AZStd::move(customSerializer));
  6587. EXPECT_FALSE(serializerDeleted);
  6588. m_serializeContext->EnableRemoveReflection();
  6589. m_serializeContext->Class<TestLeafNode>();
  6590. m_serializeContext->DisableRemoveReflection();
  6591. ASSERT_FALSE(serializerDeleted);
  6592. delete serializerInstance;
  6593. }
  6594. TEST_F(Serialization, DefaultCtorThatAllocatesMemoryDoesntLeak)
  6595. {
  6596. ClassThatAllocatesMemoryInDefaultCtor::Reflect(*GetSerializeContext());
  6597. AZStd::vector<char> xmlBuffer;
  6598. IO::ByteContainerStream<AZStd::vector<char> > xmlStream(&xmlBuffer);
  6599. {
  6600. ClassThatAllocatesMemoryInDefaultCtor obj;
  6601. ObjectStream* xmlObjStream = ObjectStream::Create(&xmlStream, *GetSerializeContext(), ObjectStream::ST_XML);
  6602. xmlObjStream->WriteClass(&obj);
  6603. xmlObjStream->Finalize();
  6604. }
  6605. xmlStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  6606. ClassThatAllocatesMemoryInDefaultCtor* deserialized = AZ::Utils::LoadObjectFromStream<ClassThatAllocatesMemoryInDefaultCtor>(xmlStream);
  6607. EXPECT_TRUE(deserialized);
  6608. if (deserialized)
  6609. {
  6610. delete deserialized;
  6611. }
  6612. EXPECT_EQ(ClassThatAllocatesMemoryInDefaultCtor::InstanceTracker::s_instanceCount, 0);
  6613. }
  6614. // Test that loading containers in-place clears any existing data in the
  6615. // containers (
  6616. template <typename T>
  6617. class GenericsLoadInPlaceHolder final
  6618. {
  6619. public:
  6620. AZ_RTTI((GenericsLoadInPlaceHolder, "{98328203-83F0-4644-B1F6-34DDF50F3416}", T));
  6621. static void Reflect(AZ::SerializeContext& sc)
  6622. {
  6623. sc.Class<GenericsLoadInPlaceHolder>()->Version(1)->Field("data", &GenericsLoadInPlaceHolder::m_data);
  6624. }
  6625. T m_data;
  6626. };
  6627. template <typename T>
  6628. class GenericsLoadInPlaceFixture
  6629. : public Serialization
  6630. {
  6631. public:
  6632. GenericsLoadInPlaceHolder<T> m_holder;
  6633. };
  6634. TYPED_TEST_CASE_P(GenericsLoadInPlaceFixture);
  6635. TYPED_TEST_P(GenericsLoadInPlaceFixture, ClearsOnLoadInPlace)
  6636. {
  6637. using DataType = decltype(this->m_holder);
  6638. DataType::Reflect(*this->GetSerializeContext());
  6639. // Add 3 items to the container
  6640. [[maybe_unused]] typename TypeParam::iterator insertIter{};
  6641. if constexpr (AZStd::same_as<TypeParam, AZStd::forward_list<int>>)
  6642. {
  6643. insertIter = this->m_holder.m_data.before_begin();
  6644. }
  6645. for (int i = 0; i < 3; ++i)
  6646. {
  6647. if constexpr (AZStd::same_as<TypeParam, AZStd::forward_list<int>>)
  6648. {
  6649. insertIter = this->m_holder.m_data.insert_after(insertIter, i);
  6650. }
  6651. else
  6652. {
  6653. this->m_holder.m_data.insert(this->m_holder.m_data.end(), i);
  6654. }
  6655. }
  6656. // Serialize the container
  6657. AZStd::vector<char> xmlBuffer;
  6658. IO::ByteContainerStream<AZStd::vector<char>> xmlStream(&xmlBuffer);
  6659. {
  6660. ObjectStream* xmlObjStream = ObjectStream::Create(&xmlStream, *this->GetSerializeContext(), ObjectStream::ST_XML);
  6661. xmlObjStream->WriteClass(&this->m_holder);
  6662. xmlObjStream->Finalize();
  6663. }
  6664. xmlStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  6665. // Put different data in a different instance
  6666. DataType got;
  6667. if constexpr (AZStd::same_as<TypeParam, AZStd::forward_list<int>>)
  6668. {
  6669. insertIter = got.m_data.before_begin();
  6670. }
  6671. for (int i = 3; i < 6; ++i)
  6672. {
  6673. if constexpr (AZStd::same_as<TypeParam, AZStd::forward_list<int>>)
  6674. {
  6675. insertIter = got.m_data.insert_after(insertIter, i);
  6676. }
  6677. else
  6678. {
  6679. got.m_data.insert(got.m_data.end(), i);
  6680. }
  6681. }
  6682. // Verify that the two containers are different
  6683. EXPECT_THAT(got.m_data, ::testing::Ne(this->m_holder.m_data));
  6684. // Deserialize the container into a new one
  6685. AZ::Utils::LoadObjectFromStreamInPlace(xmlStream, got, this->GetSerializeContext());
  6686. // Verify the two containers are the same
  6687. EXPECT_THAT(got.m_data, ::testing::ContainerEq(this->m_holder.m_data));
  6688. }
  6689. REGISTER_TYPED_TEST_CASE_P(GenericsLoadInPlaceFixture, ClearsOnLoadInPlace);
  6690. // The test ClearsOnLoadInPlace is run once for each type in this list
  6691. typedef ::testing::Types<
  6692. AZStd::vector<int>,
  6693. AZStd::list<int>,
  6694. AZStd::forward_list<int>,
  6695. AZStd::set<int>,
  6696. AZStd::unordered_set<int>,
  6697. AZStd::unordered_multiset<int>
  6698. > TypesThatShouldBeClearedWhenLoadedInPlace;
  6699. INSTANTIATE_TYPED_TEST_CASE_P(Clears, GenericsLoadInPlaceFixture, TypesThatShouldBeClearedWhenLoadedInPlace);
  6700. enum TestUnscopedSerializationEnum : int32_t
  6701. {
  6702. TestUnscopedSerializationEnum_Option1,
  6703. TestUnscopedSerializationEnum_Option2,
  6704. TestUnscopedSerializationEnum_Option3,
  6705. TestUnscopedSerializationEnum_Option5NotReflected = 4,
  6706. TestUnscopedSerializationEnum_Option4 = 3,
  6707. };
  6708. enum class TestScopedSerializationEnum
  6709. {
  6710. Option1,
  6711. Option2,
  6712. Option3,
  6713. Option4,
  6714. Option5NotReflected,
  6715. };
  6716. enum class TestUnsignedEnum : uint32_t
  6717. {
  6718. Option42 = 42,
  6719. };
  6720. }
  6721. namespace AZ
  6722. {
  6723. AZ_TYPE_INFO_SPECIALIZE(UnitTest::TestUnscopedSerializationEnum, "{83383BFA-F6DA-4124-BE4F-2FAAB7C594E7}");
  6724. AZ_TYPE_INFO_SPECIALIZE(UnitTest::TestScopedSerializationEnum, "{17341C5E-81C3-44CB-A40D-F97D49C2531D}");
  6725. AZ_TYPE_INFO_SPECIALIZE(UnitTest::TestUnsignedEnum, "{0F91A5AE-DADA-4455-B158-8DB79D277495}");
  6726. }
  6727. namespace UnitTest
  6728. {
  6729. enum class TestNoTypeInfoEnum
  6730. {
  6731. Zeroth,
  6732. Second = 2,
  6733. Fourth = 4,
  6734. };
  6735. struct NoTypeInfoNonReflectedEnumWrapper
  6736. {
  6737. AZ_TYPE_INFO(NoTypeInfoNonReflectedEnumWrapper, "{500D534D-4535-46FE-8D0C-7EC0782553F7}");
  6738. TestNoTypeInfoEnum m_value{};
  6739. };
  6740. struct TypeInfoReflectedEnumWrapper
  6741. {
  6742. AZ_TYPE_INFO(TypeInfoReflectedEnumWrapper, "{00ACD993-28B4-4951-91E8-16056EA8A8DA}");
  6743. TestScopedSerializationEnum m_value{};
  6744. };
  6745. class EnumTypeSerialization
  6746. : public LeakDetectionFixture
  6747. {
  6748. public:
  6749. void SetUp() override
  6750. {
  6751. LeakDetectionFixture::SetUp();
  6752. m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
  6753. }
  6754. void TearDown() override
  6755. {
  6756. m_serializeContext.reset();
  6757. LeakDetectionFixture::TearDown();
  6758. }
  6759. protected:
  6760. AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
  6761. };
  6762. TEST_F(EnumTypeSerialization, TestUnscopedEnumReflection_Succeeds)
  6763. {
  6764. m_serializeContext->Enum<TestUnscopedSerializationEnum>();
  6765. const AZ::SerializeContext::ClassData* enumClassData = m_serializeContext->FindClassData(azrtti_typeid<TestUnscopedSerializationEnum>());
  6766. ASSERT_NE(nullptr, enumClassData);
  6767. AZ::TypeId underlyingTypeId = AZ::TypeId::CreateNull();
  6768. AttributeReader attrReader(nullptr, enumClassData->FindAttribute(AZ::Serialize::Attributes::EnumUnderlyingType));
  6769. EXPECT_TRUE(attrReader.Read<AZ::TypeId>(underlyingTypeId));
  6770. EXPECT_EQ(azrtti_typeid<int32_t>(), underlyingTypeId);
  6771. // Unreflect Enum type
  6772. m_serializeContext->EnableRemoveReflection();
  6773. m_serializeContext->Enum<TestUnscopedSerializationEnum>();
  6774. m_serializeContext->DisableRemoveReflection();
  6775. enumClassData = m_serializeContext->FindClassData(azrtti_typeid<TestUnscopedSerializationEnum>());
  6776. EXPECT_EQ(nullptr, enumClassData);
  6777. }
  6778. TEST_F(EnumTypeSerialization, TestScopedEnumReflection_Succeeds)
  6779. {
  6780. m_serializeContext->Enum<TestScopedSerializationEnum>();
  6781. const AZ::SerializeContext::ClassData* enumClassData = m_serializeContext->FindClassData(azrtti_typeid<TestScopedSerializationEnum>());
  6782. ASSERT_NE(nullptr, enumClassData);
  6783. // Unreflect Enum type
  6784. m_serializeContext->EnableRemoveReflection();
  6785. m_serializeContext->Enum<TestScopedSerializationEnum>();
  6786. m_serializeContext->DisableRemoveReflection();
  6787. enumClassData = m_serializeContext->FindClassData(azrtti_typeid<TestScopedSerializationEnum>());
  6788. EXPECT_EQ(nullptr, enumClassData);
  6789. }
  6790. TEST_F(EnumTypeSerialization, TestEnumReflectionWithValues_Succeeds)
  6791. {
  6792. m_serializeContext->Enum<TestUnscopedSerializationEnum>()
  6793. ->Value("Option1", TestUnscopedSerializationEnum::TestUnscopedSerializationEnum_Option1)
  6794. ->Value("Option2", TestUnscopedSerializationEnum::TestUnscopedSerializationEnum_Option2)
  6795. ->Value("Option3", TestUnscopedSerializationEnum::TestUnscopedSerializationEnum_Option3)
  6796. ->Value("Option4", TestUnscopedSerializationEnum::TestUnscopedSerializationEnum_Option4)
  6797. ;
  6798. const AZ::SerializeContext::ClassData* enumClassData = m_serializeContext->FindClassData(azrtti_typeid<TestUnscopedSerializationEnum>());
  6799. ASSERT_NE(nullptr, enumClassData);
  6800. using EnumConstantBase = AZ::SerializeContextEnumInternal::EnumConstantBase;
  6801. using EnumConstantBasePtr = AZStd::unique_ptr<EnumConstantBase>;
  6802. AZStd::vector<AZStd::reference_wrapper<EnumConstantBase>> enumConstants;
  6803. enumConstants.reserve(4);
  6804. for (const AZ::AttributeSharedPair& attrPair : enumClassData->m_attributes)
  6805. {
  6806. if (attrPair.first == AZ::Serialize::Attributes::EnumValueKey)
  6807. {
  6808. auto enumConstantAttribute{ azrtti_cast<AZ::AttributeData<EnumConstantBasePtr>*>(attrPair.second.get()) };
  6809. ASSERT_NE(nullptr, enumConstantAttribute);
  6810. const EnumConstantBasePtr& sourceEnumConstant = enumConstantAttribute->Get(nullptr);
  6811. ASSERT_NE(nullptr, sourceEnumConstant);
  6812. enumConstants.emplace_back(*sourceEnumConstant);
  6813. }
  6814. }
  6815. ASSERT_EQ(4, enumConstants.size());
  6816. EXPECT_EQ("Option1", static_cast<EnumConstantBase&>(enumConstants[0]).GetEnumValueName());
  6817. EXPECT_EQ(0, static_cast<EnumConstantBase&>(enumConstants[0]).GetEnumValueAsUInt());
  6818. EXPECT_EQ("Option2", static_cast<EnumConstantBase&>(enumConstants[1]).GetEnumValueName());
  6819. EXPECT_EQ(1, static_cast<EnumConstantBase&>(enumConstants[1]).GetEnumValueAsUInt());
  6820. EXPECT_EQ("Option3", static_cast<EnumConstantBase&>(enumConstants[2]).GetEnumValueName());
  6821. EXPECT_EQ(2, static_cast<EnumConstantBase&>(enumConstants[2]).GetEnumValueAsUInt());
  6822. EXPECT_EQ("Option4", static_cast<EnumConstantBase&>(enumConstants[3]).GetEnumValueName());
  6823. EXPECT_EQ(3, static_cast<EnumConstantBase&>(enumConstants[3]).GetEnumValueAsUInt());
  6824. m_serializeContext->EnableRemoveReflection();
  6825. m_serializeContext->Enum<TestUnscopedSerializationEnum>();
  6826. m_serializeContext->DisableRemoveReflection();
  6827. }
  6828. TEST_F(EnumTypeSerialization, TestEnumFieldWithTypeInfoAndReflectedAsEnum_Succeeds)
  6829. {
  6830. m_serializeContext->Enum<TestScopedSerializationEnum>()
  6831. ->Value("Option1", TestScopedSerializationEnum::Option1)
  6832. ->Value("Option2", TestScopedSerializationEnum::Option2)
  6833. ->Value("Option3", TestScopedSerializationEnum::Option3)
  6834. ->Value("Option4", TestScopedSerializationEnum::Option4)
  6835. ;
  6836. m_serializeContext->Class<TypeInfoReflectedEnumWrapper>()
  6837. ->Field("m_value", &TypeInfoReflectedEnumWrapper::m_value)
  6838. ;
  6839. // The TestScopedSerializationEnum is explicitly reflected as an Enum in the SerializeContext and FindClassData
  6840. // should return the EnumType class data
  6841. const AZ::SerializeContext::ClassData* enumClassData = m_serializeContext->FindClassData(azrtti_typeid<TestScopedSerializationEnum>());
  6842. ASSERT_NE(nullptr, enumClassData);
  6843. EXPECT_EQ(azrtti_typeid<TestScopedSerializationEnum>(), enumClassData->m_typeId);
  6844. TypeInfoReflectedEnumWrapper testObject;
  6845. testObject.m_value = TestScopedSerializationEnum::Option3;
  6846. AZStd::vector<uint8_t> byteBuffer;
  6847. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  6848. AZ::ObjectStream* objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_BINARY);
  6849. objStream->WriteClass(&testObject);
  6850. objStream->Finalize();
  6851. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  6852. TypeInfoReflectedEnumWrapper loadObject;
  6853. const bool loadResult = AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadObject, m_serializeContext.get());
  6854. EXPECT_TRUE(loadResult);
  6855. EXPECT_EQ(TestScopedSerializationEnum::Option3, loadObject.m_value);
  6856. m_serializeContext->EnableRemoveReflection();
  6857. m_serializeContext->Class<TypeInfoReflectedEnumWrapper>();
  6858. m_serializeContext->Enum<TestScopedSerializationEnum>();
  6859. m_serializeContext->DisableRemoveReflection();
  6860. }
  6861. TEST_F(EnumTypeSerialization, TestEnumFieldWithTypeInfoAndNotReflectedAsEnum_Succeeds)
  6862. {
  6863. m_serializeContext->Class<TypeInfoReflectedEnumWrapper>()
  6864. ->Field("m_value", &TypeInfoReflectedEnumWrapper::m_value)
  6865. ;
  6866. // The TestScopedSerializationEnum is not reflected as an Enum in the SerializeContext, but has specialized AzTypeInfo
  6867. // So FindClassData should return the underlying type in this case, which is an int
  6868. const AZ::SerializeContext::ClassData* underlyingTypeClassData = m_serializeContext->FindClassData(azrtti_typeid<TestScopedSerializationEnum>());
  6869. ASSERT_NE(nullptr, underlyingTypeClassData);
  6870. EXPECT_EQ(azrtti_typeid<int>(), underlyingTypeClassData->m_typeId);
  6871. TypeInfoReflectedEnumWrapper testObject;
  6872. testObject.m_value = TestScopedSerializationEnum::Option3;
  6873. AZStd::vector<uint8_t> byteBuffer;
  6874. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  6875. AZ::ObjectStream* objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_BINARY);
  6876. objStream->WriteClass(&testObject);
  6877. objStream->Finalize();
  6878. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  6879. TypeInfoReflectedEnumWrapper loadObject;
  6880. const bool loadResult = AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadObject, m_serializeContext.get());
  6881. EXPECT_TRUE(loadResult);
  6882. EXPECT_EQ(TestScopedSerializationEnum::Option3, loadObject.m_value);
  6883. m_serializeContext->EnableRemoveReflection();
  6884. m_serializeContext->Class<TypeInfoReflectedEnumWrapper>();
  6885. m_serializeContext->DisableRemoveReflection();
  6886. }
  6887. TEST_F(EnumTypeSerialization, TestEnumFieldWithNoTypeInfo_Succeeds)
  6888. {
  6889. m_serializeContext->Class<NoTypeInfoNonReflectedEnumWrapper>()
  6890. ->Field("m_value", &NoTypeInfoNonReflectedEnumWrapper::m_value)
  6891. ;
  6892. static_assert(AZ::Internal::HasAZTypeInfo<TestNoTypeInfoEnum>::value, "Test enum type should not have AzTypeInfo");
  6893. NoTypeInfoNonReflectedEnumWrapper testObject;
  6894. testObject.m_value = TestNoTypeInfoEnum::Second;
  6895. AZStd::vector<uint8_t> byteBuffer;
  6896. AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
  6897. AZ::ObjectStream* objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, AZ::ObjectStream::ST_BINARY);
  6898. objStream->WriteClass(&testObject);
  6899. objStream->Finalize();
  6900. byteStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
  6901. NoTypeInfoNonReflectedEnumWrapper loadObject;
  6902. const bool loadResult = AZ::Utils::LoadObjectFromStreamInPlace(byteStream, loadObject, m_serializeContext.get());
  6903. EXPECT_TRUE(loadResult);
  6904. EXPECT_EQ(TestNoTypeInfoEnum::Second, loadObject.m_value);
  6905. m_serializeContext->EnableRemoveReflection();
  6906. m_serializeContext->Class<NoTypeInfoNonReflectedEnumWrapper>();
  6907. m_serializeContext->DisableRemoveReflection();
  6908. }
  6909. TEST_F(EnumTypeSerialization, LoadIntIntoEnumTypeInfoSpecialization_Succeeds)
  6910. {
  6911. AZStd::string_view typeInfoEnumWrapperObjStreamData = R"(<ObjectStream version="3">
  6912. <Class name="TypeInfoReflectedEnumWrapper" type="{00ACD993-28B4-4951-91E8-16056EA8A8DA}">
  6913. <Class name="int" field="m_value" value="72" type="{72039442-EB38-4d42-A1AD-CB68F7E0EEF6}"/>
  6914. </Class>
  6915. </ObjectStream>
  6916. )";
  6917. m_serializeContext->Class<TypeInfoReflectedEnumWrapper>()
  6918. ->Field("m_value", &TypeInfoReflectedEnumWrapper::m_value)
  6919. ;
  6920. // Validate that the "m_value" ClassElement reflected to the TypeInfoReflectedEnumWrapper class
  6921. // is set to the Type of TestScopedSerializationEnum and not the TypeId of int
  6922. // When using enum types in fields previously it always used the underlying type for reflection
  6923. // Now if the enum type is being used in a field and has specialized AzTypeInfo, it uses the specialized TypeID
  6924. const SerializeContext::ClassData* classData = m_serializeContext->FindClassData(azrtti_typeid<TypeInfoReflectedEnumWrapper>());
  6925. ASSERT_NE(nullptr, classData);
  6926. ASSERT_EQ(1, classData->m_elements.size());
  6927. EXPECT_EQ(azrtti_typeid<TestScopedSerializationEnum>(), classData->m_elements[0].m_typeId);
  6928. EXPECT_NE(azrtti_typeid<int>(), classData->m_elements[0].m_typeId);
  6929. AZ::IO::MemoryStream memStream(typeInfoEnumWrapperObjStreamData.data(), typeInfoEnumWrapperObjStreamData.size());
  6930. TypeInfoReflectedEnumWrapper testObject;
  6931. EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(memStream, testObject, m_serializeContext.get()));
  6932. EXPECT_EQ(72, static_cast<int>(testObject.m_value));
  6933. m_serializeContext->EnableRemoveReflection();
  6934. m_serializeContext->Class<TypeInfoReflectedEnumWrapper>();
  6935. m_serializeContext->DisableRemoveReflection();
  6936. }
  6937. struct TestUnsignedEnumWrapper
  6938. {
  6939. AZ_TYPE_INFO(TestUnsignedEnumWrapper, "{A5DD32CD-EC5B-4F0D-9D25-239EC76F1860}");
  6940. TestUnsignedEnum m_value{};
  6941. };
  6942. TEST_F(EnumTypeSerialization, VersionConverterRunOnEnum_ConvertsTypeSuccessfully)
  6943. {
  6944. AZStd::string_view typeInfoEnumWrapperObjStreamData = R"(<ObjectStream version="3">
  6945. <Class name="TestUnsignedEnumWrapper" type="{A5DD32CD-EC5B-4F0D-9D25-239EC76F1860}">
  6946. <Class name="unsigned int" field="m_value" value="234343" type="{43DA906B-7DEF-4ca8-9790-854106D3F983}"/>
  6947. </Class>
  6948. </ObjectStream>
  6949. )";
  6950. auto VersionConverter = [](AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) -> bool
  6951. {
  6952. if (classElement.GetVersion() < 1)
  6953. {
  6954. int enumIndex = classElement.FindElement(AZ_CRC("m_value"));
  6955. if (enumIndex == -1)
  6956. {
  6957. return false;
  6958. }
  6959. AZ::SerializeContext::DataElementNode& enumValueNode = classElement.GetSubElement(enumIndex);
  6960. TestUnsignedEnum oldValue{};
  6961. EXPECT_TRUE(enumValueNode.GetData(oldValue));
  6962. EXPECT_EQ(234343U, static_cast<std::underlying_type_t<TestUnsignedEnum>>(oldValue));
  6963. EXPECT_TRUE(enumValueNode.Convert<TestUnsignedEnum>(context));
  6964. EXPECT_TRUE(enumValueNode.SetData(context, TestUnsignedEnum::Option42));
  6965. }
  6966. return true;
  6967. };
  6968. m_serializeContext->Class<TestUnsignedEnumWrapper>()
  6969. ->Version(1, VersionConverter)
  6970. ->Field("m_value", &TestUnsignedEnumWrapper::m_value)
  6971. ;
  6972. AZ::IO::MemoryStream memStream(typeInfoEnumWrapperObjStreamData.data(), typeInfoEnumWrapperObjStreamData.size());
  6973. TestUnsignedEnumWrapper testObject;
  6974. EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(memStream, testObject, m_serializeContext.get()));
  6975. EXPECT_EQ(TestUnsignedEnum::Option42, testObject.m_value);
  6976. m_serializeContext->EnableRemoveReflection();
  6977. m_serializeContext->Class<TestUnsignedEnumWrapper>();
  6978. m_serializeContext->DisableRemoveReflection();
  6979. }
  6980. struct TestClassWithEnumField
  6981. {
  6982. AZ_TYPE_INFO(TestClassWithEnumField, "{F1F03A45-3E6D-44C3-A615-A556DEE18E94}");
  6983. TestUnsignedEnum m_value{};
  6984. AZStd::string m_strValue;
  6985. };
  6986. TEST_F(EnumTypeSerialization, LoadingOldVersionOfClassWithEnumFieldStoredUsingTheUnderlying_AndThatClassDoesNotHaveAVersionConverter_Succeeds)
  6987. {
  6988. AZStd::string_view testClassWithEnumFieldData = R"(<ObjectStream version="3">
  6989. <Class name="TestClassWithEnumField" type="{F1F03A45-3E6D-44C3-A615-A556DEE18E94}">
  6990. <Class name="unsigned int" field="m_value" value="42" type="{43DA906B-7DEF-4ca8-9790-854106D3F983}"/>
  6991. </Class>
  6992. </ObjectStream>
  6993. )";
  6994. m_serializeContext->Class<TestClassWithEnumField>()
  6995. ->Version(1)
  6996. ->Field("m_value", &TestClassWithEnumField::m_value)
  6997. ->Field("m_strValue", &TestClassWithEnumField::m_strValue)
  6998. ;
  6999. AZ::IO::MemoryStream memStream(testClassWithEnumFieldData.data(), testClassWithEnumFieldData.size());
  7000. TestClassWithEnumField testObject;
  7001. EXPECT_TRUE(AZ::Utils::LoadObjectFromStreamInPlace(memStream, testObject, m_serializeContext.get()));
  7002. EXPECT_EQ(TestUnsignedEnum::Option42, testObject.m_value);
  7003. m_serializeContext->EnableRemoveReflection();
  7004. m_serializeContext->Class<TestClassWithEnumField>();
  7005. m_serializeContext->DisableRemoveReflection();
  7006. }
  7007. struct TestClassWithEnumFieldThatSpecializesTypeInfo
  7008. {
  7009. AZ_TYPE_INFO(TestClassWithEnumFieldThatSpecializesTypeInfo, "{B7E066F4-3598-4678-A331-5AB8789CE391}");
  7010. TestUnsignedEnum m_value{};
  7011. };
  7012. TEST_F(EnumTypeSerialization, CloneObjectAZStdAnyOfEnum_SucceedsWithoutCrashing)
  7013. {
  7014. m_serializeContext->Class<TestClassWithEnumFieldThatSpecializesTypeInfo>()
  7015. ->Version(1)
  7016. ->Field("m_value", &TestClassWithEnumFieldThatSpecializesTypeInfo::m_value)
  7017. ;
  7018. AZStd::any testAny(AZStd::make_any<TestUnsignedEnum>(TestUnsignedEnum::Option42));
  7019. AZStd::any resultAny;
  7020. m_serializeContext->CloneObjectInplace(resultAny, &testAny);
  7021. auto resultEnum = AZStd::any_cast<TestUnsignedEnum>(&resultAny);
  7022. ASSERT_NE(nullptr, resultEnum);
  7023. EXPECT_EQ(TestUnsignedEnum::Option42, *resultEnum);
  7024. m_serializeContext->EnableRemoveReflection();
  7025. m_serializeContext->Class<TestClassWithEnumFieldThatSpecializesTypeInfo>();
  7026. m_serializeContext->DisableRemoveReflection();
  7027. }
  7028. }
  7029. namespace UnitTest
  7030. {
  7031. class AssociativeContainerSerializationFixture
  7032. : public LeakDetectionFixture
  7033. {
  7034. public:
  7035. AssociativeContainerSerializationFixture()
  7036. {
  7037. m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
  7038. m_serializeContext->RegisterGenericType<AZStd::set<int>>();
  7039. m_serializeContext->RegisterGenericType<AZStd::map<int, int>>();
  7040. m_serializeContext->RegisterGenericType<AZStd::unordered_set<int>>();
  7041. m_serializeContext->RegisterGenericType<AZStd::unordered_map<int, int>>();
  7042. }
  7043. ~AssociativeContainerSerializationFixture() override
  7044. {
  7045. m_serializeContext.reset();
  7046. }
  7047. protected:
  7048. AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
  7049. };
  7050. TEST_F(AssociativeContainerSerializationFixture, GetAssociativeType_ReturnsCorrectAssociativeStructure)
  7051. {
  7052. using AssociativeType = AZ::Serialize::IDataContainer::IAssociativeDataContainer::AssociativeType;
  7053. const auto setClassData = m_serializeContext->FindClassData(azrtti_typeid<AZStd::set<int>>());
  7054. ASSERT_NE(nullptr, setClassData);
  7055. const auto setDataContainer = setClassData->m_container;
  7056. ASSERT_NE(nullptr, setDataContainer);
  7057. const auto setAssociativeContainer = setClassData->m_container->GetAssociativeContainerInterface();
  7058. ASSERT_NE(nullptr, setClassData->m_container->GetAssociativeContainerInterface());
  7059. EXPECT_EQ(AssociativeType::Set, setAssociativeContainer->GetAssociativeType());
  7060. const auto mapClassData = m_serializeContext->FindClassData(azrtti_typeid<AZStd::map<int, int>>());
  7061. ASSERT_NE(nullptr, mapClassData);
  7062. const auto mapDataContainer = mapClassData->m_container;
  7063. ASSERT_NE(nullptr, mapDataContainer);
  7064. const auto mapAssociativeContainer = mapClassData->m_container->GetAssociativeContainerInterface();
  7065. ASSERT_NE(nullptr, mapClassData->m_container->GetAssociativeContainerInterface());
  7066. EXPECT_EQ(AssociativeType::Map, mapAssociativeContainer->GetAssociativeType());
  7067. const auto unorderedSetClassData = m_serializeContext->FindClassData(azrtti_typeid<AZStd::unordered_set<int>>());
  7068. ASSERT_NE(nullptr, unorderedSetClassData);
  7069. const auto unorderedSetDataContainer = unorderedSetClassData->m_container;
  7070. ASSERT_NE(nullptr, unorderedSetDataContainer);
  7071. const auto unorderedSetAssociativeContainer = unorderedSetClassData->m_container->GetAssociativeContainerInterface();
  7072. ASSERT_NE(nullptr, unorderedSetClassData->m_container->GetAssociativeContainerInterface());
  7073. EXPECT_EQ(AssociativeType::UnorderedSet, unorderedSetAssociativeContainer->GetAssociativeType());
  7074. const auto unorderedMapClassData = m_serializeContext->FindClassData(azrtti_typeid<AZStd::unordered_map<int, int>>());
  7075. ASSERT_NE(nullptr, unorderedMapClassData);
  7076. const auto unorderedMapDataContainer = unorderedMapClassData->m_container;
  7077. ASSERT_NE(nullptr, unorderedMapDataContainer);
  7078. const auto unorderedMapAssociativeContainer = unorderedMapClassData->m_container->GetAssociativeContainerInterface();
  7079. ASSERT_NE(nullptr, unorderedMapClassData->m_container->GetAssociativeContainerInterface());
  7080. EXPECT_EQ(AssociativeType::UnorderedMap, unorderedMapAssociativeContainer->GetAssociativeType());
  7081. }
  7082. }