From 617f9908e31bde9c0bb38b0aaf9af47be5af462e Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 2 Jul 2020 14:11:51 +0200 Subject: [PATCH] Add Active Record Marshal forward compatibility tests This is following a recent discussion on Basecamp. So far Rails haven't tried to preserve Marshal compatibilty of Active Record instances, and it probably shouldn't as it isn't as controllable as other serialization formats. However it's common to store ActiveRecord instances in Rails.cache, and when the Marshal format changes, it causes problems during Rails upgrade. Process using the new Rails version might not be able to deserialize the existing cache, and also older process that weren't restarted yet my fail to load the cache entries written by newer processes. The goal of this PR is not to freeze the Marshal format, but to have a better visibility when it changes, so that's it's done on purpose with good reasons rather than accidentally. Note that this only test forward compatibility (AR vN reading entries written by AR vN-1), ideally we'd also test backward compatibility (AR vN-1 reading entries written by AR vN), but it means installing and loading and older Active Record as part of the test suite. --- .../test/cases/marshal_serialization_test.rb | 39 ++++++++++++++++++ .../Mysql2/rails_6_0_topic.dump | Bin 0 -> 1901 bytes .../Mysql2/rails_6_0_topic_associations.dump | Bin 0 -> 3916 bytes .../PostgreSQL/rails_6_0_topic.dump | Bin 0 -> 1886 bytes .../rails_6_0_topic_associations.dump | Bin 0 -> 3897 bytes .../SQLite/rails_6_0_topic.dump | Bin 0 -> 1874 bytes .../SQLite/rails_6_0_topic_associations.dump | Bin 0 -> 3933 bytes 7 files changed, 39 insertions(+) create mode 100644 activerecord/test/cases/marshal_serialization_test.rb create mode 100644 activerecord/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump create mode 100644 activerecord/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump create mode 100644 activerecord/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump create mode 100644 activerecord/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump create mode 100644 activerecord/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump create mode 100644 activerecord/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump diff --git a/activerecord/test/cases/marshal_serialization_test.rb b/activerecord/test/cases/marshal_serialization_test.rb new file mode 100644 index 0000000000000..a48aa2b59d640 --- /dev/null +++ b/activerecord/test/cases/marshal_serialization_test.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require "cases/helper" +require "models/topic" +require "models/reply" + +class MarshalSerializationTest < ActiveRecord::TestCase + fixtures :topics + + def test_deserializing_rails_6_0_marshal_basic + topic = Marshal.load(marshal_fixture("rails_6_0_topic")) + + assert_not_predicate topic, :new_record? + assert_equal 1, topic.id + assert_equal "The First Topic", topic.title + assert_equal "Have a nice day", topic.content + end + + def test_deserializing_rails_6_0_marshal_with_loaded_association_cache + topic = Marshal.load(marshal_fixture("rails_6_0_topic_associations")) + + assert_not_predicate topic, :new_record? + assert_equal 1, topic.id + assert_equal "The First Topic", topic.title + assert_equal "Have a nice day", topic.content + end + + private + def marshal_fixture(file_name) + File.binread(marshal_fixture_path(file_name)) + end + + def marshal_fixture_path(file_name) + File.expand_path( + "support/marshal_compatibility_fixtures/#{ActiveRecord::Base.connection.adapter_name}/#{file_name}.dump", + TEST_ROOT + ) + end +end diff --git a/activerecord/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump b/activerecord/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump new file mode 100644 index 0000000000000000000000000000000000000000..9452aaa5b3dd7deb3d04b3733449d0ad972c15e4 GIT binary patch literal 1901 zcmaJ?&2Aev5LSO6X;+s2n!+}kII7YVC=v^b4+X-#(6uXg0UHHkIY6NULG6w$#uT~X za^=WEfxJ^+!02Q2A^HHlxWipZv1~WeVL8JY&fhmPUspBpyE+lkDp{opE}4Nyo4A7% zx7LV$W+ByNdoQwL1jjlCNyy&p<^*gxsGO2#3)e^dYCIP?S@ zo-T-Y#|aP;DhuaeJhDO)^g*OTt2U|8G~yE6L5iWUqK+rS)j6QwZ``*^JopgFF7f+t zE|lEyO2zLZse+2-i#Z)OeJiYla)1$&!@`F*dANk^Yo!2V)M_v0i3O8lnElim9@*n@ z`d&`igyhr-rbeAtgQa#*ZwJfbi+{uBD$ndd8>aZMun|1EC2$iqx26Ix(YRi(R z7VFL9&uBS=^C-~PQlzm^3d`*-nNcedR@XwzcwR61En+20;sw^c2GiayYWSAR>{i_;)AmI_MEQ0f zh0RCZ0W>@*Jf2pYVhLSiMK$zwWlz+!zk(*~GBE{kvqwNb|mHUbAZ#|b%G zGwn%S>p-PE*Kiz*i)n*Cz}%$#40i~#I*SJA JtdtOo(tqD@QpNxP literal 0 HcmV?d00001 diff --git a/activerecord/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump b/activerecord/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump new file mode 100644 index 0000000000000000000000000000000000000000..251e2fdc9557cd16dd9270f09c89cc941b18362a GIT binary patch literal 3916 zcma)9+j1Mn5e1VJKmfdev=m-sOE6^7vMJK5i)Cx3QfZ13Ohlw5i=dnY4_kxX0Wr~X z2iglM2zJVq_q^sS@|GV^C60PTC-A9_mop% z74qeY9Y{w9ZXGKTMS*I^kqkAvyyZmdSng?8dW>z2zU<2=&kG0aYUcBxUPzFUdPd(V6LZy9+l__+DC(Vnej#Q*(@fHaG zP{Qt~=69MEG22OPc$yrSv2E@9 z5@*!@mMeOZ3_={U9Y%q0qP>3j!W)tqOIG`Ejej`JXDmKz@i{g1-$tz>;;5?w+ZRXa z9{j=t!<$BJWym0pgz{|Rx`7NsV+}1fYV#+7iX!RT+D{GqIBQ_)r3WICO?4!pSe28l zEr_k++(>NB6JdmS3-=eK%!cDrV6PcRBTzoVUTTixK5}AeM`RRKI%jMzd?#6KxxLMCeaj zd%N4(i;w&QaAN?Qc%O}|WQ(NRe?eSr2Zs%v^5bMhR~ofBb=1>AB+{c8%B<-10(~rp z?l=#m_qFz<@W;l%A&Y_Rc}j-1qvKSU=H=oT7)3s>d1aa}H2I>pQ2;c5;vabH$qNt> z`|3q35rk7ZXbl$jL;z3QNE?F@P!@)iF^mmxipHl22NtEnK*zn&YTiL~Bk9^Ai5Fc2 zR^pzUA&p}&%B?0q&DAoD;RrziP^ zL}=75xrU8A9lKFi`OlGMn~pw8wVuk6M$C!^)w6T|S$X}S`>$S}6<=vzHfqxc&25O( z&*VlU=2vGob1SbA2)OAJ;_!1O4-Qz-V7^sWIrZxk{~CVq-)ySacW-7hpi%p1 zV`HPbBaUTNRDI>hsw?`X&CShHYH=22fJ+8sDt8`!jECO|3?q^S29%z`1!!Yf;QcKs zus8*Z#3Q@QmtPP5{qv2XM^1s{EXyD_$WuwP&(gF!-4+Zu$Tpv*)r)sp^yty$WfcIu-k3T*Gl};w2c5`{JP5Xl zH_ahYtMY7#kmlM^!c=mocDizqXEVe6I$*c6b!6);GpY$%)t>PC6U0`5Z?tAnyvn3c zd>K#!T8tX`U*yK#TMNo(pu5 zeoITVOe?f{z?WM^zJje*`K4BYu22P|HR4UjZwq`N@Ho(R&#*A}rPus^S?zW(RhFdOK17X99$ z?f(O8dT3Ey<>?!hqa8dAy#K+XM}S)5gk-y2i}ub!haR7$4dKMsiu_Y5@$1$wun2nt zVK>yqFy3p3H@`8+u?36?>IkQ?pUXZyV{>FWnfASY9j(BXXx+LmG01#K;ChZC2*}w9 zJx=<3on3y*X1DwH1ad5VvqOY7vM~Ypp-3bQCBiJSMCTBfNpvta*pZH%E|BMW(p3g7 z3j{Gw4uwIOBjq2XeZe@aE@lv`+|U9s3**qyJuv(o3*z=A!3G zk4qzfC9=L3{r9%=_vz@Jp$zwN!%0bfCN4fBB#*6#P^ZM`0 zJ^y{6{lha_*=pu=4`0NHO4Kj#-F?1S;NQ{@{4o;fNyg5}ghJ5`WCv049ps6V3{)8U zr_Fc||93IM|5%`@zcy*=?@e3{(y_umQBfBu`iQ3f#^x}yVcbT$ZspkgSX+qIEa^@s zluZQp}@B^05AdkA)xnUBrwm2A}1Q~hX5w- zEr5cZpc7bFm`pDVxz`oA6d?OrxcAJrVGPR?gG8dA_ zr!hgsV}gGP1z(<5D<>LzXye-8r5C;@Mr4lL^v6Wi7SiP#K=scFT$5N+@vkj@&*Dtw{s(kn%eepm literal 0 HcmV?d00001 diff --git a/activerecord/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump b/activerecord/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump new file mode 100644 index 0000000000000000000000000000000000000000..cdfd36b38925de171d3f188986a5e6f8cb89e395 GIT binary patch literal 1886 zcma)7-EJF26b=%yz3VzoLQzuDrj`pxsB*N8iiFN`F`>cgN~sEsK|;A0jdxG&A?ulC zcGj&EA@v1#7A|;!z63Ws3Rj%jwVl`rh{#fA&Yu78J7+#@Xz&L*lkpa8F@K5Fk<(M`%1~vy5_(xzs9vCd*@yqC2E=BCTxE$p|$<%KMf3-vAHa#_0h3 zA&#UyZHl#!DqgFo%Hfm>R-;CECkR_XxG6vQJL+zU!j84! zN=z!t@a|F}h`RUYpK&5&%0-eG%ySok?L^)78zZen#kHz}va0Y`Wsd=#X{C@FtJP5= zGK(e$_)h0`WbpL+6M&b|F~G5~IFJ*hsIpn+MPb`Rt%{sml2@J|ta`5MnVVJBkkw`? za!Uw{q%!(?)#!hxbG-p~Vok^?;(;pB{34R)-eLi=lPk zH(5-?GG}!Sx7UGh?Nv+-pRMOj#?-o>j$WKR(`hkLbz+gDZ;2W#QiL6*hd)!pc}$JS zAi$5~D$QHMDOvqbIxG2G59}|s=ELjmP0hmvE1>lb&Egb*mM7o?0Gvy&`*QYA# z-W`mw)0ZZvgWs^mXLDC&NaI5n2)BC%ts&S^RiVm+z6u1!}|faeI` z+WhO@`{VH+Sq;1kt?=fw5V%jC!r@mC1eK@NxuCWj2Eo%F{hoYTDJ&RN-5&IMz0Pwn z#g6DG8Dl3AGymY=z@K|t;Sz;kp;G@glDIbhEBbO{9ewh71ALM#v8VGD^mJK6J}SaT zt&_d|_kaHWTdx*=>NHk~a6{vAMuqX#~7>yr6!pG_Ti z_z+)fgWQpm$Fzh3QgIj7ggvH>q|Gg8eJY z&v910DMT^YWNxczmCpJ!`U&RN=o!*8cAt^*Igy^?^HN@v3%3vZS89AXh{u#{nqne1{sC7XO&S0I literal 0 HcmV?d00001 diff --git a/activerecord/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump b/activerecord/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump new file mode 100644 index 0000000000000000000000000000000000000000..c0b4019c971c33077f48ce6be5297a36b85dfc07 GIT binary patch literal 3897 zcma)9TW=f36{diK6iMqEySg~BS=yG9D3aHg`~ zJI$skkY`RPT^)KhW+IM5b(q95((KN<8>>^ft3By6w%%XamvNDo4%ofi@{V}h9k6VR zsNJgkFxRM;lviZM7fsFX=GdFvj%2J6#PV2%Wi~|}=%6B{1B+EDa)mF=hp$dltS0ak zir`p6@7LycoR#Id>o-~DP#&wmUnv)|zaQDS3_O2%FmKc=v5I|J!X_3Tj9Xf$H$#(La0|u*6U+68%6QO)ZcwQ)@$ecj4jr!DCsNz@# zjt;UzDZBXV)W(c$>L8FXtPa*a(TQakF}A0p_&AjNuXY%F+1O%iOT@CNP9#oM)l@GW zJ9VgoBywWVGs&OiC1>~PZOd+hU6a0uVt811*`}}an?6{bVFTQ7H9Qvp2bJak2>lE8 z%ql}AeDzj(tum`R&gm1!X_eRnMaf}ooL?muzzSO>&91+PJdZEW)a=2i-q;M&eYd{5 zv#I^$Bq#wz2EM7+SYJgpOZxE7Fu3Ew5RqGbna=1gETc|3I*dhj4?~#{oldAvWzSUC zL3TrHUy9&TvqpV3lpSBm$Z>U&$#vjm)F1gr{&M;OEG2>Z zK9O+HhzweSh8+>Y%npLcpbM0l9%TS(1G%y>Xv%>}0vzz=x z2sP@rJ;O%6PQ19Sf;WiHRac*6Qb(ezk+8A>{KVvc7T#^O|J5n7@>?CqtI-1IK3-!_ zo-@nJB<14*W_e;+Yb*GF{48VWBPg4Fva+&L+ZLy?CTf9lWz7@a%IfNBr6(5?k!V>&h1aSr8?4y9wj>9|Nj7Ff)Ls%)Ng zsF1k@(r3S}SUBye<_{_yI5%|zFyaqYk$*~6{+X!;saREHbA(9Nt`a7TLbThK7e#iX z7eWW@X+Bk~UosG_pgTltmG~E}2_&Z~>9atFRKWKQ08n_+Yo_0^2#;mlDw+a> zKk7sy#v_QZFdkpb(Nk5TwMM;Wf^8qQB=E9mtLdX!3>xrg zEJj}f6T2eJCeJNmsbBxQu=wsDO9kYG`xbp|(XT9`M*Sy2O&b<%Hfc*0=mmzYiu4xoWrg&gc=KLP6W5c zPK?$f66p>@iP3n>(KW<*5=SW4POKBR4b=I*^pt_h3}Krudz(R+Bo&;ZIzc(iZspLb zyvPDE58=qw9W*z;NDYft3(B0zte!frrJv&5G(m6D5|-H?Q$(JRZPV+aY0#QxHg1Ba z8k^=W?MR^9ApT^iS$$YG_8=TL5t=e&Y*!$ALMTWPotuqDpo1bVA`9`5MqhM+KtF5C z5a)iHm(^F4v2V@#rZ196me5n8weyq23;hU z2jA!%aLLpV)Me!~(`-XqWRZ5bJzoS8~Rct8%Qgbz$ZsB|<%i5sKEJU5Uj z^5`@)Vg;{N1Ti6}o0GR-+LO+2S{MV8DOm>n zu8B?=^#wOD6A9q8qE`gQd-vx`<{2}nFI^vQbFJLUbkS=s=9$4h^XLmsHr~w=?t}`V zm)LG+R`+|;zzP`9g2&<$L>FDsV{GL!cF`fbG|T74Lf4}q@<(5E6xp6Ad^FcF75SlA z&6#yZYW#8f`ut4Ac_KSV1Iy9^cd|*598xv^6A8satTYRIzZ4QZ!O}&NDs6aKht=%z zG}USa6&5FD$cpD>T|X-o1DDsC1@57SG!~GtQ03KKJ#2F>#rqr(+AW8BDc6V}!$)8n zkLGtPP0csUhOR}but33CXqBfMX+OlC8HgA!x_^UiNrcII~QfT>jfWOg` z@~#bAO6lQXFzCPHE9mpS6e08@zIKMgp;I0=d4q4LK^xK9#s~}Te=@?lG#P=Hentq? z)qKG3YdWBCiwy;OK4S4~;Q9TLPevYjG9LQgX#D(Xg??G%!nO7UIb9(8LO~M~j6dMOMEC8 zpB4JN*e+A@=-Q0U*X%|x56@U;xHin->d1KEVKoN#$`Re7Jf{2|E-PkK9xgH2IEF~H F{sn>bKV$#^ literal 0 HcmV?d00001 diff --git a/activerecord/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump b/activerecord/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump new file mode 100644 index 0000000000000000000000000000000000000000..abe7f1544dace577b5d7bf1622c94a4151faee35 GIT binary patch literal 3933 zcma)9>vP+<5qD-fk|o8@Cbg5?U35y^OD>f|$##+h+I0PhCTio$!%EYRI_1D5Y@wkE z9SPdexi`~K{o4PxpZWtS$)fE%Ji?e*>@I-a-#+lGY0b(V-B;c`o2O8oxRLa99C$o!s&Z@$+EJ@?6BdZuys`cCD!V0xLZ0 zX!a~)f0J&-*tQNs3H>_U^hMvuC}wQ$^$TU>+K@1ww?iWjWmIBw)W=Cx3?YYADE34k z?MI-Fl(8R?2oEJL_s0I8W+nN-3p%X4FAr51)Js#@-@nrjM8CdFbSRb`7gDo< zhzTn{&m zy~@jUMz?Wwb=2395!pQ~Wk&S-kv^6~TinjJ9O68?*Ou0S6ye#)+O@?<_5&qj*VD;R zR|RfPLiJN3VcJU;XZs?8{agfrbv)P?hLkbhEE-DIQYi-}<-kdMw~+xCIR2BUF-B@wWXriRMV_r_r3^k$n1#Y>?WT; zce{4Ww`>&X#5X+^zDMA!dip5SdJg#Q+U=&}tks>z^~R%WW1TghutsCG*<4$5oS{S> z@9o+$B%Hd_z;7rqV$FjbmICK`9lyp#rfYS{S# z&f^9#l!J|$x(pH4v>!!;70Dw4N-qEcv@ss=eFg_i&Y>Z-UK6%>Tz8t)Mw2xhwz0O_ zbQ)_<9u2LR2g_$APNz-_RMzZ%E+)o_ov~J=kB}$CzKCUsmC0s5DzmTX*y7FImj^nM zt_8H~A>}w=u@kDWWzvyCA{NMoqgvu%w}+bFDf7EotpN1+iYoBmQiXqKQ+lda71$CX zthJ|vEg4Yl_2g-RT^)wqTegLc7V&&Ch6|a9BO?QSoHj}EJN(^J0*UX%6!Ecq5v4#0!A!# zYXThn{^=B3Kue&GaCP^+9MDTPOSZ=8Fc`E@Cwv*3NDm}ho3995?~zD>PdB9}Y4_1$ z-<+|z`vZ3ZW)9Ze7&tJlL2D6>Kgt$!N0L_eRbmH{@(;$$(ve;T6hy`*e z48km_@EElXhr{f84&KU-9T4-Fk3HQ-bMtL#c=Tg9%(2X>vHL~_X<*C%&+pR$nE3}& zglYh>`OV07aUDCGw$WBGwgXH%5*%(EurkuDHmMsjh~I6*vWytp75#!$3Q|nQ3R;CO zS^yC{2%t1v<5OgYlb(#Q@4dXP(Lot|XV=_+kGZ zn)+Xg^sf$G`A-LLg{(7iPn78)LU-uODVs$zht?VuzdOa|#>!&MW=J0##L~p4Q@q{+ zw8sv2_Y)PM%hRJ5#i+x4HG;%e#!%!>HT*w;`yrlpr4eX}M2Y`_4BrAS@sI%$+!UOE z!op;9IS9R;zykom*R6Dmp1q)EjlAOXn*(N1BnHnj!2u?Wb4KI7ie8J(;7ti^_E#-IILdn+5$rCRg!?K;%G!LTkvYuMA$6ugg z#GTUwx8p4-4-w|bkZzi(TI?pJxx#ktNCxhK@QjWInmx>KGcr#ub+j_(V(R(KCkS|S z_aC5Oe S;%hCw?(hwVKXUkEHT8cKt+$o{ literal 0 HcmV?d00001