1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866 |
- package validator
- import (
- "bytes"
- "context"
- "database/sql"
- "database/sql/driver"
- "encoding/base64"
- "encoding/json"
- "fmt"
- "path/filepath"
- "reflect"
- "strings"
- "testing"
- "time"
- "github.com/go-playground/locales/en"
- "github.com/go-playground/locales/fr"
- "github.com/go-playground/locales/nl"
- ut "github.com/go-playground/universal-translator"
- . "gopkg.in/go-playground/assert.v1"
- )
- // NOTES:
- // - Run "go test" to run tests
- // - Run "gocov test | gocov report" to report on test converage by file
- // - Run "gocov test | gocov annotate -" to report on all code and functions, those ,marked with "MISS" were never called
- //
- // or
- //
- // -- may be a good idea to change to output path to somewherelike /tmp
- // go test -coverprofile cover.out && go tool cover -html=cover.out -o cover.html
- //
- //
- // go test -cpuprofile cpu.out
- // ./validator.test -test.bench=. -test.cpuprofile=cpu.prof
- // go tool pprof validator.test cpu.prof
- //
- //
- // go test -memprofile mem.out
- type I interface {
- Foo() string
- }
- type Impl struct {
- F string `validate:"len=3"`
- }
- func (i *Impl) Foo() string {
- return i.F
- }
- type SubTest struct {
- Test string `validate:"required"`
- }
- type TestInterface struct {
- Iface I
- }
- type TestString struct {
- BlankTag string `validate:""`
- Required string `validate:"required"`
- Len string `validate:"len=10"`
- Min string `validate:"min=1"`
- Max string `validate:"max=10"`
- MinMax string `validate:"min=1,max=10"`
- Lt string `validate:"lt=10"`
- Lte string `validate:"lte=10"`
- Gt string `validate:"gt=10"`
- Gte string `validate:"gte=10"`
- OmitEmpty string `validate:"omitempty,min=1,max=10"`
- Sub *SubTest
- SubIgnore *SubTest `validate:"-"`
- Anonymous struct {
- A string `validate:"required"`
- }
- Iface I
- }
- type TestUint64 struct {
- Required uint64 `validate:"required"`
- Len uint64 `validate:"len=10"`
- Min uint64 `validate:"min=1"`
- Max uint64 `validate:"max=10"`
- MinMax uint64 `validate:"min=1,max=10"`
- OmitEmpty uint64 `validate:"omitempty,min=1,max=10"`
- }
- type TestFloat64 struct {
- Required float64 `validate:"required"`
- Len float64 `validate:"len=10"`
- Min float64 `validate:"min=1"`
- Max float64 `validate:"max=10"`
- MinMax float64 `validate:"min=1,max=10"`
- Lte float64 `validate:"lte=10"`
- OmitEmpty float64 `validate:"omitempty,min=1,max=10"`
- }
- type TestSlice struct {
- Required []int `validate:"required"`
- Len []int `validate:"len=10"`
- Min []int `validate:"min=1"`
- Max []int `validate:"max=10"`
- MinMax []int `validate:"min=1,max=10"`
- OmitEmpty []int `validate:"omitempty,min=1,max=10"`
- }
- func AssertError(t *testing.T, err error, nsKey, structNsKey, field, structField, expectedTag string) {
- errs := err.(ValidationErrors)
- found := false
- var fe FieldError
- for i := 0; i < len(errs); i++ {
- if errs[i].Namespace() == nsKey && errs[i].StructNamespace() == structNsKey {
- found = true
- fe = errs[i]
- break
- }
- }
- EqualSkip(t, 2, found, true)
- NotEqualSkip(t, 2, fe, nil)
- EqualSkip(t, 2, fe.Field(), field)
- EqualSkip(t, 2, fe.StructField(), structField)
- EqualSkip(t, 2, fe.Tag(), expectedTag)
- }
- func AssertDeepError(t *testing.T, err error, nsKey, structNsKey, field, structField, expectedTag, actualTag string) {
- errs := err.(ValidationErrors)
- found := false
- var fe FieldError
- for i := 0; i < len(errs); i++ {
- if errs[i].Namespace() == nsKey && errs[i].StructNamespace() == structNsKey && errs[i].Tag() == expectedTag && errs[i].ActualTag() == actualTag {
- found = true
- fe = errs[i]
- break
- }
- }
- EqualSkip(t, 2, found, true)
- NotEqualSkip(t, 2, fe, nil)
- EqualSkip(t, 2, fe.Field(), field)
- EqualSkip(t, 2, fe.StructField(), structField)
- }
- func getError(err error, nsKey, structNsKey string) FieldError {
- errs := err.(ValidationErrors)
- var fe FieldError
- for i := 0; i < len(errs); i++ {
- if errs[i].Namespace() == nsKey && errs[i].StructNamespace() == structNsKey {
- fe = errs[i]
- break
- }
- }
- return fe
- }
- type valuer struct {
- Name string
- }
- func (v valuer) Value() (driver.Value, error) {
- if v.Name == "errorme" {
- panic("SQL Driver Valuer error: some kind of error")
- // return nil, errors.New("some kind of error")
- }
- if len(v.Name) == 0 {
- return nil, nil
- }
- return v.Name, nil
- }
- type MadeUpCustomType struct {
- FirstName string
- LastName string
- }
- func ValidateCustomType(field reflect.Value) interface{} {
- if cust, ok := field.Interface().(MadeUpCustomType); ok {
- if len(cust.FirstName) == 0 || len(cust.LastName) == 0 {
- return ""
- }
- return cust.FirstName + " " + cust.LastName
- }
- return ""
- }
- func OverrideIntTypeForSomeReason(field reflect.Value) interface{} {
- if i, ok := field.Interface().(int); ok {
- if i == 1 {
- return "1"
- }
- if i == 2 {
- return "12"
- }
- }
- return ""
- }
- type CustomMadeUpStruct struct {
- MadeUp MadeUpCustomType `validate:"required"`
- OverriddenInt int `validate:"gt=1"`
- }
- func ValidateValuerType(field reflect.Value) interface{} {
- if valuer, ok := field.Interface().(driver.Valuer); ok {
- val, err := valuer.Value()
- if err != nil {
- // handle the error how you want
- return nil
- }
- return val
- }
- return nil
- }
- type TestPartial struct {
- NoTag string
- BlankTag string `validate:""`
- Required string `validate:"required"`
- SubSlice []*SubTest `validate:"required,dive"`
- Sub *SubTest
- SubIgnore *SubTest `validate:"-"`
- Anonymous struct {
- A string `validate:"required"`
- ASubSlice []*SubTest `validate:"required,dive"`
- SubAnonStruct []struct {
- Test string `validate:"required"`
- OtherTest string `validate:"required"`
- } `validate:"required,dive"`
- }
- }
- type TestStruct struct {
- String string `validate:"required" json:"StringVal"`
- }
- func StructValidationTestStructSuccess(sl StructLevel) {
- st := sl.Current().Interface().(TestStruct)
- if st.String != "good value" {
- sl.ReportError(st.String, "StringVal", "String", "badvalueteststruct", "good value")
- }
- }
- func StructValidationTestStruct(sl StructLevel) {
- st := sl.Current().Interface().(TestStruct)
- if st.String != "bad value" {
- sl.ReportError(st.String, "StringVal", "String", "badvalueteststruct", "bad value")
- }
- }
- func StructValidationNoTestStructCustomName(sl StructLevel) {
- st := sl.Current().Interface().(TestStruct)
- if st.String != "bad value" {
- sl.ReportError(st.String, "String", "", "badvalueteststruct", "bad value")
- }
- }
- func StructValidationTestStructInvalid(sl StructLevel) {
- st := sl.Current().Interface().(TestStruct)
- if st.String != "bad value" {
- sl.ReportError(nil, "StringVal", "String", "badvalueteststruct", "bad value")
- }
- }
- func StructValidationTestStructReturnValidationErrors(sl StructLevel) {
- s := sl.Current().Interface().(TestStructReturnValidationErrors)
- errs := sl.Validator().Struct(s.Inner1.Inner2)
- if errs == nil {
- return
- }
- sl.ReportValidationErrors("Inner1.", "Inner1.", errs.(ValidationErrors))
- }
- func StructValidationTestStructReturnValidationErrors2(sl StructLevel) {
- s := sl.Current().Interface().(TestStructReturnValidationErrors)
- errs := sl.Validator().Struct(s.Inner1.Inner2)
- if errs == nil {
- return
- }
- sl.ReportValidationErrors("Inner1JSON.", "Inner1.", errs.(ValidationErrors))
- }
- type TestStructReturnValidationErrorsInner2 struct {
- String string `validate:"required" json:"JSONString"`
- }
- type TestStructReturnValidationErrorsInner1 struct {
- Inner2 *TestStructReturnValidationErrorsInner2
- }
- type TestStructReturnValidationErrors struct {
- Inner1 *TestStructReturnValidationErrorsInner1 `json:"Inner1JSON"`
- }
- type StructLevelInvalidErr struct {
- Value string
- }
- func StructLevelInvalidError(sl StructLevel) {
- top := sl.Top().Interface().(StructLevelInvalidErr)
- s := sl.Current().Interface().(StructLevelInvalidErr)
- if top.Value == s.Value {
- sl.ReportError(nil, "Value", "Value", "required", "")
- }
- }
- func TestStructLevelInvalidError(t *testing.T) {
- validate := New()
- validate.RegisterStructValidation(StructLevelInvalidError, StructLevelInvalidErr{})
- var test StructLevelInvalidErr
- err := validate.Struct(test)
- NotEqual(t, err, nil)
- errs, ok := err.(ValidationErrors)
- Equal(t, ok, true)
- fe := errs[0]
- Equal(t, fe.Field(), "Value")
- Equal(t, fe.StructField(), "Value")
- Equal(t, fe.Namespace(), "StructLevelInvalidErr.Value")
- Equal(t, fe.StructNamespace(), "StructLevelInvalidErr.Value")
- Equal(t, fe.Tag(), "required")
- Equal(t, fe.ActualTag(), "required")
- Equal(t, fe.Kind(), reflect.Invalid)
- Equal(t, fe.Type(), reflect.TypeOf(nil))
- }
- func TestNameNamespace(t *testing.T) {
- type Inner2Namespace struct {
- String []string `validate:"dive,required" json:"JSONString"`
- }
- type Inner1Namespace struct {
- Inner2 *Inner2Namespace `json:"Inner2JSON"`
- }
- type Namespace struct {
- Inner1 *Inner1Namespace `json:"Inner1JSON"`
- }
- validate := New()
- validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
- name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
- if name == "-" {
- return ""
- }
- return name
- })
- i2 := &Inner2Namespace{String: []string{"ok", "ok", "ok"}}
- i1 := &Inner1Namespace{Inner2: i2}
- ns := &Namespace{Inner1: i1}
- errs := validate.Struct(ns)
- Equal(t, errs, nil)
- i2.String[1] = ""
- errs = validate.Struct(ns)
- NotEqual(t, errs, nil)
- ve := errs.(ValidationErrors)
- Equal(t, len(ve), 1)
- AssertError(t, errs, "Namespace.Inner1JSON.Inner2JSON.JSONString[1]", "Namespace.Inner1.Inner2.String[1]", "JSONString[1]", "String[1]", "required")
- fe := getError(ve, "Namespace.Inner1JSON.Inner2JSON.JSONString[1]", "Namespace.Inner1.Inner2.String[1]")
- NotEqual(t, fe, nil)
- Equal(t, fe.Field(), "JSONString[1]")
- Equal(t, fe.StructField(), "String[1]")
- Equal(t, fe.Namespace(), "Namespace.Inner1JSON.Inner2JSON.JSONString[1]")
- Equal(t, fe.StructNamespace(), "Namespace.Inner1.Inner2.String[1]")
- }
- func TestAnonymous(t *testing.T) {
- validate := New()
- validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
- name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
- if name == "-" {
- return ""
- }
- return name
- })
- type Test struct {
- Anonymous struct {
- A string `validate:"required" json:"EH"`
- }
- AnonymousB struct {
- B string `validate:"required" json:"BEE"`
- }
- anonymousC struct {
- c string `validate:"required"`
- }
- }
- tst := &Test{
- Anonymous: struct {
- A string `validate:"required" json:"EH"`
- }{
- A: "1",
- },
- AnonymousB: struct {
- B string `validate:"required" json:"BEE"`
- }{
- B: "",
- },
- anonymousC: struct {
- c string `validate:"required"`
- }{
- c: "",
- },
- }
- Equal(t, tst.anonymousC.c, "")
- err := validate.Struct(tst)
- NotEqual(t, err, nil)
- errs := err.(ValidationErrors)
- Equal(t, len(errs), 1)
- AssertError(t, errs, "Test.AnonymousB.BEE", "Test.AnonymousB.B", "BEE", "B", "required")
- fe := getError(errs, "Test.AnonymousB.BEE", "Test.AnonymousB.B")
- NotEqual(t, fe, nil)
- Equal(t, fe.Field(), "BEE")
- Equal(t, fe.StructField(), "B")
- s := struct {
- c string `validate:"required"`
- }{
- c: "",
- }
- err = validate.Struct(s)
- Equal(t, err, nil)
- }
- func TestAnonymousSameStructDifferentTags(t *testing.T) {
- validate := New()
- validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
- name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
- if name == "-" {
- return ""
- }
- return name
- })
- type Test struct {
- A interface{}
- }
- tst := &Test{
- A: struct {
- A string `validate:"required"`
- }{
- A: "",
- },
- }
- err := validate.Struct(tst)
- NotEqual(t, err, nil)
- errs := err.(ValidationErrors)
- Equal(t, len(errs), 1)
- AssertError(t, errs, "Test.A.A", "Test.A.A", "A", "A", "required")
- tst = &Test{
- A: struct {
- A string `validate:"omitempty,required"`
- }{
- A: "",
- },
- }
- err = validate.Struct(tst)
- Equal(t, err, nil)
- }
- func TestStructLevelReturnValidationErrors(t *testing.T) {
- validate := New()
- validate.RegisterStructValidation(StructValidationTestStructReturnValidationErrors, TestStructReturnValidationErrors{})
- inner2 := &TestStructReturnValidationErrorsInner2{
- String: "I'm HERE",
- }
- inner1 := &TestStructReturnValidationErrorsInner1{
- Inner2: inner2,
- }
- val := &TestStructReturnValidationErrors{
- Inner1: inner1,
- }
- errs := validate.Struct(val)
- Equal(t, errs, nil)
- inner2.String = ""
- errs = validate.Struct(val)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 2)
- AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.Inner2.String", "TestStructReturnValidationErrors.Inner1.Inner2.String", "String", "String", "required")
- // this is an extra error reported from struct validation
- AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String", "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String", "String", "String", "required")
- }
- func TestStructLevelReturnValidationErrorsWithJSON(t *testing.T) {
- validate := New()
- validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
- name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
- if name == "-" {
- return ""
- }
- return name
- })
- validate.RegisterStructValidation(StructValidationTestStructReturnValidationErrors2, TestStructReturnValidationErrors{})
- inner2 := &TestStructReturnValidationErrorsInner2{
- String: "I'm HERE",
- }
- inner1 := &TestStructReturnValidationErrorsInner1{
- Inner2: inner2,
- }
- val := &TestStructReturnValidationErrors{
- Inner1: inner1,
- }
- errs := validate.Struct(val)
- Equal(t, errs, nil)
- inner2.String = ""
- errs = validate.Struct(val)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 2)
- AssertError(t, errs, "TestStructReturnValidationErrors.Inner1JSON.Inner2.JSONString", "TestStructReturnValidationErrors.Inner1.Inner2.String", "JSONString", "String", "required")
- // this is an extra error reported from struct validation, it's a badly formatted one, but on purpose
- AssertError(t, errs, "TestStructReturnValidationErrors.Inner1JSON.TestStructReturnValidationErrorsInner2.JSONString", "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String", "JSONString", "String", "required")
- fe := getError(errs, "TestStructReturnValidationErrors.Inner1JSON.Inner2.JSONString", "TestStructReturnValidationErrors.Inner1.Inner2.String")
- NotEqual(t, fe, nil)
- // check for proper JSON namespace
- Equal(t, fe.Field(), "JSONString")
- Equal(t, fe.StructField(), "String")
- Equal(t, fe.Namespace(), "TestStructReturnValidationErrors.Inner1JSON.Inner2.JSONString")
- Equal(t, fe.StructNamespace(), "TestStructReturnValidationErrors.Inner1.Inner2.String")
- fe = getError(errs, "TestStructReturnValidationErrors.Inner1JSON.TestStructReturnValidationErrorsInner2.JSONString", "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String")
- NotEqual(t, fe, nil)
- // check for proper JSON namespace
- Equal(t, fe.Field(), "JSONString")
- Equal(t, fe.StructField(), "String")
- Equal(t, fe.Namespace(), "TestStructReturnValidationErrors.Inner1JSON.TestStructReturnValidationErrorsInner2.JSONString")
- Equal(t, fe.StructNamespace(), "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String")
- }
- func TestStructLevelValidations(t *testing.T) {
- v1 := New()
- v1.RegisterStructValidation(StructValidationTestStruct, TestStruct{})
- tst := &TestStruct{
- String: "good value",
- }
- errs := v1.Struct(tst)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestStruct.StringVal", "TestStruct.String", "StringVal", "String", "badvalueteststruct")
- v2 := New()
- v2.RegisterStructValidation(StructValidationNoTestStructCustomName, TestStruct{})
- errs = v2.Struct(tst)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestStruct.String", "TestStruct.String", "String", "String", "badvalueteststruct")
- v3 := New()
- v3.RegisterStructValidation(StructValidationTestStructInvalid, TestStruct{})
- errs = v3.Struct(tst)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestStruct.StringVal", "TestStruct.String", "StringVal", "String", "badvalueteststruct")
- v4 := New()
- v4.RegisterStructValidation(StructValidationTestStructSuccess, TestStruct{})
- errs = v4.Struct(tst)
- Equal(t, errs, nil)
- }
- func TestAliasTags(t *testing.T) {
- validate := New()
- validate.RegisterAlias("iscoloralias", "hexcolor|rgb|rgba|hsl|hsla")
- s := "rgb(255,255,255)"
- errs := validate.Var(s, "iscoloralias")
- Equal(t, errs, nil)
- s = ""
- errs = validate.Var(s, "omitempty,iscoloralias")
- Equal(t, errs, nil)
- s = "rgb(255,255,0)"
- errs = validate.Var(s, "iscoloralias,len=5")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "len")
- type Test struct {
- Color string `validate:"iscoloralias"`
- }
- tst := &Test{
- Color: "#000",
- }
- errs = validate.Struct(tst)
- Equal(t, errs, nil)
- tst.Color = "cfvre"
- errs = validate.Struct(tst)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.Color", "Test.Color", "Color", "Color", "iscoloralias")
- fe := getError(errs, "Test.Color", "Test.Color")
- NotEqual(t, fe, nil)
- Equal(t, fe.ActualTag(), "hexcolor|rgb|rgba|hsl|hsla")
- validate.RegisterAlias("req", "required,dive,iscoloralias")
- arr := []string{"val1", "#fff", "#000"}
- errs = validate.Var(arr, "req")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "[0]", "[0]", "[0]", "[0]", "iscoloralias")
- PanicMatches(t, func() { validate.RegisterAlias("exists!", "gt=5,lt=10") }, "Alias 'exists!' either contains restricted characters or is the same as a restricted tag needed for normal operation")
- }
- func TestNilValidator(t *testing.T) {
- type TestStruct struct {
- Test string `validate:"required"`
- }
- ts := TestStruct{}
- var val *Validate
- fn := func(fl FieldLevel) bool {
- return fl.Parent().String() == fl.Field().String()
- }
- PanicMatches(t, func() { val.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{}) }, "runtime error: invalid memory address or nil pointer dereference")
- PanicMatches(t, func() { _ = val.RegisterValidation("something", fn) }, "runtime error: invalid memory address or nil pointer dereference")
- PanicMatches(t, func() { _ = val.Var(ts.Test, "required") }, "runtime error: invalid memory address or nil pointer dereference")
- PanicMatches(t, func() { _ = val.VarWithValue("test", ts.Test, "required") }, "runtime error: invalid memory address or nil pointer dereference")
- PanicMatches(t, func() { _ = val.Struct(ts) }, "runtime error: invalid memory address or nil pointer dereference")
- PanicMatches(t, func() { _ = val.StructExcept(ts, "Test") }, "runtime error: invalid memory address or nil pointer dereference")
- PanicMatches(t, func() { _ = val.StructPartial(ts, "Test") }, "runtime error: invalid memory address or nil pointer dereference")
- }
- func TestStructPartial(t *testing.T) {
- p1 := []string{
- "NoTag",
- "Required",
- }
- p2 := []string{
- "SubSlice[0].Test",
- "Sub",
- "SubIgnore",
- "Anonymous.A",
- }
- p3 := []string{
- "SubTest.Test",
- }
- p4 := []string{
- "A",
- }
- tPartial := &TestPartial{
- NoTag: "NoTag",
- Required: "Required",
- SubSlice: []*SubTest{
- {
- Test: "Required",
- },
- {
- Test: "Required",
- },
- },
- Sub: &SubTest{
- Test: "1",
- },
- SubIgnore: &SubTest{
- Test: "",
- },
- Anonymous: struct {
- A string `validate:"required"`
- ASubSlice []*SubTest `validate:"required,dive"`
- SubAnonStruct []struct {
- Test string `validate:"required"`
- OtherTest string `validate:"required"`
- } `validate:"required,dive"`
- }{
- A: "1",
- ASubSlice: []*SubTest{
- {
- Test: "Required",
- },
- {
- Test: "Required",
- },
- },
- SubAnonStruct: []struct {
- Test string `validate:"required"`
- OtherTest string `validate:"required"`
- }{
- {"Required", "RequiredOther"},
- {"Required", "RequiredOther"},
- },
- },
- }
- validate := New()
- // the following should all return no errors as everything is valid in
- // the default state
- errs := validate.StructPartialCtx(context.Background(), tPartial, p1...)
- Equal(t, errs, nil)
- errs = validate.StructPartial(tPartial, p2...)
- Equal(t, errs, nil)
- // this isn't really a robust test, but is ment to illustrate the ANON CASE below
- errs = validate.StructPartial(tPartial.SubSlice[0], p3...)
- Equal(t, errs, nil)
- errs = validate.StructExceptCtx(context.Background(), tPartial, p1...)
- Equal(t, errs, nil)
- errs = validate.StructExcept(tPartial, p2...)
- Equal(t, errs, nil)
- // mod tParial for required feild and re-test making sure invalid fields are NOT required:
- tPartial.Required = ""
- errs = validate.StructExcept(tPartial, p1...)
- Equal(t, errs, nil)
- errs = validate.StructPartial(tPartial, p2...)
- Equal(t, errs, nil)
- // inversion and retesting Partial to generate failures:
- errs = validate.StructPartial(tPartial, p1...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.Required", "TestPartial.Required", "Required", "Required", "required")
- errs = validate.StructExcept(tPartial, p2...)
- AssertError(t, errs, "TestPartial.Required", "TestPartial.Required", "Required", "Required", "required")
- // reset Required field, and set nested struct
- tPartial.Required = "Required"
- tPartial.Anonymous.A = ""
- // will pass as unset feilds is not going to be tested
- errs = validate.StructPartial(tPartial, p1...)
- Equal(t, errs, nil)
- errs = validate.StructExcept(tPartial, p2...)
- Equal(t, errs, nil)
- // ANON CASE the response here is strange, it clearly does what it is being told to
- errs = validate.StructExcept(tPartial.Anonymous, p4...)
- Equal(t, errs, nil)
- // will fail as unset feild is tested
- errs = validate.StructPartial(tPartial, p2...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.Anonymous.A", "TestPartial.Anonymous.A", "A", "A", "required")
- errs = validate.StructExcept(tPartial, p1...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.Anonymous.A", "TestPartial.Anonymous.A", "A", "A", "required")
- // reset nested struct and unset struct in slice
- tPartial.Anonymous.A = "Required"
- tPartial.SubSlice[0].Test = ""
- // these will pass as unset item is NOT tested
- errs = validate.StructPartial(tPartial, p1...)
- Equal(t, errs, nil)
- errs = validate.StructExcept(tPartial, p2...)
- Equal(t, errs, nil)
- // these will fail as unset item IS tested
- errs = validate.StructExcept(tPartial, p1...)
- AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required")
- Equal(t, len(errs.(ValidationErrors)), 1)
- errs = validate.StructPartial(tPartial, p2...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required")
- Equal(t, len(errs.(ValidationErrors)), 1)
- // Unset second slice member concurrently to test dive behavior:
- tPartial.SubSlice[1].Test = ""
- errs = validate.StructPartial(tPartial, p1...)
- Equal(t, errs, nil)
- // NOTE: When specifying nested items, it is still the users responsibility
- // to specify the dive tag, the library does not override this.
- errs = validate.StructExcept(tPartial, p2...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required")
- errs = validate.StructExcept(tPartial, p1...)
- Equal(t, len(errs.(ValidationErrors)), 2)
- AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required")
- AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required")
- errs = validate.StructPartial(tPartial, p2...)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required")
- // reset struct in slice, and unset struct in slice in unset posistion
- tPartial.SubSlice[0].Test = "Required"
- // these will pass as the unset item is NOT tested
- errs = validate.StructPartial(tPartial, p1...)
- Equal(t, errs, nil)
- errs = validate.StructPartial(tPartial, p2...)
- Equal(t, errs, nil)
- // testing for missing item by exception, yes it dives and fails
- errs = validate.StructExcept(tPartial, p1...)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required")
- errs = validate.StructExcept(tPartial, p2...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required")
- tPartial.SubSlice[1].Test = "Required"
- tPartial.Anonymous.SubAnonStruct[0].Test = ""
- // these will pass as the unset item is NOT tested
- errs = validate.StructPartial(tPartial, p1...)
- Equal(t, errs, nil)
- errs = validate.StructPartial(tPartial, p2...)
- Equal(t, errs, nil)
- errs = validate.StructExcept(tPartial, p1...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "Test", "required")
- errs = validate.StructExcept(tPartial, p2...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "Test", "required")
- }
- func TestCrossStructLteFieldValidation(t *testing.T) {
- type Inner struct {
- CreatedAt *time.Time
- String string
- Int int
- Uint uint
- Float float64
- Array []string
- }
- type Test struct {
- Inner *Inner
- CreatedAt *time.Time `validate:"ltecsfield=Inner.CreatedAt"`
- String string `validate:"ltecsfield=Inner.String"`
- Int int `validate:"ltecsfield=Inner.Int"`
- Uint uint `validate:"ltecsfield=Inner.Uint"`
- Float float64 `validate:"ltecsfield=Inner.Float"`
- Array []string `validate:"ltecsfield=Inner.Array"`
- }
- now := time.Now().UTC()
- then := now.Add(time.Hour * 5)
- inner := &Inner{
- CreatedAt: &then,
- String: "abcd",
- Int: 13,
- Uint: 13,
- Float: 1.13,
- Array: []string{"val1", "val2"},
- }
- test := &Test{
- Inner: inner,
- CreatedAt: &now,
- String: "abc",
- Int: 12,
- Uint: 12,
- Float: 1.12,
- Array: []string{"val1"},
- }
- validate := New()
- errs := validate.Struct(test)
- Equal(t, errs, nil)
- test.CreatedAt = &then
- test.String = "abcd"
- test.Int = 13
- test.Uint = 13
- test.Float = 1.13
- test.Array = []string{"val1", "val2"}
- errs = validate.Struct(test)
- Equal(t, errs, nil)
- after := now.Add(time.Hour * 10)
- test.CreatedAt = &after
- test.String = "abce"
- test.Int = 14
- test.Uint = 14
- test.Float = 1.14
- test.Array = []string{"val1", "val2", "val3"}
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltecsfield")
- AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltecsfield")
- AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltecsfield")
- AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltecsfield")
- AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltecsfield")
- AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltecsfield")
- errs = validate.VarWithValueCtx(context.Background(), 1, "", "ltecsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltecsfield")
- // this test is for the WARNING about unforeseen validation issues.
- errs = validate.VarWithValue(test, now, "ltecsfield")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 6)
- AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltecsfield")
- AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltecsfield")
- AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltecsfield")
- AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltecsfield")
- AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltecsfield")
- AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltecsfield")
- type Other struct {
- Value string
- }
- type Test2 struct {
- Value Other
- Time time.Time `validate:"ltecsfield=Value"`
- }
- tst := Test2{
- Value: Other{Value: "StringVal"},
- Time: then,
- }
- errs = validate.Struct(tst)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "ltecsfield")
- }
- func TestCrossStructLtFieldValidation(t *testing.T) {
- type Inner struct {
- CreatedAt *time.Time
- String string
- Int int
- Uint uint
- Float float64
- Array []string
- }
- type Test struct {
- Inner *Inner
- CreatedAt *time.Time `validate:"ltcsfield=Inner.CreatedAt"`
- String string `validate:"ltcsfield=Inner.String"`
- Int int `validate:"ltcsfield=Inner.Int"`
- Uint uint `validate:"ltcsfield=Inner.Uint"`
- Float float64 `validate:"ltcsfield=Inner.Float"`
- Array []string `validate:"ltcsfield=Inner.Array"`
- }
- now := time.Now().UTC()
- then := now.Add(time.Hour * 5)
- inner := &Inner{
- CreatedAt: &then,
- String: "abcd",
- Int: 13,
- Uint: 13,
- Float: 1.13,
- Array: []string{"val1", "val2"},
- }
- test := &Test{
- Inner: inner,
- CreatedAt: &now,
- String: "abc",
- Int: 12,
- Uint: 12,
- Float: 1.12,
- Array: []string{"val1"},
- }
- validate := New()
- errs := validate.Struct(test)
- Equal(t, errs, nil)
- test.CreatedAt = &then
- test.String = "abcd"
- test.Int = 13
- test.Uint = 13
- test.Float = 1.13
- test.Array = []string{"val1", "val2"}
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltcsfield")
- AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltcsfield")
- AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltcsfield")
- AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltcsfield")
- AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltcsfield")
- AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltcsfield")
- errs = validate.VarWithValue(1, "", "ltcsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltcsfield")
- // this test is for the WARNING about unforeseen validation issues.
- errs = validate.VarWithValue(test, now, "ltcsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltcsfield")
- AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltcsfield")
- AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltcsfield")
- AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltcsfield")
- AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltcsfield")
- AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltcsfield")
- type Other struct {
- Value string
- }
- type Test2 struct {
- Value Other
- Time time.Time `validate:"ltcsfield=Value"`
- }
- tst := Test2{
- Value: Other{Value: "StringVal"},
- Time: then,
- }
- errs = validate.Struct(tst)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "ltcsfield")
- }
- func TestCrossStructGteFieldValidation(t *testing.T) {
- type Inner struct {
- CreatedAt *time.Time
- String string
- Int int
- Uint uint
- Float float64
- Array []string
- }
- type Test struct {
- Inner *Inner
- CreatedAt *time.Time `validate:"gtecsfield=Inner.CreatedAt"`
- String string `validate:"gtecsfield=Inner.String"`
- Int int `validate:"gtecsfield=Inner.Int"`
- Uint uint `validate:"gtecsfield=Inner.Uint"`
- Float float64 `validate:"gtecsfield=Inner.Float"`
- Array []string `validate:"gtecsfield=Inner.Array"`
- }
- now := time.Now().UTC()
- then := now.Add(time.Hour * -5)
- inner := &Inner{
- CreatedAt: &then,
- String: "abcd",
- Int: 13,
- Uint: 13,
- Float: 1.13,
- Array: []string{"val1", "val2"},
- }
- test := &Test{
- Inner: inner,
- CreatedAt: &now,
- String: "abcde",
- Int: 14,
- Uint: 14,
- Float: 1.14,
- Array: []string{"val1", "val2", "val3"},
- }
- validate := New()
- errs := validate.Struct(test)
- Equal(t, errs, nil)
- test.CreatedAt = &then
- test.String = "abcd"
- test.Int = 13
- test.Uint = 13
- test.Float = 1.13
- test.Array = []string{"val1", "val2"}
- errs = validate.Struct(test)
- Equal(t, errs, nil)
- before := now.Add(time.Hour * -10)
- test.CreatedAt = &before
- test.String = "abc"
- test.Int = 12
- test.Uint = 12
- test.Float = 1.12
- test.Array = []string{"val1"}
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtecsfield")
- AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtecsfield")
- AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtecsfield")
- AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtecsfield")
- AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtecsfield")
- AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtecsfield")
- errs = validate.VarWithValue(1, "", "gtecsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtecsfield")
- // this test is for the WARNING about unforeseen validation issues.
- errs = validate.VarWithValue(test, now, "gtecsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtecsfield")
- AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtecsfield")
- AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtecsfield")
- AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtecsfield")
- AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtecsfield")
- AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtecsfield")
- type Other struct {
- Value string
- }
- type Test2 struct {
- Value Other
- Time time.Time `validate:"gtecsfield=Value"`
- }
- tst := Test2{
- Value: Other{Value: "StringVal"},
- Time: then,
- }
- errs = validate.Struct(tst)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "gtecsfield")
- }
- func TestCrossStructGtFieldValidation(t *testing.T) {
- type Inner struct {
- CreatedAt *time.Time
- String string
- Int int
- Uint uint
- Float float64
- Array []string
- }
- type Test struct {
- Inner *Inner
- CreatedAt *time.Time `validate:"gtcsfield=Inner.CreatedAt"`
- String string `validate:"gtcsfield=Inner.String"`
- Int int `validate:"gtcsfield=Inner.Int"`
- Uint uint `validate:"gtcsfield=Inner.Uint"`
- Float float64 `validate:"gtcsfield=Inner.Float"`
- Array []string `validate:"gtcsfield=Inner.Array"`
- }
- now := time.Now().UTC()
- then := now.Add(time.Hour * -5)
- inner := &Inner{
- CreatedAt: &then,
- String: "abcd",
- Int: 13,
- Uint: 13,
- Float: 1.13,
- Array: []string{"val1", "val2"},
- }
- test := &Test{
- Inner: inner,
- CreatedAt: &now,
- String: "abcde",
- Int: 14,
- Uint: 14,
- Float: 1.14,
- Array: []string{"val1", "val2", "val3"},
- }
- validate := New()
- errs := validate.Struct(test)
- Equal(t, errs, nil)
- test.CreatedAt = &then
- test.String = "abcd"
- test.Int = 13
- test.Uint = 13
- test.Float = 1.13
- test.Array = []string{"val1", "val2"}
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtcsfield")
- AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtcsfield")
- AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtcsfield")
- AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtcsfield")
- AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtcsfield")
- AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtcsfield")
- errs = validate.VarWithValue(1, "", "gtcsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtcsfield")
- // this test is for the WARNING about unforeseen validation issues.
- errs = validate.VarWithValue(test, now, "gtcsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtcsfield")
- AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtcsfield")
- AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtcsfield")
- AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtcsfield")
- AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtcsfield")
- AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtcsfield")
- type Other struct {
- Value string
- }
- type Test2 struct {
- Value Other
- Time time.Time `validate:"gtcsfield=Value"`
- }
- tst := Test2{
- Value: Other{Value: "StringVal"},
- Time: then,
- }
- errs = validate.Struct(tst)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "gtcsfield")
- }
- func TestCrossStructNeFieldValidation(t *testing.T) {
- type Inner struct {
- CreatedAt *time.Time
- }
- type Test struct {
- Inner *Inner
- CreatedAt *time.Time `validate:"necsfield=Inner.CreatedAt"`
- }
- now := time.Now().UTC()
- then := now.Add(time.Hour * 5)
- inner := &Inner{
- CreatedAt: &then,
- }
- test := &Test{
- Inner: inner,
- CreatedAt: &now,
- }
- validate := New()
- errs := validate.Struct(test)
- Equal(t, errs, nil)
- test.CreatedAt = &then
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "necsfield")
- var j uint64
- var k float64
- var j2 uint64
- var k2 float64
- s := "abcd"
- i := 1
- j = 1
- k = 1.543
- arr := []string{"test"}
- s2 := "abcd"
- i2 := 1
- j2 = 1
- k2 = 1.543
- arr2 := []string{"test"}
- arr3 := []string{"test", "test2"}
- now2 := now
- errs = validate.VarWithValue(s, s2, "necsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "necsfield")
- errs = validate.VarWithValue(i2, i, "necsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "necsfield")
- errs = validate.VarWithValue(j2, j, "necsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "necsfield")
- errs = validate.VarWithValue(k2, k, "necsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "necsfield")
- errs = validate.VarWithValue(arr2, arr, "necsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "necsfield")
- errs = validate.VarWithValue(now2, now, "necsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "necsfield")
- errs = validate.VarWithValue(arr3, arr, "necsfield")
- Equal(t, errs, nil)
- type SInner struct {
- Name string
- }
- type TStruct struct {
- Inner *SInner
- CreatedAt *time.Time `validate:"necsfield=Inner"`
- }
- sinner := &SInner{
- Name: "NAME",
- }
- test2 := &TStruct{
- Inner: sinner,
- CreatedAt: &now,
- }
- errs = validate.Struct(test2)
- Equal(t, errs, nil)
- test2.Inner = nil
- errs = validate.Struct(test2)
- Equal(t, errs, nil)
- errs = validate.VarWithValue(nil, 1, "necsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "necsfield")
- }
- func TestCrossStructEqFieldValidation(t *testing.T) {
- type Inner struct {
- CreatedAt *time.Time
- }
- type Test struct {
- Inner *Inner
- CreatedAt *time.Time `validate:"eqcsfield=Inner.CreatedAt"`
- }
- now := time.Now().UTC()
- inner := &Inner{
- CreatedAt: &now,
- }
- test := &Test{
- Inner: inner,
- CreatedAt: &now,
- }
- validate := New()
- errs := validate.Struct(test)
- Equal(t, errs, nil)
- newTime := time.Now().UTC()
- test.CreatedAt = &newTime
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "eqcsfield")
- var j uint64
- var k float64
- s := "abcd"
- i := 1
- j = 1
- k = 1.543
- arr := []string{"test"}
- var j2 uint64
- var k2 float64
- s2 := "abcd"
- i2 := 1
- j2 = 1
- k2 = 1.543
- arr2 := []string{"test"}
- arr3 := []string{"test", "test2"}
- now2 := now
- errs = validate.VarWithValue(s, s2, "eqcsfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(i2, i, "eqcsfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(j2, j, "eqcsfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(k2, k, "eqcsfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(arr2, arr, "eqcsfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(now2, now, "eqcsfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(arr3, arr, "eqcsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "eqcsfield")
- type SInner struct {
- Name string
- }
- type TStruct struct {
- Inner *SInner
- CreatedAt *time.Time `validate:"eqcsfield=Inner"`
- }
- sinner := &SInner{
- Name: "NAME",
- }
- test2 := &TStruct{
- Inner: sinner,
- CreatedAt: &now,
- }
- errs = validate.Struct(test2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqcsfield")
- test2.Inner = nil
- errs = validate.Struct(test2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqcsfield")
- errs = validate.VarWithValue(nil, 1, "eqcsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "eqcsfield")
- }
- func TestCrossNamespaceFieldValidation(t *testing.T) {
- type SliceStruct struct {
- Name string
- }
- type Inner struct {
- CreatedAt *time.Time
- Slice []string
- SliceStructs []*SliceStruct
- SliceSlice [][]string
- SliceSliceStruct [][]*SliceStruct
- SliceMap []map[string]string
- Map map[string]string
- MapMap map[string]map[string]string
- MapStructs map[string]*SliceStruct
- MapMapStruct map[string]map[string]*SliceStruct
- MapSlice map[string][]string
- MapInt map[int]string
- MapInt8 map[int8]string
- MapInt16 map[int16]string
- MapInt32 map[int32]string
- MapInt64 map[int64]string
- MapUint map[uint]string
- MapUint8 map[uint8]string
- MapUint16 map[uint16]string
- MapUint32 map[uint32]string
- MapUint64 map[uint64]string
- MapFloat32 map[float32]string
- MapFloat64 map[float64]string
- MapBool map[bool]string
- }
- type Test struct {
- Inner *Inner
- CreatedAt *time.Time
- }
- now := time.Now()
- inner := &Inner{
- CreatedAt: &now,
- Slice: []string{"val1", "val2", "val3"},
- SliceStructs: []*SliceStruct{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}},
- SliceSlice: [][]string{{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}},
- SliceSliceStruct: [][]*SliceStruct{{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, {{Name: "name4"}, {Name: "name5"}, {Name: "name6"}}, {{Name: "name7"}, {Name: "name8"}, {Name: "name9"}}},
- SliceMap: []map[string]string{{"key1": "val1", "key2": "val2", "key3": "val3"}, {"key4": "val4", "key5": "val5", "key6": "val6"}},
- Map: map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"},
- MapStructs: map[string]*SliceStruct{"key1": {Name: "name1"}, "key2": {Name: "name2"}, "key3": {Name: "name3"}},
- MapMap: map[string]map[string]string{"key1": {"key1-1": "val1"}, "key2": {"key2-1": "val2"}, "key3": {"key3-1": "val3"}},
- MapMapStruct: map[string]map[string]*SliceStruct{"key1": {"key1-1": {Name: "name1"}}, "key2": {"key2-1": {Name: "name2"}}, "key3": {"key3-1": {Name: "name3"}}},
- MapSlice: map[string][]string{"key1": {"1", "2", "3"}, "key2": {"4", "5", "6"}, "key3": {"7", "8", "9"}},
- MapInt: map[int]string{1: "val1", 2: "val2", 3: "val3"},
- MapInt8: map[int8]string{1: "val1", 2: "val2", 3: "val3"},
- MapInt16: map[int16]string{1: "val1", 2: "val2", 3: "val3"},
- MapInt32: map[int32]string{1: "val1", 2: "val2", 3: "val3"},
- MapInt64: map[int64]string{1: "val1", 2: "val2", 3: "val3"},
- MapUint: map[uint]string{1: "val1", 2: "val2", 3: "val3"},
- MapUint8: map[uint8]string{1: "val1", 2: "val2", 3: "val3"},
- MapUint16: map[uint16]string{1: "val1", 2: "val2", 3: "val3"},
- MapUint32: map[uint32]string{1: "val1", 2: "val2", 3: "val3"},
- MapUint64: map[uint64]string{1: "val1", 2: "val2", 3: "val3"},
- MapFloat32: map[float32]string{1.01: "val1", 2.02: "val2", 3.03: "val3"},
- MapFloat64: map[float64]string{1.01: "val1", 2.02: "val2", 3.03: "val3"},
- MapBool: map[bool]string{true: "val1", false: "val2"},
- }
- test := &Test{
- Inner: inner,
- CreatedAt: &now,
- }
- val := reflect.ValueOf(test)
- vd := New()
- v := &validate{
- v: vd,
- }
- current, kind, ok := v.getStructFieldOKInternal(val, "Inner.CreatedAt")
- Equal(t, ok, true)
- Equal(t, kind, reflect.Struct)
- tm, ok := current.Interface().(time.Time)
- Equal(t, ok, true)
- Equal(t, tm, now)
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.Slice[1]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
- current, _, ok = v.getStructFieldOKInternal(val, "Inner.CrazyNonExistantField")
- Equal(t, ok, false)
- current, _, ok = v.getStructFieldOKInternal(val, "Inner.Slice[101]")
- Equal(t, ok, false)
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.Map[key3]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val3")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapMap[key2][key2-1]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapStructs[key2].Name")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "name2")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapMapStruct[key3][key3-1].Name")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "name3")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.SliceSlice[2][0]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "7")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.SliceSliceStruct[2][1].Name")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "name8")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.SliceMap[1][key5]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val5")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapSlice[key3][2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "9")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapInt[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapInt8[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapInt16[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapInt32[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapInt64[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapUint[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapUint8[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapUint16[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapUint32[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapUint64[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapFloat32[3.03]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val3")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapFloat64[2.02]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapBool[true]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val1")
- inner = &Inner{
- CreatedAt: &now,
- Slice: []string{"val1", "val2", "val3"},
- SliceStructs: []*SliceStruct{{Name: "name1"}, {Name: "name2"}, nil},
- SliceSlice: [][]string{{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}},
- SliceSliceStruct: [][]*SliceStruct{{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, {{Name: "name4"}, {Name: "name5"}, {Name: "name6"}}, {{Name: "name7"}, {Name: "name8"}, {Name: "name9"}}},
- SliceMap: []map[string]string{{"key1": "val1", "key2": "val2", "key3": "val3"}, {"key4": "val4", "key5": "val5", "key6": "val6"}},
- Map: map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"},
- MapStructs: map[string]*SliceStruct{"key1": {Name: "name1"}, "key2": {Name: "name2"}, "key3": {Name: "name3"}},
- MapMap: map[string]map[string]string{"key1": {"key1-1": "val1"}, "key2": {"key2-1": "val2"}, "key3": {"key3-1": "val3"}},
- MapMapStruct: map[string]map[string]*SliceStruct{"key1": {"key1-1": {Name: "name1"}}, "key2": {"key2-1": {Name: "name2"}}, "key3": {"key3-1": {Name: "name3"}}},
- MapSlice: map[string][]string{"key1": {"1", "2", "3"}, "key2": {"4", "5", "6"}, "key3": {"7", "8", "9"}},
- }
- test = &Test{
- Inner: inner,
- CreatedAt: nil,
- }
- val = reflect.ValueOf(test)
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.SliceStructs[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.Ptr)
- Equal(t, current.String(), "<*validator.SliceStruct Value>")
- Equal(t, current.IsNil(), true)
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.SliceStructs[2].Name")
- Equal(t, ok, false)
- Equal(t, kind, reflect.Ptr)
- Equal(t, current.String(), "<*validator.SliceStruct Value>")
- Equal(t, current.IsNil(), true)
- PanicMatches(t, func() { v.getStructFieldOKInternal(reflect.ValueOf(1), "crazyinput") }, "Invalid field namespace")
- }
- func TestExistsValidation(t *testing.T) {
- jsonText := "{ \"truthiness2\": true }"
- type Thing struct {
- Truthiness *bool `json:"truthiness" validate:"required"`
- }
- var ting Thing
- err := json.Unmarshal([]byte(jsonText), &ting)
- Equal(t, err, nil)
- NotEqual(t, ting, nil)
- Equal(t, ting.Truthiness, nil)
- validate := New()
- errs := validate.Struct(ting)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Thing.Truthiness", "Thing.Truthiness", "Truthiness", "Truthiness", "required")
- jsonText = "{ \"truthiness\": true }"
- err = json.Unmarshal([]byte(jsonText), &ting)
- Equal(t, err, nil)
- NotEqual(t, ting, nil)
- Equal(t, ting.Truthiness, true)
- errs = validate.Struct(ting)
- Equal(t, errs, nil)
- }
- func TestSQLValue2Validation(t *testing.T) {
- validate := New()
- validate.RegisterCustomTypeFunc(ValidateValuerType, valuer{}, (*driver.Valuer)(nil), sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})
- validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
- validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1)
- val := valuer{
- Name: "",
- }
- errs := validate.Var(val, "required")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "required")
- val.Name = "Valid Name"
- errs = validate.VarCtx(context.Background(), val, "required")
- Equal(t, errs, nil)
- val.Name = "errorme"
- PanicMatches(t, func() { _ = validate.Var(val, "required") }, "SQL Driver Valuer error: some kind of error")
- myVal := valuer{
- Name: "",
- }
- errs = validate.Var(myVal, "required")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "required")
- cust := MadeUpCustomType{
- FirstName: "Joey",
- LastName: "Bloggs",
- }
- c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2}
- errs = validate.Struct(c)
- Equal(t, errs, nil)
- c.MadeUp.FirstName = ""
- c.OverriddenInt = 1
- errs = validate.Struct(c)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 2)
- AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "CustomMadeUpStruct.MadeUp", "MadeUp", "MadeUp", "required")
- AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "OverriddenInt", "gt")
- }
- func TestSQLValueValidation(t *testing.T) {
- validate := New()
- validate.RegisterCustomTypeFunc(ValidateValuerType, (*driver.Valuer)(nil), valuer{})
- validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
- validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1)
- val := valuer{
- Name: "",
- }
- errs := validate.Var(val, "required")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "required")
- val.Name = "Valid Name"
- errs = validate.Var(val, "required")
- Equal(t, errs, nil)
- val.Name = "errorme"
- PanicMatches(t, func() { errs = validate.Var(val, "required") }, "SQL Driver Valuer error: some kind of error")
- myVal := valuer{
- Name: "",
- }
- errs = validate.Var(myVal, "required")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "required")
- cust := MadeUpCustomType{
- FirstName: "Joey",
- LastName: "Bloggs",
- }
- c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2}
- errs = validate.Struct(c)
- Equal(t, errs, nil)
- c.MadeUp.FirstName = ""
- c.OverriddenInt = 1
- errs = validate.Struct(c)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 2)
- AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "CustomMadeUpStruct.MadeUp", "MadeUp", "MadeUp", "required")
- AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "OverriddenInt", "gt")
- }
- func TestMACValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"3D:F2:C9:A6:B3:4F", true},
- {"3D-F2-C9-A6-B3:4F", false},
- {"123", false},
- {"", false},
- {"abacaba", false},
- {"00:25:96:FF:FE:12:34:56", true},
- {"0025:96FF:FE12:3456", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "mac")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d mac failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d mac failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "mac" {
- t.Fatalf("Index: %d mac failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestIPValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"10.0.0.1", true},
- {"172.16.0.1", true},
- {"192.168.0.1", true},
- {"192.168.255.254", true},
- {"192.168.255.256", false},
- {"172.16.255.254", true},
- {"172.16.256.255", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652", true},
- {"2001:cdba:0:0:0:0:3257:9652", true},
- {"2001:cdba::3257:9652", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "ip")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ip failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ip failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "ip" {
- t.Fatalf("Index: %d ip failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestIPv6Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"10.0.0.1", false},
- {"172.16.0.1", false},
- {"192.168.0.1", false},
- {"192.168.255.254", false},
- {"192.168.255.256", false},
- {"172.16.255.254", false},
- {"172.16.256.255", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652", true},
- {"2001:cdba:0:0:0:0:3257:9652", true},
- {"2001:cdba::3257:9652", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "ipv6")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "ipv6" {
- t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestIPv4Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"10.0.0.1", true},
- {"172.16.0.1", true},
- {"192.168.0.1", true},
- {"192.168.255.254", true},
- {"192.168.255.256", false},
- {"172.16.255.254", true},
- {"172.16.256.255", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652", false},
- {"2001:cdba:0:0:0:0:3257:9652", false},
- {"2001:cdba::3257:9652", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "ipv4")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "ipv4" {
- t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestCIDRValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"10.0.0.0/0", true},
- {"10.0.0.1/8", true},
- {"172.16.0.1/16", true},
- {"192.168.0.1/24", true},
- {"192.168.255.254/24", true},
- {"192.168.255.254/48", false},
- {"192.168.255.256/24", false},
- {"172.16.255.254/16", true},
- {"172.16.256.255/16", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652/64", true},
- {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false},
- {"2001:cdba:0:0:0:0:3257:9652/32", true},
- {"2001:cdba::3257:9652/16", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "cidr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "cidr" {
- t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestCIDRv6Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"10.0.0.0/0", false},
- {"10.0.0.1/8", false},
- {"172.16.0.1/16", false},
- {"192.168.0.1/24", false},
- {"192.168.255.254/24", false},
- {"192.168.255.254/48", false},
- {"192.168.255.256/24", false},
- {"172.16.255.254/16", false},
- {"172.16.256.255/16", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652/64", true},
- {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false},
- {"2001:cdba:0:0:0:0:3257:9652/32", true},
- {"2001:cdba::3257:9652/16", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "cidrv6")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "cidrv6" {
- t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestCIDRv4Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"10.0.0.0/0", true},
- {"10.0.0.1/8", true},
- {"172.16.0.1/16", true},
- {"192.168.0.1/24", true},
- {"192.168.255.254/24", true},
- {"192.168.255.254/48", false},
- {"192.168.255.256/24", false},
- {"172.16.255.254/16", true},
- {"172.16.256.255/16", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652/64", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false},
- {"2001:cdba:0:0:0:0:3257:9652/32", false},
- {"2001:cdba::3257:9652/16", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "cidrv4")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "cidrv4" {
- t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestTCPAddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {":80", false},
- {"127.0.0.1:80", true},
- {"[::1]:80", true},
- {"256.0.0.0:1", false},
- {"[::1]", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "tcp_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "tcp_addr" {
- t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestTCP6AddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {":80", false},
- {"127.0.0.1:80", false},
- {"[::1]:80", true},
- {"256.0.0.0:1", false},
- {"[::1]", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "tcp6_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "tcp6_addr" {
- t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestTCP4AddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {":80", false},
- {"127.0.0.1:80", true},
- {"[::1]:80", false}, // https://github.com/golang/go/issues/14037
- {"256.0.0.0:1", false},
- {"[::1]", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "tcp4_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Log(test.param, IsEqual(errs, nil))
- t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "tcp4_addr" {
- t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestUDPAddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {":80", false},
- {"127.0.0.1:80", true},
- {"[::1]:80", true},
- {"256.0.0.0:1", false},
- {"[::1]", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "udp_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "udp_addr" {
- t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestUDP6AddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {":80", false},
- {"127.0.0.1:80", false},
- {"[::1]:80", true},
- {"256.0.0.0:1", false},
- {"[::1]", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "udp6_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "udp6_addr" {
- t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestUDP4AddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {":80", false},
- {"127.0.0.1:80", true},
- {"[::1]:80", false}, // https://github.com/golang/go/issues/14037
- {"256.0.0.0:1", false},
- {"[::1]", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "udp4_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Log(test.param, IsEqual(errs, nil))
- t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "udp4_addr" {
- t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestIPAddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"127.0.0.1", true},
- {"127.0.0.1:80", false},
- {"::1", true},
- {"256.0.0.0", false},
- {"localhost", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "ip_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "ip_addr" {
- t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestIP6AddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"127.0.0.1", false}, // https://github.com/golang/go/issues/14037
- {"127.0.0.1:80", false},
- {"::1", true},
- {"0:0:0:0:0:0:0:1", true},
- {"256.0.0.0", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "ip6_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "ip6_addr" {
- t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestIP4AddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"127.0.0.1", true},
- {"127.0.0.1:80", false},
- {"::1", false}, // https://github.com/golang/go/issues/14037
- {"256.0.0.0", false},
- {"localhost", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "ip4_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Log(test.param, IsEqual(errs, nil))
- t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "ip4_addr" {
- t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestUnixAddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", true},
- {"v.sock", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "unix_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Log(test.param, IsEqual(errs, nil))
- t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "unix_addr" {
- t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) {
- validate := New()
- var m map[string]string
- errs := validate.Var(m, "required")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "required")
- m = map[string]string{}
- errs = validate.Var(m, "required")
- Equal(t, errs, nil)
- var arr [5]string
- errs = validate.Var(arr, "required")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "required")
- arr[0] = "ok"
- errs = validate.Var(arr, "required")
- Equal(t, errs, nil)
- var s []string
- errs = validate.Var(s, "required")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "required")
- s = []string{}
- errs = validate.Var(s, "required")
- Equal(t, errs, nil)
- var c chan string
- errs = validate.Var(c, "required")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "required")
- c = make(chan string)
- errs = validate.Var(c, "required")
- Equal(t, errs, nil)
- var tst *int
- errs = validate.Var(tst, "required")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "required")
- one := 1
- tst = &one
- errs = validate.Var(tst, "required")
- Equal(t, errs, nil)
- var iface interface{}
- errs = validate.Var(iface, "required")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "required")
- errs = validate.Var(iface, "omitempty,required")
- Equal(t, errs, nil)
- errs = validate.Var(iface, "")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(nil, iface, "")
- Equal(t, errs, nil)
- var f func(string)
- errs = validate.Var(f, "required")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "required")
- f = func(name string) {}
- errs = validate.Var(f, "required")
- Equal(t, errs, nil)
- }
- func TestDatePtrValidationIssueValidation(t *testing.T) {
- type Test struct {
- LastViewed *time.Time
- Reminder *time.Time
- }
- test := &Test{}
- validate := New()
- errs := validate.Struct(test)
- Equal(t, errs, nil)
- }
- func TestCommaAndPipeObfuscationValidation(t *testing.T) {
- s := "My Name Is, |joeybloggs|"
- validate := New()
- errs := validate.Var(s, "excludesall=0x2C")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "excludesall")
- errs = validate.Var(s, "excludesall=0x7C")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "excludesall")
- }
- func TestBadKeyValidation(t *testing.T) {
- type Test struct {
- Name string `validate:"required, "`
- }
- tst := &Test{
- Name: "test",
- }
- validate := New()
- PanicMatches(t, func() { _ = validate.Struct(tst) }, "Undefined validation function ' ' on field 'Name'")
- type Test2 struct {
- Name string `validate:"required,,len=2"`
- }
- tst2 := &Test2{
- Name: "test",
- }
- PanicMatches(t, func() { _ = validate.Struct(tst2) }, "Invalid validation tag on field 'Name'")
- }
- func TestInterfaceErrValidation(t *testing.T) {
- var v2 interface{} = 1
- var v1 interface{} = v2
- validate := New()
- errs := validate.Var(v1, "len=1")
- Equal(t, errs, nil)
- errs = validate.Var(v2, "len=1")
- Equal(t, errs, nil)
- type ExternalCMD struct {
- Userid string `json:"userid"`
- Action uint32 `json:"action"`
- Data interface{} `json:"data,omitempty" validate:"required"`
- }
- s := &ExternalCMD{
- Userid: "123456",
- Action: 10000,
- // Data: 1,
- }
- errs = validate.Struct(s)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "ExternalCMD.Data", "ExternalCMD.Data", "Data", "Data", "required")
- type ExternalCMD2 struct {
- Userid string `json:"userid"`
- Action uint32 `json:"action"`
- Data interface{} `json:"data,omitempty" validate:"len=1"`
- }
- s2 := &ExternalCMD2{
- Userid: "123456",
- Action: 10000,
- // Data: 1,
- }
- errs = validate.Struct(s2)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "ExternalCMD2.Data", "ExternalCMD2.Data", "Data", "Data", "len")
- s3 := &ExternalCMD2{
- Userid: "123456",
- Action: 10000,
- Data: 2,
- }
- errs = validate.Struct(s3)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "ExternalCMD2.Data", "ExternalCMD2.Data", "Data", "Data", "len")
- type Inner struct {
- Name string `validate:"required"`
- }
- inner := &Inner{
- Name: "",
- }
- s4 := &ExternalCMD{
- Userid: "123456",
- Action: 10000,
- Data: inner,
- }
- errs = validate.Struct(s4)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "ExternalCMD.Data.Name", "ExternalCMD.Data.Name", "Name", "Name", "required")
- type TestMapStructPtr struct {
- Errs map[int]interface{} `validate:"gt=0,dive,len=2"`
- }
- mip := map[int]interface{}{0: &Inner{"ok"}, 3: nil, 4: &Inner{"ok"}}
- msp := &TestMapStructPtr{
- Errs: mip,
- }
- errs = validate.Struct(msp)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "TestMapStructPtr.Errs[3]", "TestMapStructPtr.Errs[3]", "Errs[3]", "Errs[3]", "len")
- type TestMultiDimensionalStructs struct {
- Errs [][]interface{} `validate:"gt=0,dive,dive"`
- }
- var errStructArray [][]interface{}
- errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}})
- errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}})
- tms := &TestMultiDimensionalStructs{
- Errs: errStructArray,
- }
- errs = validate.Struct(tms)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 4)
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][1].Name", "TestMultiDimensionalStructs.Errs[0][1].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].Name", "TestMultiDimensionalStructs.Errs[1][2].Name", "Name", "Name", "required")
- type TestMultiDimensionalStructsPtr2 struct {
- Errs [][]*Inner `validate:"gt=0,dive,dive,required"`
- }
- var errStructPtr2Array [][]*Inner
- errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
- errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
- errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil})
- tmsp2 := &TestMultiDimensionalStructsPtr2{
- Errs: errStructPtr2Array,
- }
- errs = validate.Struct(tmsp2)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 6)
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][2]", "TestMultiDimensionalStructsPtr2.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required")
- m := map[int]interface{}{0: "ok", 3: "", 4: "ok"}
- errs = validate.Var(m, "len=3,dive,len=2")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "[3]", "[3]", "[3]", "[3]", "len")
- errs = validate.Var(m, "len=2,dive,required")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "", "", "", "", "len")
- arr := []interface{}{"ok", "", "ok"}
- errs = validate.Var(arr, "len=3,dive,len=2")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "[1]", "[1]", "[1]", "[1]", "len")
- errs = validate.Var(arr, "len=2,dive,required")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "", "", "", "", "len")
- type MyStruct struct {
- A, B string
- C interface{}
- }
- var a MyStruct
- a.A = "value"
- a.C = "nu"
- errs = validate.Struct(a)
- Equal(t, errs, nil)
- }
- func TestMapDiveValidation(t *testing.T) {
- validate := New()
- n := map[int]interface{}{0: nil}
- errs := validate.Var(n, "omitempty,required")
- Equal(t, errs, nil)
- m := map[int]string{0: "ok", 3: "", 4: "ok"}
- errs = validate.Var(m, "len=3,dive,required")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "[3]", "[3]", "[3]", "[3]", "required")
- errs = validate.Var(m, "len=2,dive,required")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "", "", "", "", "len")
- type Inner struct {
- Name string `validate:"required"`
- }
- type TestMapStruct struct {
- Errs map[int]Inner `validate:"gt=0,dive"`
- }
- mi := map[int]Inner{0: {"ok"}, 3: {""}, 4: {"ok"}}
- ms := &TestMapStruct{
- Errs: mi,
- }
- errs = validate.Struct(ms)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "TestMapStruct.Errs[3].Name", "TestMapStruct.Errs[3].Name", "Name", "Name", "required")
- // for full test coverage
- s := fmt.Sprint(errs.Error())
- NotEqual(t, s, "")
- type TestMapTimeStruct struct {
- Errs map[int]*time.Time `validate:"gt=0,dive,required"`
- }
- t1 := time.Now().UTC()
- mta := map[int]*time.Time{0: &t1, 3: nil, 4: nil}
- mt := &TestMapTimeStruct{
- Errs: mta,
- }
- errs = validate.Struct(mt)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 2)
- AssertError(t, errs, "TestMapTimeStruct.Errs[3]", "TestMapTimeStruct.Errs[3]", "Errs[3]", "Errs[3]", "required")
- AssertError(t, errs, "TestMapTimeStruct.Errs[4]", "TestMapTimeStruct.Errs[4]", "Errs[4]", "Errs[4]", "required")
- type TestMapStructPtr struct {
- Errs map[int]*Inner `validate:"gt=0,dive,required"`
- }
- mip := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}}
- msp := &TestMapStructPtr{
- Errs: mip,
- }
- errs = validate.Struct(msp)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "TestMapStructPtr.Errs[3]", "TestMapStructPtr.Errs[3]", "Errs[3]", "Errs[3]", "required")
- type TestMapStructPtr2 struct {
- Errs map[int]*Inner `validate:"gt=0,dive,omitempty,required"`
- }
- mip2 := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}}
- msp2 := &TestMapStructPtr2{
- Errs: mip2,
- }
- errs = validate.Struct(msp2)
- Equal(t, errs, nil)
- v2 := New()
- v2.RegisterTagNameFunc(func(fld reflect.StructField) string {
- name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
- if name == "-" {
- return ""
- }
- return name
- })
- type MapDiveJSONTest struct {
- Map map[string]string `validate:"required,gte=1,dive,gte=1" json:"MyName"`
- }
- mdjt := &MapDiveJSONTest{
- Map: map[string]string{
- "Key1": "Value1",
- "Key2": "",
- },
- }
- err := v2.Struct(mdjt)
- NotEqual(t, err, nil)
- errs = err.(ValidationErrors)
- fe := getError(errs, "MapDiveJSONTest.MyName[Key2]", "MapDiveJSONTest.Map[Key2]")
- NotEqual(t, fe, nil)
- Equal(t, fe.Tag(), "gte")
- Equal(t, fe.ActualTag(), "gte")
- Equal(t, fe.Field(), "MyName[Key2]")
- Equal(t, fe.StructField(), "Map[Key2]")
- }
- func TestArrayDiveValidation(t *testing.T) {
- validate := New()
- arr := []string{"ok", "", "ok"}
- errs := validate.Var(arr, "len=3,dive,required")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "[1]", "[1]", "[1]", "[1]", "required")
- errs = validate.Var(arr, "len=2,dive,required")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "", "", "", "", "len")
- type BadDive struct {
- Name string `validate:"dive"`
- }
- bd := &BadDive{
- Name: "TEST",
- }
- PanicMatches(t, func() { _ = validate.Struct(bd) }, "dive error! can't dive on a non slice or map")
- type Test struct {
- Errs []string `validate:"gt=0,dive,required"`
- }
- test := &Test{
- Errs: []string{"ok", "", "ok"},
- }
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "Test.Errs[1]", "Test.Errs[1]", "Errs[1]", "Errs[1]", "required")
- test = &Test{
- Errs: []string{"ok", "ok", ""},
- }
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "Test.Errs[2]", "Test.Errs[2]", "Errs[2]", "Errs[2]", "required")
- type TestMultiDimensional struct {
- Errs [][]string `validate:"gt=0,dive,dive,required"`
- }
- var errArray [][]string
- errArray = append(errArray, []string{"ok", "", ""})
- errArray = append(errArray, []string{"ok", "", ""})
- tm := &TestMultiDimensional{
- Errs: errArray,
- }
- errs = validate.Struct(tm)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 4)
- AssertError(t, errs, "TestMultiDimensional.Errs[0][1]", "TestMultiDimensional.Errs[0][1]", "Errs[0][1]", "Errs[0][1]", "required")
- AssertError(t, errs, "TestMultiDimensional.Errs[0][2]", "TestMultiDimensional.Errs[0][2]", "Errs[0][2]", "Errs[0][2]", "required")
- AssertError(t, errs, "TestMultiDimensional.Errs[1][1]", "TestMultiDimensional.Errs[1][1]", "Errs[1][1]", "Errs[1][1]", "required")
- AssertError(t, errs, "TestMultiDimensional.Errs[1][2]", "TestMultiDimensional.Errs[1][2]", "Errs[1][2]", "Errs[1][2]", "required")
- type Inner struct {
- Name string `validate:"required"`
- }
- type TestMultiDimensionalStructs struct {
- Errs [][]Inner `validate:"gt=0,dive,dive"`
- }
- var errStructArray [][]Inner
- errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}})
- errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}})
- tms := &TestMultiDimensionalStructs{
- Errs: errStructArray,
- }
- errs = validate.Struct(tms)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 4)
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][1].Name", "TestMultiDimensionalStructs.Errs[0][1].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].Name", "TestMultiDimensionalStructs.Errs[1][2].Name", "Name", "Name", "required")
- type TestMultiDimensionalStructsPtr struct {
- Errs [][]*Inner `validate:"gt=0,dive,dive"`
- }
- var errStructPtrArray [][]*Inner
- errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}})
- errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}})
- errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, nil})
- tmsp := &TestMultiDimensionalStructsPtr{
- Errs: errStructPtrArray,
- }
- errs = validate.Struct(tmsp)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 5)
- AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[0][1].Name", "TestMultiDimensionalStructsPtr.Errs[0][1].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[0][2].Name", "TestMultiDimensionalStructsPtr.Errs[0][2].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][1].Name", "TestMultiDimensionalStructsPtr.Errs[1][1].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][2].Name", "TestMultiDimensionalStructsPtr.Errs[1][2].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[2][1].Name", "TestMultiDimensionalStructsPtr.Errs[2][1].Name", "Name", "Name", "required")
- // for full test coverage
- s := fmt.Sprint(errs.Error())
- NotEqual(t, s, "")
- type TestMultiDimensionalStructsPtr2 struct {
- Errs [][]*Inner `validate:"gt=0,dive,dive,required"`
- }
- var errStructPtr2Array [][]*Inner
- errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
- errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
- errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil})
- tmsp2 := &TestMultiDimensionalStructsPtr2{
- Errs: errStructPtr2Array,
- }
- errs = validate.Struct(tmsp2)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 6)
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][2]", "TestMultiDimensionalStructsPtr2.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required")
- type TestMultiDimensionalStructsPtr3 struct {
- Errs [][]*Inner `validate:"gt=0,dive,dive,omitempty"`
- }
- var errStructPtr3Array [][]*Inner
- errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}})
- errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}})
- errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, nil})
- tmsp3 := &TestMultiDimensionalStructsPtr3{
- Errs: errStructPtr3Array,
- }
- errs = validate.Struct(tmsp3)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 5)
- AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[0][1].Name", "TestMultiDimensionalStructsPtr3.Errs[0][1].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[0][2].Name", "TestMultiDimensionalStructsPtr3.Errs[0][2].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][1].Name", "TestMultiDimensionalStructsPtr3.Errs[1][1].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][2].Name", "TestMultiDimensionalStructsPtr3.Errs[1][2].Name", "Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[2][1].Name", "TestMultiDimensionalStructsPtr3.Errs[2][1].Name", "Name", "Name", "required")
- type TestMultiDimensionalTimeTime struct {
- Errs [][]*time.Time `validate:"gt=0,dive,dive,required"`
- }
- var errTimePtr3Array [][]*time.Time
- t1 := time.Now().UTC()
- t2 := time.Now().UTC()
- t3 := time.Now().UTC().Add(time.Hour * 24)
- errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, &t3})
- errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, nil})
- errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, nil, nil})
- tmtp3 := &TestMultiDimensionalTimeTime{
- Errs: errTimePtr3Array,
- }
- errs = validate.Struct(tmtp3)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 3)
- AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[1][2]", "TestMultiDimensionalTimeTime.Errs[1][2]", "Errs[1][2]", "Errs[1][2]", "required")
- AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[2][1]", "TestMultiDimensionalTimeTime.Errs[2][1]", "Errs[2][1]", "Errs[2][1]", "required")
- AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[2][2]", "TestMultiDimensionalTimeTime.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required")
- type TestMultiDimensionalTimeTime2 struct {
- Errs [][]*time.Time `validate:"gt=0,dive,dive,required"`
- }
- var errTimeArray [][]*time.Time
- t1 = time.Now().UTC()
- t2 = time.Now().UTC()
- t3 = time.Now().UTC().Add(time.Hour * 24)
- errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, &t3})
- errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, nil})
- errTimeArray = append(errTimeArray, []*time.Time{&t1, nil, nil})
- tmtp := &TestMultiDimensionalTimeTime2{
- Errs: errTimeArray,
- }
- errs = validate.Struct(tmtp)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 3)
- AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[1][2]", "TestMultiDimensionalTimeTime2.Errs[1][2]", "Errs[1][2]", "Errs[1][2]", "required")
- AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[2][1]", "TestMultiDimensionalTimeTime2.Errs[2][1]", "Errs[2][1]", "Errs[2][1]", "required")
- AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[2][2]", "TestMultiDimensionalTimeTime2.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required")
- }
- func TestNilStructPointerValidation(t *testing.T) {
- type Inner struct {
- Data string
- }
- type Outer struct {
- Inner *Inner `validate:"omitempty"`
- }
- inner := &Inner{
- Data: "test",
- }
- outer := &Outer{
- Inner: inner,
- }
- validate := New()
- errs := validate.Struct(outer)
- Equal(t, errs, nil)
- outer = &Outer{
- Inner: nil,
- }
- errs = validate.Struct(outer)
- Equal(t, errs, nil)
- type Inner2 struct {
- Data string
- }
- type Outer2 struct {
- Inner2 *Inner2 `validate:"required"`
- }
- inner2 := &Inner2{
- Data: "test",
- }
- outer2 := &Outer2{
- Inner2: inner2,
- }
- errs = validate.Struct(outer2)
- Equal(t, errs, nil)
- outer2 = &Outer2{
- Inner2: nil,
- }
- errs = validate.Struct(outer2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Outer2.Inner2", "Outer2.Inner2", "Inner2", "Inner2", "required")
- type Inner3 struct {
- Data string
- }
- type Outer3 struct {
- Inner3 *Inner3
- }
- inner3 := &Inner3{
- Data: "test",
- }
- outer3 := &Outer3{
- Inner3: inner3,
- }
- errs = validate.Struct(outer3)
- Equal(t, errs, nil)
- type Inner4 struct {
- Data string
- }
- type Outer4 struct {
- Inner4 *Inner4 `validate:"-"`
- }
- inner4 := &Inner4{
- Data: "test",
- }
- outer4 := &Outer4{
- Inner4: inner4,
- }
- errs = validate.Struct(outer4)
- Equal(t, errs, nil)
- }
- func TestSSNValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"00-90-8787", false},
- {"66690-76", false},
- {"191 60 2869", true},
- {"191-60-2869", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "ssn")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d SSN failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d SSN failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "ssn" {
- t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestLongitudeValidation(t *testing.T) {
- tests := []struct {
- param interface{}
- expected bool
- }{
- {"", false},
- {"-180.000", true},
- {"180.1", false},
- {"+73.234", true},
- {"+382.3811", false},
- {"23.11111111", true},
- {uint(180), true},
- {float32(-180.0), true},
- {-180, true},
- {180.1, false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "longitude")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d Longitude failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d Longitude failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "longitude" {
- t.Fatalf("Index: %d Longitude failed Error: %s", i, errs)
- }
- }
- }
- }
- PanicMatches(t, func() { _ = validate.Var(true, "longitude") }, "Bad field type bool")
- }
- func TestLatitudeValidation(t *testing.T) {
- tests := []struct {
- param interface{}
- expected bool
- }{
- {"", false},
- {"-90.000", true},
- {"+90", true},
- {"47.1231231", true},
- {"+99.9", false},
- {"108", false},
- {uint(90), true},
- {float32(-90.0), true},
- {-90, true},
- {90.1, false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "latitude")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "latitude" {
- t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
- }
- }
- }
- }
- PanicMatches(t, func() { _ = validate.Var(true, "latitude") }, "Bad field type bool")
- }
- func TestDataURIValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"data:image/png;base64,TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=", true},
- {"data:text/plain;base64,Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==", true},
- {"image/gif;base64,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false},
- {"data:image/gif;base64,MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw" +
- "UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye" +
- "rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619" +
- "FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx" +
- "QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ" +
- "Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ" + "HQIDAQAB", true},
- {"data:image/png;base64,12345", false},
- {"", false},
- {"data:text,:;base85,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "datauri")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "datauri" {
- t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestMultibyteValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", true},
- {"abc", false},
- {"123", false},
- {"<>@;.-=", false},
- {"ひらがな・カタカナ、.漢字", true},
- {"あいうえお foobar", true},
- {"test@example.com", true},
- {"test@example.com", true},
- {"1234abcDExyz", true},
- {"カタカナ", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "multibyte")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "multibyte" {
- t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestPrintableASCIIValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", true},
- {"foobar", false},
- {"xyz098", false},
- {"123456", false},
- {"カタカナ", false},
- {"foobar", true},
- {"0987654321", true},
- {"test@example.com", true},
- {"1234abcDEF", true},
- {"newline\n", false},
- {"\x19test\x7F", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "printascii")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "printascii" {
- t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestASCIIValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", true},
- {"foobar", false},
- {"xyz098", false},
- {"123456", false},
- {"カタカナ", false},
- {"foobar", true},
- {"0987654321", true},
- {"test@example.com", true},
- {"1234abcDEF", true},
- {"", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "ascii")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "ascii" {
- t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestUUID5Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
- {"9c858901-8a57-4791-81fe-4c455b099bc9", false},
- {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
- {"987fbc97-4bed-5078-af07-9141ba07c9f3", true},
- {"987fbc97-4bed-5078-9f07-9141ba07c9f3", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "uuid5")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "uuid5" {
- t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestUUID4Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
- {"a987fbc9-4bed-5078-af07-9141ba07c9f3", false},
- {"934859", false},
- {"57b73598-8764-4ad0-a76a-679bb6640eb1", true},
- {"625e63f3-58f5-40b7-83a1-a72ad31acffb", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "uuid4")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "uuid4" {
- t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestUUID3Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"412452646", false},
- {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
- {"a987fbc9-4bed-4078-8f07-9141ba07c9f3", false},
- {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "uuid3")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "uuid3" {
- t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestUUIDValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
- {"a987fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false},
- {"a987fbc94bed3078cf079141ba07c9f3", false},
- {"934859", false},
- {"987fbc9-4bed-3078-cf07a-9141ba07c9f3", false},
- {"aaaaaaaa-1111-1111-aaag-111111111111", false},
- {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "uuid")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "uuid" {
- t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestUUID5RFC4122Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"xxxa987Fbc9-4bed-3078-cf07-9141ba07c9f3", false},
- {"9c858901-8a57-4791-81Fe-4c455b099bc9", false},
- {"a987Fbc9-4bed-3078-cf07-9141ba07c9f3", false},
- {"987Fbc97-4bed-5078-af07-9141ba07c9f3", true},
- {"987Fbc97-4bed-5078-9f07-9141ba07c9f3", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "uuid5_rfc4122")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID5RFC4122 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID5RFC4122 failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "uuid5_rfc4122" {
- t.Fatalf("Index: %d UUID5RFC4122 failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestUUID4RFC4122Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9F3", false},
- {"a987fbc9-4bed-5078-af07-9141ba07c9F3", false},
- {"934859", false},
- {"57b73598-8764-4ad0-a76A-679bb6640eb1", true},
- {"625e63f3-58f5-40b7-83a1-a72ad31acFfb", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "uuid4_rfc4122")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID4RFC4122 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID4RFC4122 failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "uuid4_rfc4122" {
- t.Fatalf("Index: %d UUID4RFC4122 failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestUUID3RFC4122Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"412452646", false},
- {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9F3", false},
- {"a987fbc9-4bed-4078-8f07-9141ba07c9F3", false},
- {"a987fbc9-4bed-3078-cf07-9141ba07c9F3", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "uuid3_rfc4122")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID3RFC4122 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID3RFC4122 failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "uuid3_rfc4122" {
- t.Fatalf("Index: %d UUID3RFC4122 failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestUUIDRFC4122Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"xxxa987Fbc9-4bed-3078-cf07-9141ba07c9f3", false},
- {"a987Fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false},
- {"a987Fbc94bed3078cf079141ba07c9f3", false},
- {"934859", false},
- {"987fbc9-4bed-3078-cf07a-9141ba07c9F3", false},
- {"aaaaaaaa-1111-1111-aaaG-111111111111", false},
- {"a987Fbc9-4bed-3078-cf07-9141ba07c9f3", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "uuid_rfc4122")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUIDRFC4122 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUIDRFC4122 failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "uuid_rfc4122" {
- t.Fatalf("Index: %d UUIDRFC4122 failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestISBNValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"foo", false},
- {"3836221195", true},
- {"1-61729-085-8", true},
- {"3 423 21412 0", true},
- {"3 401 01319 X", true},
- {"9784873113685", true},
- {"978-4-87311-368-5", true},
- {"978 3401013190", true},
- {"978-3-8362-2119-1", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "isbn")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "isbn" {
- t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestISBN13Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"foo", false},
- {"3-8362-2119-5", false},
- {"01234567890ab", false},
- {"978 3 8362 2119 0", false},
- {"9784873113685", true},
- {"978-4-87311-368-5", true},
- {"978 3401013190", true},
- {"978-3-8362-2119-1", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "isbn13")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "isbn13" {
- t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestISBN10Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"foo", false},
- {"3423214121", false},
- {"978-3836221191", false},
- {"3-423-21412-1", false},
- {"3 423 21412 1", false},
- {"3836221195", true},
- {"1-61729-085-8", true},
- {"3 423 21412 0", true},
- {"3 401 01319 X", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "isbn10")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "isbn10" {
- t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestExcludesRuneValidation(t *testing.T) {
- tests := []struct {
- Value string `validate:"excludesrune=☻"`
- Tag string
- ExpectedNil bool
- }{
- {Value: "a☺b☻c☹d", Tag: "excludesrune=☻", ExpectedNil: false},
- {Value: "abcd", Tag: "excludesrune=☻", ExpectedNil: true},
- }
- validate := New()
- for i, s := range tests {
- errs := validate.Var(s.Value, s.Tag)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- errs = validate.Struct(s)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- }
- }
- func TestExcludesAllValidation(t *testing.T) {
- tests := []struct {
- Value string `validate:"excludesall=@!{}[]"`
- Tag string
- ExpectedNil bool
- }{
- {Value: "abcd@!jfk", Tag: "excludesall=@!{}[]", ExpectedNil: false},
- {Value: "abcdefg", Tag: "excludesall=@!{}[]", ExpectedNil: true},
- }
- validate := New()
- for i, s := range tests {
- errs := validate.Var(s.Value, s.Tag)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- errs = validate.Struct(s)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- }
- username := "joeybloggs "
- errs := validate.Var(username, "excludesall=@ ")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "excludesall")
- excluded := ","
- errs = validate.Var(excluded, "excludesall=!@#$%^&*()_+.0x2C?")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "excludesall")
- excluded = "="
- errs = validate.Var(excluded, "excludesall=!@#$%^&*()_+.0x2C=?")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "excludesall")
- }
- func TestExcludesValidation(t *testing.T) {
- tests := []struct {
- Value string `validate:"excludes=@"`
- Tag string
- ExpectedNil bool
- }{
- {Value: "abcd@!jfk", Tag: "excludes=@", ExpectedNil: false},
- {Value: "abcdq!jfk", Tag: "excludes=@", ExpectedNil: true},
- }
- validate := New()
- for i, s := range tests {
- errs := validate.Var(s.Value, s.Tag)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- errs = validate.Struct(s)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- }
- }
- func TestContainsRuneValidation(t *testing.T) {
- tests := []struct {
- Value string `validate:"containsrune=☻"`
- Tag string
- ExpectedNil bool
- }{
- {Value: "a☺b☻c☹d", Tag: "containsrune=☻", ExpectedNil: true},
- {Value: "abcd", Tag: "containsrune=☻", ExpectedNil: false},
- }
- validate := New()
- for i, s := range tests {
- errs := validate.Var(s.Value, s.Tag)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- errs = validate.Struct(s)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- }
- }
- func TestContainsAnyValidation(t *testing.T) {
- tests := []struct {
- Value string `validate:"containsany=@!{}[]"`
- Tag string
- ExpectedNil bool
- }{
- {Value: "abcd@!jfk", Tag: "containsany=@!{}[]", ExpectedNil: true},
- {Value: "abcdefg", Tag: "containsany=@!{}[]", ExpectedNil: false},
- }
- validate := New()
- for i, s := range tests {
- errs := validate.Var(s.Value, s.Tag)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- errs = validate.Struct(s)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- }
- }
- func TestContainsValidation(t *testing.T) {
- tests := []struct {
- Value string `validate:"contains=@"`
- Tag string
- ExpectedNil bool
- }{
- {Value: "abcd@!jfk", Tag: "contains=@", ExpectedNil: true},
- {Value: "abcdq!jfk", Tag: "contains=@", ExpectedNil: false},
- }
- validate := New()
- for i, s := range tests {
- errs := validate.Var(s.Value, s.Tag)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- errs = validate.Struct(s)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- }
- }
- func TestIsNeFieldValidation(t *testing.T) {
- validate := New()
- var j uint64
- var k float64
- s := "abcd"
- i := 1
- j = 1
- k = 1.543
- arr := []string{"test"}
- now := time.Now().UTC()
- var j2 uint64
- var k2 float64
- s2 := "abcdef"
- i2 := 3
- j2 = 2
- k2 = 1.5434456
- arr2 := []string{"test", "test2"}
- arr3 := []string{"test"}
- now2 := now
- errs := validate.VarWithValue(s, s2, "nefield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(i2, i, "nefield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(j2, j, "nefield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(k2, k, "nefield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(arr2, arr, "nefield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(now2, now, "nefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "nefield")
- errs = validate.VarWithValue(arr3, arr, "nefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "nefield")
- type Test struct {
- Start *time.Time `validate:"nefield=End"`
- End *time.Time
- }
- sv := &Test{
- Start: &now,
- End: &now,
- }
- errs = validate.Struct(sv)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.Start", "Test.Start", "Start", "Start", "nefield")
- now3 := time.Now().UTC()
- sv = &Test{
- Start: &now,
- End: &now3,
- }
- errs = validate.Struct(sv)
- Equal(t, errs, nil)
- errs = validate.VarWithValue(nil, 1, "nefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "nefield")
- errs = validate.VarWithValue(sv, now, "nefield")
- Equal(t, errs, nil)
- type Test2 struct {
- Start *time.Time `validate:"nefield=NonExistantField"`
- End *time.Time
- }
- sv2 := &Test2{
- Start: &now,
- End: &now,
- }
- errs = validate.Struct(sv2)
- Equal(t, errs, nil)
- type Other struct {
- Value string
- }
- type Test3 struct {
- Value Other
- Time time.Time `validate:"nefield=Value"`
- }
- tst := Test3{
- Value: Other{Value: "StringVal"},
- Time: now,
- }
- errs = validate.Struct(tst)
- Equal(t, errs, nil)
- }
- func TestIsNeValidation(t *testing.T) {
- validate := New()
- var j uint64
- var k float64
- s := "abcdef"
- i := 3
- j = 2
- k = 1.5434
- arr := []string{"test"}
- now := time.Now().UTC()
- errs := validate.Var(s, "ne=abcd")
- Equal(t, errs, nil)
- errs = validate.Var(i, "ne=1")
- Equal(t, errs, nil)
- errs = validate.Var(j, "ne=1")
- Equal(t, errs, nil)
- errs = validate.Var(k, "ne=1.543")
- Equal(t, errs, nil)
- errs = validate.Var(arr, "ne=2")
- Equal(t, errs, nil)
- errs = validate.Var(arr, "ne=1")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ne")
- PanicMatches(t, func() { _ = validate.Var(now, "ne=now") }, "Bad field type time.Time")
- }
- func TestIsEqFieldValidation(t *testing.T) {
- validate := New()
- var j uint64
- var k float64
- s := "abcd"
- i := 1
- j = 1
- k = 1.543
- arr := []string{"test"}
- now := time.Now().UTC()
- var j2 uint64
- var k2 float64
- s2 := "abcd"
- i2 := 1
- j2 = 1
- k2 = 1.543
- arr2 := []string{"test"}
- arr3 := []string{"test", "test2"}
- now2 := now
- errs := validate.VarWithValue(s, s2, "eqfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(i2, i, "eqfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(j2, j, "eqfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(k2, k, "eqfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(arr2, arr, "eqfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(now2, now, "eqfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(arr3, arr, "eqfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "eqfield")
- type Test struct {
- Start *time.Time `validate:"eqfield=End"`
- End *time.Time
- }
- sv := &Test{
- Start: &now,
- End: &now,
- }
- errs = validate.Struct(sv)
- Equal(t, errs, nil)
- now3 := time.Now().UTC()
- sv = &Test{
- Start: &now,
- End: &now3,
- }
- errs = validate.Struct(sv)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.Start", "Test.Start", "Start", "Start", "eqfield")
- errs = validate.VarWithValue(nil, 1, "eqfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "eqfield")
- channel := make(chan string)
- errs = validate.VarWithValue(5, channel, "eqfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "eqfield")
- errs = validate.VarWithValue(5, now, "eqfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "eqfield")
- type Test2 struct {
- Start *time.Time `validate:"eqfield=NonExistantField"`
- End *time.Time
- }
- sv2 := &Test2{
- Start: &now,
- End: &now,
- }
- errs = validate.Struct(sv2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test2.Start", "Test2.Start", "Start", "Start", "eqfield")
- type Inner struct {
- Name string
- }
- type TStruct struct {
- Inner *Inner
- CreatedAt *time.Time `validate:"eqfield=Inner"`
- }
- inner := &Inner{
- Name: "NAME",
- }
- test := &TStruct{
- Inner: inner,
- CreatedAt: &now,
- }
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqfield")
- }
- func TestIsEqValidation(t *testing.T) {
- validate := New()
- var j uint64
- var k float64
- s := "abcd"
- i := 1
- j = 1
- k = 1.543
- arr := []string{"test"}
- now := time.Now().UTC()
- errs := validate.Var(s, "eq=abcd")
- Equal(t, errs, nil)
- errs = validate.Var(i, "eq=1")
- Equal(t, errs, nil)
- errs = validate.Var(j, "eq=1")
- Equal(t, errs, nil)
- errs = validate.Var(k, "eq=1.543")
- Equal(t, errs, nil)
- errs = validate.Var(arr, "eq=1")
- Equal(t, errs, nil)
- errs = validate.Var(arr, "eq=2")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "eq")
- PanicMatches(t, func() { _ = validate.Var(now, "eq=now") }, "Bad field type time.Time")
- }
- func TestOneOfValidation(t *testing.T) {
- validate := New()
- passSpecs := []struct {
- f interface{}
- t string
- }{
- {f: "red", t: "oneof=red green"},
- {f: "green", t: "oneof=red green"},
- {f: 5, t: "oneof=5 6"},
- {f: 6, t: "oneof=5 6"},
- {f: int8(6), t: "oneof=5 6"},
- {f: int16(6), t: "oneof=5 6"},
- {f: int32(6), t: "oneof=5 6"},
- {f: int64(6), t: "oneof=5 6"},
- {f: uint(6), t: "oneof=5 6"},
- {f: uint8(6), t: "oneof=5 6"},
- {f: uint16(6), t: "oneof=5 6"},
- {f: uint32(6), t: "oneof=5 6"},
- {f: uint64(6), t: "oneof=5 6"},
- }
- for _, spec := range passSpecs {
- t.Logf("%#v", spec)
- errs := validate.Var(spec.f, spec.t)
- Equal(t, errs, nil)
- }
- failSpecs := []struct {
- f interface{}
- t string
- }{
- {f: "", t: "oneof=red green"},
- {f: "yellow", t: "oneof=red green"},
- {f: 5, t: "oneof=red green"},
- {f: 6, t: "oneof=red green"},
- {f: 6, t: "oneof=7"},
- {f: uint(6), t: "oneof=7"},
- {f: int8(5), t: "oneof=red green"},
- {f: int16(5), t: "oneof=red green"},
- {f: int32(5), t: "oneof=red green"},
- {f: int64(5), t: "oneof=red green"},
- {f: uint(5), t: "oneof=red green"},
- {f: uint8(5), t: "oneof=red green"},
- {f: uint16(5), t: "oneof=red green"},
- {f: uint32(5), t: "oneof=red green"},
- {f: uint64(5), t: "oneof=red green"},
- }
- for _, spec := range failSpecs {
- t.Logf("%#v", spec)
- errs := validate.Var(spec.f, spec.t)
- AssertError(t, errs, "", "", "", "", "oneof")
- }
- PanicMatches(t, func() {
- _ = validate.Var(3.14, "oneof=red green")
- }, "Bad field type float64")
- }
- func TestBase64Validation(t *testing.T) {
- validate := New()
- s := "dW5pY29ybg=="
- errs := validate.Var(s, "base64")
- Equal(t, errs, nil)
- s = "dGhpIGlzIGEgdGVzdCBiYXNlNjQ="
- errs = validate.Var(s, "base64")
- Equal(t, errs, nil)
- s = ""
- errs = validate.Var(s, "base64")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "base64")
- s = "dW5pY29ybg== foo bar"
- errs = validate.Var(s, "base64")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "base64")
- }
- func TestBase64URLValidation(t *testing.T) {
- validate := New()
- testCases := []struct {
- decoded, encoded string
- success bool
- }{
- // empty string, although a valid base64 string, should fail
- {"", "", false},
- // invalid length
- {"", "a", false},
- // base64 with padding
- {"f", "Zg==", true},
- {"fo", "Zm8=", true},
- // base64 without padding
- {"foo", "Zm9v", true},
- {"", "Zg", false},
- {"", "Zm8", false},
- // base64 URL safe encoding with invalid, special characters '+' and '/'
- {"\x14\xfb\x9c\x03\xd9\x7e", "FPucA9l+", false},
- {"\x14\xfb\x9c\x03\xf9\x73", "FPucA/lz", false},
- // base64 URL safe encoding with valid, special characters '-' and '_'
- {"\x14\xfb\x9c\x03\xd9\x7e", "FPucA9l-", true},
- {"\x14\xfb\x9c\x03\xf9\x73", "FPucA_lz", true},
- // non base64 characters
- {"", "@mc=", false},
- {"", "Zm 9", false},
- }
- for _, tc := range testCases {
- err := validate.Var(tc.encoded, "base64url")
- if tc.success {
- Equal(t, err, nil)
- // make sure encoded value is decoded back to the expected value
- d, innerErr := base64.URLEncoding.DecodeString(tc.encoded)
- Equal(t, innerErr, nil)
- Equal(t, tc.decoded, string(d))
- } else {
- NotEqual(t, err, nil)
- if len(tc.encoded) > 0 {
- // make sure that indeed the encoded value was faulty
- _, err := base64.URLEncoding.DecodeString(tc.encoded)
- NotEqual(t, err, nil)
- }
- }
- }
- }
- func TestFileValidation(t *testing.T) {
- validate := New()
- tests := []struct {
- title string
- param string
- expected bool
- }{
- {"empty path", "", false},
- {"regular file", filepath.Join("testdata", "a.go"), true},
- {"missing file", filepath.Join("testdata", "no.go"), false},
- {"directory, not a file", "testdata", false},
- }
- for _, test := range tests {
- errs := validate.Var(test.param, "file")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Test: '%s' failed Error: %s", test.title, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Test: '%s' failed Error: %s", test.title, errs)
- }
- }
- }
- PanicMatches(t, func() {
- _ = validate.Var(6, "file")
- }, "Bad field type int")
- }
- func TestEthereumAddressValidation(t *testing.T) {
- validate := New()
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"0x02F9AE5f22EA3fA88F05780B30385bEC", false},
- {"123f681646d4a755815f9cb19e1acc8565a0c2ac", false},
- {"0x02F9AE5f22EA3fA88F05780B30385bECFacbf130", true},
- {"0x123f681646d4a755815f9cb19e1acc8565a0c2ac", true},
- }
- for i, test := range tests {
- errs := validate.Var(test.param, "eth_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d eth_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d eth_addr failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "eth_addr" {
- t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestBitcoinAddressValidation(t *testing.T) {
- validate := New()
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"x", false},
- {"0x02F9AE5f22EA3fA88F05780B30385bEC", false},
- {"1A1zP1ePQGefi2DMPTifTL5SLmv7DivfNa", false},
- {"1P9RQEr2XeE3PEb44ZE35sfZRRW1JH8Uqx", false},
- {"3P14159I73E4gFr7JterCCQh9QjiTjiZrG", false},
- {"3P141597f3E4gFr7JterCCQh9QjiTjiZrG", false},
- {"37qgekLpCCHrQuSjvX3fs496FWTGsHFHizjJAs6NPcR47aefnnCWECAhHV6E3g4YN7u7Yuwod5Y", false},
- {"dzb7VV1Ui55BARxv7ATxAtCUeJsANKovDGWFVgpTbhq9gvPqP3yv", false},
- {"MuNu7ZAEDFiHthiunm7dPjwKqrVNCM3mAz6rP9zFveQu14YA8CxExSJTHcVP9DErn6u84E6Ej7S", false},
- {"rPpQpYknyNQ5AEHuY6H8ijJJrYc2nDKKk9jjmKEXsWzyAQcFGpDLU2Zvsmoi8JLR7hAwoy3RQWf", false},
- {"4Uc3FmN6NQ6zLBK5QQBXRBUREaaHwCZYsGCueHauuDmJpZKn6jkEskMB2Zi2CNgtb5r6epWEFfUJq", false},
- {"7aQgR5DFQ25vyXmqZAWmnVCjL3PkBcdVkBUpjrjMTcghHx3E8wb", false},
- {"17QpPprjeg69fW1DV8DcYYCKvWjYhXvWkov6MJ1iTTvMFj6weAqW7wybZeH57WTNxXVCRH4veVs", false},
- {"KxuACDviz8Xvpn1xAh9MfopySZNuyajYMZWz16Dv2mHHryznWUp3", false},
- {"7nK3GSmqdXJQtdohvGfJ7KsSmn3TmGqExug49583bDAL91pVSGq5xS9SHoAYL3Wv3ijKTit65th", false},
- {"cTivdBmq7bay3RFGEBBuNfMh2P1pDCgRYN2Wbxmgwr4ki3jNUL2va", false},
- {"gjMV4vjNjyMrna4fsAr8bWxAbwtmMUBXJS3zL4NJt5qjozpbQLmAfK1uA3CquSqsZQMpoD1g2nk", false},
- {"emXm1naBMoVzPjbk7xpeTVMFy4oDEe25UmoyGgKEB1gGWsK8kRGs", false},
- {"7VThQnNRj1o3Zyvc7XHPRrjDf8j2oivPTeDXnRPYWeYGE4pXeRJDZgf28ppti5hsHWXS2GSobdqyo", false},
- {"1G9u6oCVCPh2o8m3t55ACiYvG1y5BHewUkDSdiQarDcYXXhFHYdzMdYfUAhfxn5vNZBwpgUNpso", false},
- {"31QQ7ZMLkScDiB4VyZjuptr7AEc9j1SjstF7pRoLhHTGkW4Q2y9XELobQmhhWxeRvqcukGd1XCq", false},
- {"DHqKSnpxa8ZdQyH8keAhvLTrfkyBMQxqngcQA5N8LQ9KVt25kmGN", false},
- {"2LUHcJPbwLCy9GLH1qXmfmAwvadWw4bp4PCpDfduLqV17s6iDcy1imUwhQJhAoNoN1XNmweiJP4i", false},
- {"7USRzBXAnmck8fX9HmW7RAb4qt92VFX6soCnts9s74wxm4gguVhtG5of8fZGbNPJA83irHVY6bCos", false},
- {"1DGezo7BfVebZxAbNT3XGujdeHyNNBF3vnficYoTSp4PfK2QaML9bHzAMxke3wdKdHYWmsMTJVu", false},
- {"2D12DqDZKwCxxkzs1ZATJWvgJGhQ4cFi3WrizQ5zLAyhN5HxuAJ1yMYaJp8GuYsTLLxTAz6otCfb", false},
- {"8AFJzuTujXjw1Z6M3fWhQ1ujDW7zsV4ePeVjVo7D1egERqSW9nZ", false},
- {"163Q17qLbTCue8YY3AvjpUhotuaodLm2uqMhpYirsKjVqnxJRWTEoywMVY3NbBAHuhAJ2cF9GAZ", false},
- {"2MnmgiRH4eGLyLc9eAqStzk7dFgBjFtUCtu", false},
- {"461QQ2sYWxU7H2PV4oBwJGNch8XVTYYbZxU", false},
- {"2UCtv53VttmQYkVU4VMtXB31REvQg4ABzs41AEKZ8UcB7DAfVzdkV9JDErwGwyj5AUHLkmgZeobs", false},
- {"cSNjAsnhgtiFMi6MtfvgscMB2Cbhn2v1FUYfviJ1CdjfidvmeW6mn", false},
- {"gmsow2Y6EWAFDFE1CE4Hd3Tpu2BvfmBfG1SXsuRARbnt1WjkZnFh1qGTiptWWbjsq2Q6qvpgJVj", false},
- {"nksUKSkzS76v8EsSgozXGMoQFiCoCHzCVajFKAXqzK5on9ZJYVHMD5CKwgmX3S3c7M1U3xabUny", false},
- {"L3favK1UzFGgdzYBF2oBT5tbayCo4vtVBLJhg2iYuMeePxWG8SQc", false},
- {"7VxLxGGtYT6N99GdEfi6xz56xdQ8nP2dG1CavuXx7Rf2PrvNMTBNevjkfgs9JmkcGm6EXpj8ipyPZ ", false},
- {"2mbZwFXF6cxShaCo2czTRB62WTx9LxhTtpP", false},
- {"dB7cwYdcPSgiyAwKWL3JwCVwSk6epU2txw", false},
- {"HPhFUhUAh8ZQQisH8QQWafAxtQYju3SFTX", false},
- {"4ctAH6AkHzq5ioiM1m9T3E2hiYEev5mTsB", false},
- {"31uEbMgunupShBVTewXjtqbBv5MndwfXhb", false},
- {"175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W", false},
- {"Hn1uFi4dNexWrqARpjMqgT6cX1UsNPuV3cHdGg9ExyXw8HTKadbktRDtdeVmY3M1BxJStiL4vjJ", false},
- {"Sq3fDbvutABmnAHHExJDgPLQn44KnNC7UsXuT7KZecpaYDMU9Txs", false},
- {"6TqWyrqdgUEYDQU1aChMuFMMEimHX44qHFzCUgGfqxGgZNMUVWJ", false},
- {"giqJo7oWqFxNKWyrgcBxAVHXnjJ1t6cGoEffce5Y1y7u649Noj5wJ4mmiUAKEVVrYAGg2KPB3Y4", false},
- {"cNzHY5e8vcmM3QVJUcjCyiKMYfeYvyueq5qCMV3kqcySoLyGLYUK", false},
- {"37uTe568EYc9WLoHEd9jXEvUiWbq5LFLscNyqvAzLU5vBArUJA6eydkLmnMwJDjkL5kXc2VK7ig", false},
- {"EsYbG4tWWWY45G31nox838qNdzksbPySWc", false},
- {"nbuzhfwMoNzA3PaFnyLcRxE9bTJPDkjZ6Rf6Y6o2ckXZfzZzXBT", false},
- {"cQN9PoxZeCWK1x56xnz6QYAsvR11XAce3Ehp3gMUdfSQ53Y2mPzx", false},
- {"1Gm3N3rkef6iMbx4voBzaxtXcmmiMTqZPhcuAepRzYUJQW4qRpEnHvMojzof42hjFRf8PE2jPde", false},
- {"2TAq2tuN6x6m233bpT7yqdYQPELdTDJn1eU", false},
- {"ntEtnnGhqPii4joABvBtSEJG6BxjT2tUZqE8PcVYgk3RHpgxgHDCQxNbLJf7ardf1dDk2oCQ7Cf", false},
- {"Ky1YjoZNgQ196HJV3HpdkecfhRBmRZdMJk89Hi5KGfpfPwS2bUbfd", false},
- {"2A1q1YsMZowabbvta7kTy2Fd6qN4r5ZCeG3qLpvZBMzCixMUdkN2Y4dHB1wPsZAeVXUGD83MfRED", false},
- {"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", true},
- {"1Ax4gZtb7gAit2TivwejZHYtNNLT18PUXJ", true},
- {"1C5bSj1iEGUgSTbziymG7Cn18ENQuT36vv", true},
- {"1Gqk4Tv79P91Cc1STQtU3s1W6277M2CVWu", true},
- {"1JwMWBVLtiqtscbaRHai4pqHokhFCbtoB4", true},
- {"19dcawoKcZdQz365WpXWMhX6QCUpR9SY4r", true},
- {"13p1ijLwsnrcuyqcTvJXkq2ASdXqcnEBLE", true},
- {"1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2", true},
- {"3P14159f73E4gFr7JterCCQh9QjiTjiZrG", true},
- {"3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou", true},
- {"3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy", true},
- {"3AnNxabYGoTxYiTEZwFEnerUoeFXK2Zoks", true},
- {"33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk", true},
- {"3QCzvfL4ZRvmJFiWWBVwxfdaNBT8EtxB5y", true},
- {"37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3", true},
- {"3ALJH9Y951VCGcVZYAdpA3KchoP9McEj1G", true},
- {"12KYrjTdVGjFMtaxERSk3gphreJ5US8aUP", true},
- {"12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y", true},
- {"1oNLrsHnBcR6dpaBpwz3LSwutbUNkNSjs", true},
- {"1SQHtwR5oJRKLfiWQ2APsAd9miUc4k2ez", true},
- {"116CGDLddrZhMrTwhCVJXtXQpxygTT1kHd", true},
- {"3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt", true},
- }
- for i, test := range tests {
- errs := validate.Var(test.param, "btc_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d btc_addr failed with Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d btc_addr failed with Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "btc_addr" {
- t.Fatalf("Index: %d Latitude failed with Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestBitcoinBech32AddressValidation(t *testing.T) {
- validate := New()
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"bc1rw5uspcuh", false},
- {"bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5", false},
- {"BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2", false},
- {"qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty", false},
- {"bc1rw5uspcuh", false},
- {"bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90", false},
- {"BC1QW508d6QEJxTDG4y5R3ZArVARY0C5XW7KV8F3T4", false},
- {"BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P", false},
- {"bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5", false},
- {"bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90", false},
- {"bc1pw508d6qejxtdg4y5r3zarqfsj6c3", false},
- {"bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du", false},
- {"bc1gmk9yu", false},
- {"bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv", false},
- {"BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4", true},
- {"bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx", true},
- {"bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3", true},
- {"BC1SW50QA3JX3S", true},
- {"bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj", true},
- }
- for i, test := range tests {
- errs := validate.Var(test.param, "btc_addr_bech32")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d btc_addr_bech32 failed with Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d btc_addr_bech32 failed with Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "btc_addr_bech32" {
- t.Fatalf("Index: %d Latitude failed with Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestNoStructLevelValidation(t *testing.T) {
- type Inner struct {
- Test string `validate:"len=5"`
- }
- type Outer struct {
- InnerStruct *Inner `validate:"required,nostructlevel"`
- }
- outer := &Outer{
- InnerStruct: nil,
- }
- validate := New()
- errs := validate.Struct(outer)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Outer.InnerStruct", "Outer.InnerStruct", "InnerStruct", "InnerStruct", "required")
- inner := &Inner{
- Test: "1234",
- }
- outer = &Outer{
- InnerStruct: inner,
- }
- errs = validate.Struct(outer)
- Equal(t, errs, nil)
- }
- func TestStructOnlyValidation(t *testing.T) {
- type Inner struct {
- Test string `validate:"len=5"`
- }
- type Outer struct {
- InnerStruct *Inner `validate:"required,structonly"`
- }
- outer := &Outer{
- InnerStruct: nil,
- }
- validate := New()
- errs := validate.Struct(outer)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Outer.InnerStruct", "Outer.InnerStruct", "InnerStruct", "InnerStruct", "required")
- inner := &Inner{
- Test: "1234",
- }
- outer = &Outer{
- InnerStruct: inner,
- }
- errs = validate.Struct(outer)
- Equal(t, errs, nil)
- // Address houses a users address information
- type Address struct {
- Street string `validate:"required"`
- City string `validate:"required"`
- Planet string `validate:"required"`
- Phone string `validate:"required"`
- }
- type User struct {
- FirstName string `json:"fname"`
- LastName string `json:"lname"`
- Age uint8 `validate:"gte=0,lte=130"`
- Email string `validate:"required,email"`
- FavouriteColor string `validate:"hexcolor|rgb|rgba"`
- Addresses []*Address `validate:"required"` // a person can have a home and cottage...
- Address Address `validate:"structonly"` // a person can have a home and cottage...
- }
- address := &Address{
- Street: "Eavesdown Docks",
- Planet: "Persphone",
- Phone: "none",
- City: "Unknown",
- }
- user := &User{
- FirstName: "",
- LastName: "",
- Age: 45,
- Email: "Badger.Smith@gmail.com",
- FavouriteColor: "#000",
- Addresses: []*Address{address},
- Address: Address{
- // Street: "Eavesdown Docks",
- Planet: "Persphone",
- Phone: "none",
- City: "Unknown",
- },
- }
- errs = validate.Struct(user)
- Equal(t, errs, nil)
- }
- func TestGtField(t *testing.T) {
- validate := New()
- type TimeTest struct {
- Start *time.Time `validate:"required,gt"`
- End *time.Time `validate:"required,gt,gtfield=Start"`
- }
- now := time.Now()
- start := now.Add(time.Hour * 24)
- end := start.Add(time.Hour * 24)
- timeTest := &TimeTest{
- Start: &start,
- End: &end,
- }
- errs := validate.Struct(timeTest)
- Equal(t, errs, nil)
- timeTest = &TimeTest{
- Start: &end,
- End: &start,
- }
- errs = validate.Struct(timeTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest.End", "TimeTest.End", "End", "End", "gtfield")
- errs = validate.VarWithValue(&end, &start, "gtfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(&start, &end, "gtfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtfield")
- errs = validate.VarWithValue(&end, &start, "gtfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(&timeTest, &end, "gtfield")
- NotEqual(t, errs, nil)
- errs = validate.VarWithValue("test bigger", "test", "gtfield")
- Equal(t, errs, nil)
- type IntTest struct {
- Val1 int `validate:"required"`
- Val2 int `validate:"required,gtfield=Val1"`
- }
- intTest := &IntTest{
- Val1: 1,
- Val2: 5,
- }
- errs = validate.Struct(intTest)
- Equal(t, errs, nil)
- intTest = &IntTest{
- Val1: 5,
- Val2: 1,
- }
- errs = validate.Struct(intTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "gtfield")
- errs = validate.VarWithValue(int(5), int(1), "gtfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(int(1), int(5), "gtfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtfield")
- type UIntTest struct {
- Val1 uint `validate:"required"`
- Val2 uint `validate:"required,gtfield=Val1"`
- }
- uIntTest := &UIntTest{
- Val1: 1,
- Val2: 5,
- }
- errs = validate.Struct(uIntTest)
- Equal(t, errs, nil)
- uIntTest = &UIntTest{
- Val1: 5,
- Val2: 1,
- }
- errs = validate.Struct(uIntTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "gtfield")
- errs = validate.VarWithValue(uint(5), uint(1), "gtfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(uint(1), uint(5), "gtfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtfield")
- type FloatTest struct {
- Val1 float64 `validate:"required"`
- Val2 float64 `validate:"required,gtfield=Val1"`
- }
- floatTest := &FloatTest{
- Val1: 1,
- Val2: 5,
- }
- errs = validate.Struct(floatTest)
- Equal(t, errs, nil)
- floatTest = &FloatTest{
- Val1: 5,
- Val2: 1,
- }
- errs = validate.Struct(floatTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "gtfield")
- errs = validate.VarWithValue(float32(5), float32(1), "gtfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(float32(1), float32(5), "gtfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtfield")
- errs = validate.VarWithValue(nil, 1, "gtfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtfield")
- errs = validate.VarWithValue(5, "T", "gtfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtfield")
- errs = validate.VarWithValue(5, start, "gtfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtfield")
- type TimeTest2 struct {
- Start *time.Time `validate:"required"`
- End *time.Time `validate:"required,gtfield=NonExistantField"`
- }
- timeTest2 := &TimeTest2{
- Start: &start,
- End: &end,
- }
- errs = validate.Struct(timeTest2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "gtfield")
- type Other struct {
- Value string
- }
- type Test struct {
- Value Other
- Time time.Time `validate:"gtfield=Value"`
- }
- tst := Test{
- Value: Other{Value: "StringVal"},
- Time: end,
- }
- errs = validate.Struct(tst)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.Time", "Test.Time", "Time", "Time", "gtfield")
- }
- func TestLtField(t *testing.T) {
- validate := New()
- type TimeTest struct {
- Start *time.Time `validate:"required,lt,ltfield=End"`
- End *time.Time `validate:"required,lt"`
- }
- now := time.Now()
- start := now.Add(time.Hour * 24 * -1 * 2)
- end := start.Add(time.Hour * 24)
- timeTest := &TimeTest{
- Start: &start,
- End: &end,
- }
- errs := validate.Struct(timeTest)
- Equal(t, errs, nil)
- timeTest = &TimeTest{
- Start: &end,
- End: &start,
- }
- errs = validate.Struct(timeTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest.Start", "TimeTest.Start", "Start", "Start", "ltfield")
- errs = validate.VarWithValue(&start, &end, "ltfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(&end, &start, "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltfield")
- errs = validate.VarWithValue(&end, timeTest, "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltfield")
- errs = validate.VarWithValue("tes", "test", "ltfield")
- Equal(t, errs, nil)
- type IntTest struct {
- Val1 int `validate:"required"`
- Val2 int `validate:"required,ltfield=Val1"`
- }
- intTest := &IntTest{
- Val1: 5,
- Val2: 1,
- }
- errs = validate.Struct(intTest)
- Equal(t, errs, nil)
- intTest = &IntTest{
- Val1: 1,
- Val2: 5,
- }
- errs = validate.Struct(intTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "ltfield")
- errs = validate.VarWithValue(int(1), int(5), "ltfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(int(5), int(1), "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltfield")
- type UIntTest struct {
- Val1 uint `validate:"required"`
- Val2 uint `validate:"required,ltfield=Val1"`
- }
- uIntTest := &UIntTest{
- Val1: 5,
- Val2: 1,
- }
- errs = validate.Struct(uIntTest)
- Equal(t, errs, nil)
- uIntTest = &UIntTest{
- Val1: 1,
- Val2: 5,
- }
- errs = validate.Struct(uIntTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "ltfield")
- errs = validate.VarWithValue(uint(1), uint(5), "ltfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(uint(5), uint(1), "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltfield")
- type FloatTest struct {
- Val1 float64 `validate:"required"`
- Val2 float64 `validate:"required,ltfield=Val1"`
- }
- floatTest := &FloatTest{
- Val1: 5,
- Val2: 1,
- }
- errs = validate.Struct(floatTest)
- Equal(t, errs, nil)
- floatTest = &FloatTest{
- Val1: 1,
- Val2: 5,
- }
- errs = validate.Struct(floatTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "ltfield")
- errs = validate.VarWithValue(float32(1), float32(5), "ltfield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(float32(5), float32(1), "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltfield")
- errs = validate.VarWithValue(nil, 5, "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltfield")
- errs = validate.VarWithValue(1, "T", "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltfield")
- errs = validate.VarWithValue(1, end, "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltfield")
- type TimeTest2 struct {
- Start *time.Time `validate:"required"`
- End *time.Time `validate:"required,ltfield=NonExistantField"`
- }
- timeTest2 := &TimeTest2{
- Start: &end,
- End: &start,
- }
- errs = validate.Struct(timeTest2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "ltfield")
- }
- func TestFieldContains(t *testing.T) {
- validate := New()
- type StringTest struct {
- Foo string `validate:"fieldcontains=Bar"`
- Bar string
- }
- stringTest := &StringTest{
- Foo: "foobar",
- Bar: "bar",
- }
- errs := validate.Struct(stringTest)
- Equal(t, errs, nil)
- stringTest = &StringTest{
- Foo: "foo",
- Bar: "bar",
- }
- errs = validate.Struct(stringTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "StringTest.Foo", "StringTest.Foo", "Foo", "Foo", "fieldcontains")
- errs = validate.VarWithValue("foo", "bar", "fieldcontains")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "fieldcontains")
- errs = validate.VarWithValue("bar", "foobarfoo", "fieldcontains")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "fieldcontains")
- errs = validate.VarWithValue("foobarfoo", "bar", "fieldcontains")
- Equal(t, errs, nil)
- type StringTestMissingField struct {
- Foo string `validate:"fieldcontains=Bar"`
- }
- stringTestMissingField := &StringTestMissingField{
- Foo: "foo",
- }
- errs = validate.Struct(stringTestMissingField)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "StringTestMissingField.Foo", "StringTestMissingField.Foo", "Foo", "Foo", "fieldcontains")
- }
- func TestFieldExcludes(t *testing.T) {
- validate := New()
- type StringTest struct {
- Foo string `validate:"fieldexcludes=Bar"`
- Bar string
- }
- stringTest := &StringTest{
- Foo: "foobar",
- Bar: "bar",
- }
- errs := validate.Struct(stringTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "StringTest.Foo", "StringTest.Foo", "Foo", "Foo", "fieldexcludes")
- stringTest = &StringTest{
- Foo: "foo",
- Bar: "bar",
- }
- errs = validate.Struct(stringTest)
- Equal(t, errs, nil)
- errs = validate.VarWithValue("foo", "bar", "fieldexcludes")
- Equal(t, errs, nil)
- errs = validate.VarWithValue("bar", "foobarfoo", "fieldexcludes")
- Equal(t, errs, nil)
- errs = validate.VarWithValue("foobarfoo", "bar", "fieldexcludes")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "fieldexcludes")
- type StringTestMissingField struct {
- Foo string `validate:"fieldexcludes=Bar"`
- }
- stringTestMissingField := &StringTestMissingField{
- Foo: "foo",
- }
- errs = validate.Struct(stringTestMissingField)
- Equal(t, errs, nil)
- }
- func TestContainsAndExcludes(t *testing.T) {
- validate := New()
- type ImpossibleStringTest struct {
- Foo string `validate:"fieldcontains=Bar"`
- Bar string `validate:"fieldexcludes=Foo"`
- }
- impossibleStringTest := &ImpossibleStringTest{
- Foo: "foo",
- Bar: "bar",
- }
- errs := validate.Struct(impossibleStringTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "ImpossibleStringTest.Foo", "ImpossibleStringTest.Foo", "Foo", "Foo", "fieldcontains")
- impossibleStringTest = &ImpossibleStringTest{
- Foo: "bar",
- Bar: "foo",
- }
- errs = validate.Struct(impossibleStringTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "ImpossibleStringTest.Foo", "ImpossibleStringTest.Foo", "Foo", "Foo", "fieldcontains")
- }
- func TestLteField(t *testing.T) {
- validate := New()
- type TimeTest struct {
- Start *time.Time `validate:"required,lte,ltefield=End"`
- End *time.Time `validate:"required,lte"`
- }
- now := time.Now()
- start := now.Add(time.Hour * 24 * -1 * 2)
- end := start.Add(time.Hour * 24)
- timeTest := &TimeTest{
- Start: &start,
- End: &end,
- }
- errs := validate.Struct(timeTest)
- Equal(t, errs, nil)
- timeTest = &TimeTest{
- Start: &end,
- End: &start,
- }
- errs = validate.Struct(timeTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest.Start", "TimeTest.Start", "Start", "Start", "ltefield")
- errs = validate.VarWithValue(&start, &end, "ltefield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(&end, &start, "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltefield")
- errs = validate.VarWithValue(&end, timeTest, "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltefield")
- errs = validate.VarWithValue("tes", "test", "ltefield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue("test", "test", "ltefield")
- Equal(t, errs, nil)
- type IntTest struct {
- Val1 int `validate:"required"`
- Val2 int `validate:"required,ltefield=Val1"`
- }
- intTest := &IntTest{
- Val1: 5,
- Val2: 1,
- }
- errs = validate.Struct(intTest)
- Equal(t, errs, nil)
- intTest = &IntTest{
- Val1: 1,
- Val2: 5,
- }
- errs = validate.Struct(intTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "ltefield")
- errs = validate.VarWithValue(int(1), int(5), "ltefield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(int(5), int(1), "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltefield")
- type UIntTest struct {
- Val1 uint `validate:"required"`
- Val2 uint `validate:"required,ltefield=Val1"`
- }
- uIntTest := &UIntTest{
- Val1: 5,
- Val2: 1,
- }
- errs = validate.Struct(uIntTest)
- Equal(t, errs, nil)
- uIntTest = &UIntTest{
- Val1: 1,
- Val2: 5,
- }
- errs = validate.Struct(uIntTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "ltefield")
- errs = validate.VarWithValue(uint(1), uint(5), "ltefield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(uint(5), uint(1), "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltefield")
- type FloatTest struct {
- Val1 float64 `validate:"required"`
- Val2 float64 `validate:"required,ltefield=Val1"`
- }
- floatTest := &FloatTest{
- Val1: 5,
- Val2: 1,
- }
- errs = validate.Struct(floatTest)
- Equal(t, errs, nil)
- floatTest = &FloatTest{
- Val1: 1,
- Val2: 5,
- }
- errs = validate.Struct(floatTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "ltefield")
- errs = validate.VarWithValue(float32(1), float32(5), "ltefield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(float32(5), float32(1), "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltefield")
- errs = validate.VarWithValue(nil, 5, "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltefield")
- errs = validate.VarWithValue(1, "T", "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltefield")
- errs = validate.VarWithValue(1, end, "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "ltefield")
- type TimeTest2 struct {
- Start *time.Time `validate:"required"`
- End *time.Time `validate:"required,ltefield=NonExistantField"`
- }
- timeTest2 := &TimeTest2{
- Start: &end,
- End: &start,
- }
- errs = validate.Struct(timeTest2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "ltefield")
- }
- func TestGteField(t *testing.T) {
- validate := New()
- type TimeTest struct {
- Start *time.Time `validate:"required,gte"`
- End *time.Time `validate:"required,gte,gtefield=Start"`
- }
- now := time.Now()
- start := now.Add(time.Hour * 24)
- end := start.Add(time.Hour * 24)
- timeTest := &TimeTest{
- Start: &start,
- End: &end,
- }
- errs := validate.Struct(timeTest)
- Equal(t, errs, nil)
- timeTest = &TimeTest{
- Start: &end,
- End: &start,
- }
- errs = validate.Struct(timeTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest.End", "TimeTest.End", "End", "End", "gtefield")
- errs = validate.VarWithValue(&end, &start, "gtefield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(&start, &end, "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtefield")
- errs = validate.VarWithValue(&start, timeTest, "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtefield")
- errs = validate.VarWithValue("test", "test", "gtefield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue("test bigger", "test", "gtefield")
- Equal(t, errs, nil)
- type IntTest struct {
- Val1 int `validate:"required"`
- Val2 int `validate:"required,gtefield=Val1"`
- }
- intTest := &IntTest{
- Val1: 1,
- Val2: 5,
- }
- errs = validate.Struct(intTest)
- Equal(t, errs, nil)
- intTest = &IntTest{
- Val1: 5,
- Val2: 1,
- }
- errs = validate.Struct(intTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "gtefield")
- errs = validate.VarWithValue(int(5), int(1), "gtefield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(int(1), int(5), "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtefield")
- type UIntTest struct {
- Val1 uint `validate:"required"`
- Val2 uint `validate:"required,gtefield=Val1"`
- }
- uIntTest := &UIntTest{
- Val1: 1,
- Val2: 5,
- }
- errs = validate.Struct(uIntTest)
- Equal(t, errs, nil)
- uIntTest = &UIntTest{
- Val1: 5,
- Val2: 1,
- }
- errs = validate.Struct(uIntTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "gtefield")
- errs = validate.VarWithValue(uint(5), uint(1), "gtefield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(uint(1), uint(5), "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtefield")
- type FloatTest struct {
- Val1 float64 `validate:"required"`
- Val2 float64 `validate:"required,gtefield=Val1"`
- }
- floatTest := &FloatTest{
- Val1: 1,
- Val2: 5,
- }
- errs = validate.Struct(floatTest)
- Equal(t, errs, nil)
- floatTest = &FloatTest{
- Val1: 5,
- Val2: 1,
- }
- errs = validate.Struct(floatTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "gtefield")
- errs = validate.VarWithValue(float32(5), float32(1), "gtefield")
- Equal(t, errs, nil)
- errs = validate.VarWithValue(float32(1), float32(5), "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtefield")
- errs = validate.VarWithValue(nil, 1, "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtefield")
- errs = validate.VarWithValue(5, "T", "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtefield")
- errs = validate.VarWithValue(5, start, "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gtefield")
- type TimeTest2 struct {
- Start *time.Time `validate:"required"`
- End *time.Time `validate:"required,gtefield=NonExistantField"`
- }
- timeTest2 := &TimeTest2{
- Start: &start,
- End: &end,
- }
- errs = validate.Struct(timeTest2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "gtefield")
- }
- func TestValidateByTagAndValue(t *testing.T) {
- validate := New()
- val := "test"
- field := "test"
- errs := validate.VarWithValue(val, field, "required")
- Equal(t, errs, nil)
- fn := func(fl FieldLevel) bool {
- return fl.Parent().String() == fl.Field().String()
- }
- errs = validate.RegisterValidation("isequaltestfunc", fn)
- Equal(t, errs, nil)
- errs = validate.VarWithValue(val, field, "isequaltestfunc")
- Equal(t, errs, nil)
- val = "unequal"
- errs = validate.VarWithValue(val, field, "isequaltestfunc")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "isequaltestfunc")
- }
- func TestAddFunctions(t *testing.T) {
- fn := func(fl FieldLevel) bool {
- return true
- }
- fnCtx := func(ctx context.Context, fl FieldLevel) bool {
- return true
- }
- validate := New()
- errs := validate.RegisterValidation("new", fn)
- Equal(t, errs, nil)
- errs = validate.RegisterValidation("", fn)
- NotEqual(t, errs, nil)
- errs = validate.RegisterValidation("new", nil)
- NotEqual(t, errs, nil)
- errs = validate.RegisterValidation("new", fn)
- Equal(t, errs, nil)
- errs = validate.RegisterValidationCtx("new", fnCtx)
- Equal(t, errs, nil)
- PanicMatches(t, func() { _ = validate.RegisterValidation("dive", fn) }, "Tag 'dive' either contains restricted characters or is the same as a restricted tag needed for normal operation")
- }
- func TestChangeTag(t *testing.T) {
- validate := New()
- validate.SetTagName("val")
- type Test struct {
- Name string `val:"len=4"`
- }
- s := &Test{
- Name: "TEST",
- }
- errs := validate.Struct(s)
- Equal(t, errs, nil)
- s.Name = ""
- errs = validate.Struct(s)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.Name", "Test.Name", "Name", "Name", "len")
- }
- func TestUnexposedStruct(t *testing.T) {
- validate := New()
- type Test struct {
- Name string
- unexposed struct {
- A string `validate:"required"`
- }
- }
- s := &Test{
- Name: "TEST",
- }
- Equal(t, s.unexposed.A, "")
- errs := validate.Struct(s)
- Equal(t, errs, nil)
- }
- func TestBadParams(t *testing.T) {
- validate := New()
- i := 1
- errs := validate.Var(i, "-")
- Equal(t, errs, nil)
- PanicMatches(t, func() { _ = validate.Var(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax")
- PanicMatches(t, func() { _ = validate.Var(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax")
- var ui uint = 1
- PanicMatches(t, func() { _ = validate.Var(ui, "len=a") }, "strconv.ParseUint: parsing \"a\": invalid syntax")
- f := 1.23
- PanicMatches(t, func() { _ = validate.Var(f, "len=a") }, "strconv.ParseFloat: parsing \"a\": invalid syntax")
- }
- func TestLength(t *testing.T) {
- validate := New()
- i := true
- PanicMatches(t, func() { _ = validate.Var(i, "len") }, "Bad field type bool")
- }
- func TestIsGt(t *testing.T) {
- validate := New()
- myMap := map[string]string{}
- errs := validate.Var(myMap, "gt=0")
- NotEqual(t, errs, nil)
- f := 1.23
- errs = validate.Var(f, "gt=5")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gt")
- var ui uint = 5
- errs = validate.Var(ui, "gt=10")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gt")
- i := true
- PanicMatches(t, func() { _ = validate.Var(i, "gt") }, "Bad field type bool")
- tm := time.Now().UTC()
- tm = tm.Add(time.Hour * 24)
- errs = validate.Var(tm, "gt")
- Equal(t, errs, nil)
- t2 := time.Now().UTC().Add(-time.Hour)
- errs = validate.Var(t2, "gt")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gt")
- type Test struct {
- Now *time.Time `validate:"gt"`
- }
- s := &Test{
- Now: &tm,
- }
- errs = validate.Struct(s)
- Equal(t, errs, nil)
- s = &Test{
- Now: &t2,
- }
- errs = validate.Struct(s)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "gt")
- }
- func TestIsGte(t *testing.T) {
- validate := New()
- i := true
- PanicMatches(t, func() { _ = validate.Var(i, "gte") }, "Bad field type bool")
- t1 := time.Now().UTC()
- t1 = t1.Add(time.Hour * 24)
- errs := validate.Var(t1, "gte")
- Equal(t, errs, nil)
- t2 := time.Now().UTC().Add(-time.Hour)
- errs = validate.Var(t2, "gte")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "gte")
- type Test struct {
- Now *time.Time `validate:"gte"`
- }
- s := &Test{
- Now: &t1,
- }
- errs = validate.Struct(s)
- Equal(t, errs, nil)
- s = &Test{
- Now: &t2,
- }
- errs = validate.Struct(s)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "gte")
- }
- func TestIsLt(t *testing.T) {
- validate := New()
- myMap := map[string]string{}
- errs := validate.Var(myMap, "lt=0")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "lt")
- f := 1.23
- errs = validate.Var(f, "lt=0")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "lt")
- var ui uint = 5
- errs = validate.Var(ui, "lt=0")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "lt")
- i := true
- PanicMatches(t, func() { _ = validate.Var(i, "lt") }, "Bad field type bool")
- t1 := time.Now().UTC().Add(-time.Hour)
- errs = validate.Var(t1, "lt")
- Equal(t, errs, nil)
- t2 := time.Now().UTC()
- t2 = t2.Add(time.Hour * 24)
- errs = validate.Var(t2, "lt")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "lt")
- type Test struct {
- Now *time.Time `validate:"lt"`
- }
- s := &Test{
- Now: &t1,
- }
- errs = validate.Struct(s)
- Equal(t, errs, nil)
- s = &Test{
- Now: &t2,
- }
- errs = validate.Struct(s)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "lt")
- }
- func TestIsLte(t *testing.T) {
- validate := New()
- i := true
- PanicMatches(t, func() { _ = validate.Var(i, "lte") }, "Bad field type bool")
- t1 := time.Now().UTC().Add(-time.Hour)
- errs := validate.Var(t1, "lte")
- Equal(t, errs, nil)
- t2 := time.Now().UTC()
- t2 = t2.Add(time.Hour * 24)
- errs = validate.Var(t2, "lte")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "lte")
- type Test struct {
- Now *time.Time `validate:"lte"`
- }
- s := &Test{
- Now: &t1,
- }
- errs = validate.Struct(s)
- Equal(t, errs, nil)
- s = &Test{
- Now: &t2,
- }
- errs = validate.Struct(s)
- NotEqual(t, errs, nil)
- }
- func TestUrnRFC2141(t *testing.T) {
- var tests = []struct {
- param string
- expected bool
- }{
- {"urn:a:b", true},
- {"urn:a::", true},
- {"urn:a:-", true},
- {"URN:simple:simple", true},
- {"urn:urna:simple", true},
- {"urn:burnout:nss", true},
- {"urn:burn:nss", true},
- {"urn:urnurnurn:x", true},
- {"urn:abcdefghilmnopqrstuvzabcdefghilm:x", true},
- {"URN:123:x", true},
- {"URN:abcd-:x", true},
- {"URN:abcd-abcd:x", true},
- {"urn:urnx:urn", true},
- {"urn:ciao:a:b:c", true},
- {"urn:aaa:x:y:", true},
- {"urn:ciao:-", true},
- {"urn:colon:::::nss", true},
- {"urn:ciao:@!=%2C(xyz)+a,b.*@g=$_'", true},
- {"URN:hexes:%25", true},
- {"URN:x:abc%1Dz%2F%3az", true},
- {"URN:foo:a123,456", true},
- {"urn:foo:a123,456", true},
- {"urn:FOO:a123,456", true},
- {"urn:foo:A123,456", true},
- {"urn:foo:a123%2C456", true},
- {"URN:FOO:a123%2c456", true},
- {"URN:FOO:ABC%FFabc123%2c456", true},
- {"URN:FOO:ABC%FFabc123%2C456%9A", true},
- {"urn:ietf:params:scim:schemas:core:2.0:User", true},
- {"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:meta.lastModified", true},
- {"URN:-xxx:x", false},
- {"urn::colon:nss", false},
- {"urn:abcdefghilmnopqrstuvzabcdefghilmn:specificstring", false},
- {"URN:a!?:x", false},
- {"URN:#,:x", false},
- {"urn:urn:NSS", false},
- {"urn:URN:NSS", false},
- {"urn:white space:NSS", false},
- {"urn:concat:no spaces", false},
- {"urn:a:%", false},
- {"urn:", false},
- }
- tag := "urn_rfc2141"
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, tag)
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d URN failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d URN failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != tag {
- t.Fatalf("Index: %d URN failed Error: %s", i, errs)
- }
- }
- }
- }
- i := 1
- PanicMatches(t, func() { _ = validate.Var(i, tag) }, "Bad field type int")
- }
- func TestUrl(t *testing.T) {
- var tests = []struct {
- param string
- expected bool
- }{
- {"http://foo.bar#com", true},
- {"http://foobar.com", true},
- {"https://foobar.com", true},
- {"foobar.com", false},
- {"http://foobar.coffee/", true},
- {"http://foobar.中文网/", true},
- {"http://foobar.org/", true},
- {"http://foobar.org:8080/", true},
- {"ftp://foobar.ru/", true},
- {"http://user:pass@www.foobar.com/", true},
- {"http://127.0.0.1/", true},
- {"http://duckduckgo.com/?q=%2F", true},
- {"http://localhost:3000/", true},
- {"http://foobar.com/?foo=bar#baz=qux", true},
- {"http://foobar.com?foo=bar", true},
- {"http://www.xn--froschgrn-x9a.net/", true},
- {"", false},
- {"xyz://foobar.com", true},
- {"invalid.", false},
- {".com", false},
- {"rtmp://foobar.com", true},
- {"http://www.foo_bar.com/", true},
- {"http://localhost:3000/", true},
- {"http://foobar.com/#baz", true},
- {"http://foobar.com#baz=qux", true},
- {"http://foobar.com/t$-_.+!*\\'(),", true},
- {"http://www.foobar.com/~foobar", true},
- {"http://www.-foobar.com/", true},
- {"http://www.foo---bar.com/", true},
- {"mailto:someone@example.com", true},
- {"irc://irc.server.org/channel", true},
- {"irc://#channel@network", true},
- {"/abs/test/dir", false},
- {"./rel/test/dir", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "url")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d URL failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d URL failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "url" {
- t.Fatalf("Index: %d URL failed Error: %s", i, errs)
- }
- }
- }
- }
- i := 1
- PanicMatches(t, func() { _ = validate.Var(i, "url") }, "Bad field type int")
- }
- func TestUri(t *testing.T) {
- var tests = []struct {
- param string
- expected bool
- }{
- {"http://foo.bar#com", true},
- {"http://foobar.com", true},
- {"https://foobar.com", true},
- {"foobar.com", false},
- {"http://foobar.coffee/", true},
- {"http://foobar.中文网/", true},
- {"http://foobar.org/", true},
- {"http://foobar.org:8080/", true},
- {"ftp://foobar.ru/", true},
- {"http://user:pass@www.foobar.com/", true},
- {"http://127.0.0.1/", true},
- {"http://duckduckgo.com/?q=%2F", true},
- {"http://localhost:3000/", true},
- {"http://foobar.com/?foo=bar#baz=qux", true},
- {"http://foobar.com?foo=bar", true},
- {"http://www.xn--froschgrn-x9a.net/", true},
- {"", false},
- {"xyz://foobar.com", true},
- {"invalid.", false},
- {".com", false},
- {"rtmp://foobar.com", true},
- {"http://www.foo_bar.com/", true},
- {"http://localhost:3000/", true},
- {"http://foobar.com#baz=qux", true},
- {"http://foobar.com/t$-_.+!*\\'(),", true},
- {"http://www.foobar.com/~foobar", true},
- {"http://www.-foobar.com/", true},
- {"http://www.foo---bar.com/", true},
- {"mailto:someone@example.com", true},
- {"irc://irc.server.org/channel", true},
- {"irc://#channel@network", true},
- {"/abs/test/dir", true},
- {"./rel/test/dir", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "uri")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d URI failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d URI failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "uri" {
- t.Fatalf("Index: %d URI failed Error: %s", i, errs)
- }
- }
- }
- }
- i := 1
- PanicMatches(t, func() { _ = validate.Var(i, "uri") }, "Bad field type int")
- }
- func TestOrTag(t *testing.T) {
- validate := New()
- s := "rgba(0,31,255,0.5)"
- errs := validate.Var(s, "rgb|rgba")
- Equal(t, errs, nil)
- s = "rgba(0,31,255,0.5)"
- errs = validate.Var(s, "rgb|rgba|len=18")
- Equal(t, errs, nil)
- s = "this ain't right"
- errs = validate.Var(s, "rgb|rgba")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "rgb|rgba")
- s = "this ain't right"
- errs = validate.Var(s, "rgb|rgba|len=10")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "rgb|rgba|len=10")
- s = "this is right"
- errs = validate.Var(s, "rgb|rgba|len=13")
- Equal(t, errs, nil)
- s = ""
- errs = validate.Var(s, "omitempty,rgb|rgba")
- Equal(t, errs, nil)
- s = "green"
- errs = validate.Var(s, "eq=|eq=blue,rgb|rgba") //should fail on first validation block
- NotEqual(t, errs, nil)
- ve := errs.(ValidationErrors)
- Equal(t, len(ve), 1)
- Equal(t, ve[0].Tag(), "eq=|eq=blue")
- s = "this is right, but a blank or isn't"
- PanicMatches(t, func() { _ = validate.Var(s, "rgb||len=13") }, "Invalid validation tag on field ''")
- PanicMatches(t, func() { _ = validate.Var(s, "rgb|rgbaa|len=13") }, "Undefined validation function 'rgbaa' on field ''")
- v2 := New()
- v2.RegisterTagNameFunc(func(fld reflect.StructField) string {
- name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
- if name == "-" {
- return ""
- }
- return name
- })
- type Colors struct {
- Fav string `validate:"rgb|rgba" json:"fc"`
- }
- c := Colors{Fav: "this ain't right"}
- err := v2.Struct(c)
- NotEqual(t, err, nil)
- errs = err.(ValidationErrors)
- fe := getError(errs, "Colors.fc", "Colors.Fav")
- NotEqual(t, fe, nil)
- }
- func TestHsla(t *testing.T) {
- validate := New()
- s := "hsla(360,100%,100%,1)"
- errs := validate.Var(s, "hsla")
- Equal(t, errs, nil)
- s = "hsla(360,100%,100%,0.5)"
- errs = validate.Var(s, "hsla")
- Equal(t, errs, nil)
- s = "hsla(0,0%,0%, 0)"
- errs = validate.Var(s, "hsla")
- Equal(t, errs, nil)
- s = "hsl(361,100%,50%,1)"
- errs = validate.Var(s, "hsla")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hsla")
- s = "hsl(361,100%,50%)"
- errs = validate.Var(s, "hsla")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hsla")
- s = "hsla(361,100%,50%)"
- errs = validate.Var(s, "hsla")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hsla")
- s = "hsla(360,101%,50%)"
- errs = validate.Var(s, "hsla")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hsla")
- s = "hsla(360,100%,101%)"
- errs = validate.Var(s, "hsla")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hsla")
- i := 1
- errs = validate.Var(i, "hsla")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hsla")
- }
- func TestHsl(t *testing.T) {
- validate := New()
- s := "hsl(360,100%,50%)"
- errs := validate.Var(s, "hsl")
- Equal(t, errs, nil)
- s = "hsl(0,0%,0%)"
- errs = validate.Var(s, "hsl")
- Equal(t, errs, nil)
- s = "hsl(361,100%,50%)"
- errs = validate.Var(s, "hsl")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hsl")
- s = "hsl(361,101%,50%)"
- errs = validate.Var(s, "hsl")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hsl")
- s = "hsl(361,100%,101%)"
- errs = validate.Var(s, "hsl")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hsl")
- s = "hsl(-10,100%,100%)"
- errs = validate.Var(s, "hsl")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hsl")
- i := 1
- errs = validate.Var(i, "hsl")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hsl")
- }
- func TestRgba(t *testing.T) {
- validate := New()
- s := "rgba(0,31,255,0.5)"
- errs := validate.Var(s, "rgba")
- Equal(t, errs, nil)
- s = "rgba(0,31,255,0.12)"
- errs = validate.Var(s, "rgba")
- Equal(t, errs, nil)
- s = "rgba(12%,55%,100%,0.12)"
- errs = validate.Var(s, "rgba")
- Equal(t, errs, nil)
- s = "rgba( 0, 31, 255, 0.5)"
- errs = validate.Var(s, "rgba")
- Equal(t, errs, nil)
- s = "rgba(12%,55,100%,0.12)"
- errs = validate.Var(s, "rgba")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "rgba")
- s = "rgb(0, 31, 255)"
- errs = validate.Var(s, "rgba")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "rgba")
- s = "rgb(1,349,275,0.5)"
- errs = validate.Var(s, "rgba")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "rgba")
- s = "rgb(01,31,255,0.5)"
- errs = validate.Var(s, "rgba")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "rgba")
- i := 1
- errs = validate.Var(i, "rgba")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "rgba")
- }
- func TestRgb(t *testing.T) {
- validate := New()
- s := "rgb(0,31,255)"
- errs := validate.Var(s, "rgb")
- Equal(t, errs, nil)
- s = "rgb(0, 31, 255)"
- errs = validate.Var(s, "rgb")
- Equal(t, errs, nil)
- s = "rgb(10%, 50%, 100%)"
- errs = validate.Var(s, "rgb")
- Equal(t, errs, nil)
- s = "rgb(10%, 50%, 55)"
- errs = validate.Var(s, "rgb")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "rgb")
- s = "rgb(1,349,275)"
- errs = validate.Var(s, "rgb")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "rgb")
- s = "rgb(01,31,255)"
- errs = validate.Var(s, "rgb")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "rgb")
- s = "rgba(0,31,255)"
- errs = validate.Var(s, "rgb")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "rgb")
- i := 1
- errs = validate.Var(i, "rgb")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "rgb")
- }
- func TestEmail(t *testing.T) {
- validate := New()
- s := "test@mail.com"
- errs := validate.Var(s, "email")
- Equal(t, errs, nil)
- s = "Dörte@Sörensen.example.com"
- errs = validate.Var(s, "email")
- Equal(t, errs, nil)
- s = "θσερ@εχαμπλε.ψομ"
- errs = validate.Var(s, "email")
- Equal(t, errs, nil)
- s = "юзер@екзампл.ком"
- errs = validate.Var(s, "email")
- Equal(t, errs, nil)
- s = "उपयोगकर्ता@उदाहरण.कॉम"
- errs = validate.Var(s, "email")
- Equal(t, errs, nil)
- s = "用户@例子.广告"
- errs = validate.Var(s, "email")
- Equal(t, errs, nil)
- s = "mail@domain_with_underscores.org"
- errs = validate.Var(s, "email")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "email")
- s = ""
- errs = validate.Var(s, "email")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "email")
- s = "test@email"
- errs = validate.Var(s, "email")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "email")
- s = "test@email."
- errs = validate.Var(s, "email")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "email")
- s = "@email.com"
- errs = validate.Var(s, "email")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "email")
- s = `"test test"@email.com`
- errs = validate.Var(s, "email")
- Equal(t, errs, nil)
- s = `"@email.com`
- errs = validate.Var(s, "email")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "email")
- i := true
- errs = validate.Var(i, "email")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "email")
- }
- func TestHexColor(t *testing.T) {
- validate := New()
- s := "#fff"
- errs := validate.Var(s, "hexcolor")
- Equal(t, errs, nil)
- s = "#c2c2c2"
- errs = validate.Var(s, "hexcolor")
- Equal(t, errs, nil)
- s = "fff"
- errs = validate.Var(s, "hexcolor")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hexcolor")
- s = "fffFF"
- errs = validate.Var(s, "hexcolor")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hexcolor")
- i := true
- errs = validate.Var(i, "hexcolor")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hexcolor")
- }
- func TestHexadecimal(t *testing.T) {
- validate := New()
- s := "ff0044"
- errs := validate.Var(s, "hexadecimal")
- Equal(t, errs, nil)
- s = "abcdefg"
- errs = validate.Var(s, "hexadecimal")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hexadecimal")
- i := true
- errs = validate.Var(i, "hexadecimal")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "hexadecimal")
- }
- func TestNumber(t *testing.T) {
- validate := New()
- s := "1"
- errs := validate.Var(s, "number")
- Equal(t, errs, nil)
- s = "+1"
- errs = validate.Var(s, "number")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "number")
- s = "-1"
- errs = validate.Var(s, "number")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "number")
- s = "1.12"
- errs = validate.Var(s, "number")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "number")
- s = "+1.12"
- errs = validate.Var(s, "number")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "number")
- s = "-1.12"
- errs = validate.Var(s, "number")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "number")
- s = "1."
- errs = validate.Var(s, "number")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "number")
- s = "1.o"
- errs = validate.Var(s, "number")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "number")
- i := 1
- errs = validate.Var(i, "number")
- Equal(t, errs, nil)
- }
- func TestNumeric(t *testing.T) {
- validate := New()
- s := "1"
- errs := validate.Var(s, "numeric")
- Equal(t, errs, nil)
- s = "+1"
- errs = validate.Var(s, "numeric")
- Equal(t, errs, nil)
- s = "-1"
- errs = validate.Var(s, "numeric")
- Equal(t, errs, nil)
- s = "1.12"
- errs = validate.Var(s, "numeric")
- Equal(t, errs, nil)
- s = "+1.12"
- errs = validate.Var(s, "numeric")
- Equal(t, errs, nil)
- s = "-1.12"
- errs = validate.Var(s, "numeric")
- Equal(t, errs, nil)
- s = "1."
- errs = validate.Var(s, "numeric")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "numeric")
- s = "1.o"
- errs = validate.Var(s, "numeric")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "numeric")
- i := 1
- errs = validate.Var(i, "numeric")
- Equal(t, errs, nil)
- }
- func TestAlphaNumeric(t *testing.T) {
- validate := New()
- s := "abcd123"
- errs := validate.Var(s, "alphanum")
- Equal(t, errs, nil)
- s = "abc!23"
- errs = validate.Var(s, "alphanum")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "alphanum")
- errs = validate.Var(1, "alphanum")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "alphanum")
- }
- func TestAlpha(t *testing.T) {
- validate := New()
- s := "abcd"
- errs := validate.Var(s, "alpha")
- Equal(t, errs, nil)
- s = "abc®"
- errs = validate.Var(s, "alpha")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "alpha")
- s = "abc÷"
- errs = validate.Var(s, "alpha")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "alpha")
- s = "abc1"
- errs = validate.Var(s, "alpha")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "alpha")
- s = "this is a test string"
- errs = validate.Var(s, "alpha")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "alpha")
- errs = validate.Var(1, "alpha")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "", "", "alpha")
- }
- func TestStructStringValidation(t *testing.T) {
- validate := New()
- tSuccess := &TestString{
- Required: "Required",
- Len: "length==10",
- Min: "min=1",
- Max: "1234567890",
- MinMax: "12345",
- Lt: "012345678",
- Lte: "0123456789",
- Gt: "01234567890",
- Gte: "0123456789",
- OmitEmpty: "",
- Sub: &SubTest{
- Test: "1",
- },
- SubIgnore: &SubTest{
- Test: "",
- },
- Anonymous: struct {
- A string `validate:"required"`
- }{
- A: "1",
- },
- Iface: &Impl{
- F: "123",
- },
- }
- errs := validate.Struct(tSuccess)
- Equal(t, errs, nil)
- tFail := &TestString{
- Required: "",
- Len: "",
- Min: "",
- Max: "12345678901",
- MinMax: "",
- Lt: "0123456789",
- Lte: "01234567890",
- Gt: "1",
- Gte: "1",
- OmitEmpty: "12345678901",
- Sub: &SubTest{
- Test: "",
- },
- Anonymous: struct {
- A string `validate:"required"`
- }{
- A: "",
- },
- Iface: &Impl{
- F: "12",
- },
- }
- errs = validate.Struct(tFail)
- // Assert Top Level
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 13)
- // Assert Fields
- AssertError(t, errs, "TestString.Required", "TestString.Required", "Required", "Required", "required")
- AssertError(t, errs, "TestString.Len", "TestString.Len", "Len", "Len", "len")
- AssertError(t, errs, "TestString.Min", "TestString.Min", "Min", "Min", "min")
- AssertError(t, errs, "TestString.Max", "TestString.Max", "Max", "Max", "max")
- AssertError(t, errs, "TestString.MinMax", "TestString.MinMax", "MinMax", "MinMax", "min")
- AssertError(t, errs, "TestString.Lt", "TestString.Lt", "Lt", "Lt", "lt")
- AssertError(t, errs, "TestString.Lte", "TestString.Lte", "Lte", "Lte", "lte")
- AssertError(t, errs, "TestString.Gt", "TestString.Gt", "Gt", "Gt", "gt")
- AssertError(t, errs, "TestString.Gte", "TestString.Gte", "Gte", "Gte", "gte")
- AssertError(t, errs, "TestString.OmitEmpty", "TestString.OmitEmpty", "OmitEmpty", "OmitEmpty", "max")
- // Nested Struct Field Errs
- AssertError(t, errs, "TestString.Anonymous.A", "TestString.Anonymous.A", "A", "A", "required")
- AssertError(t, errs, "TestString.Sub.Test", "TestString.Sub.Test", "Test", "Test", "required")
- AssertError(t, errs, "TestString.Iface.F", "TestString.Iface.F", "F", "F", "len")
- }
- func TestStructInt32Validation(t *testing.T) {
- type TestInt32 struct {
- Required int `validate:"required"`
- Len int `validate:"len=10"`
- Min int `validate:"min=1"`
- Max int `validate:"max=10"`
- MinMax int `validate:"min=1,max=10"`
- Lt int `validate:"lt=10"`
- Lte int `validate:"lte=10"`
- Gt int `validate:"gt=10"`
- Gte int `validate:"gte=10"`
- OmitEmpty int `validate:"omitempty,min=1,max=10"`
- }
- tSuccess := &TestInt32{
- Required: 1,
- Len: 10,
- Min: 1,
- Max: 10,
- MinMax: 5,
- Lt: 9,
- Lte: 10,
- Gt: 11,
- Gte: 10,
- OmitEmpty: 0,
- }
- validate := New()
- errs := validate.Struct(tSuccess)
- Equal(t, errs, nil)
- tFail := &TestInt32{
- Required: 0,
- Len: 11,
- Min: -1,
- Max: 11,
- MinMax: -1,
- Lt: 10,
- Lte: 11,
- Gt: 10,
- Gte: 9,
- OmitEmpty: 11,
- }
- errs = validate.Struct(tFail)
- // Assert Top Level
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 10)
- // Assert Fields
- AssertError(t, errs, "TestInt32.Required", "TestInt32.Required", "Required", "Required", "required")
- AssertError(t, errs, "TestInt32.Len", "TestInt32.Len", "Len", "Len", "len")
- AssertError(t, errs, "TestInt32.Min", "TestInt32.Min", "Min", "Min", "min")
- AssertError(t, errs, "TestInt32.Max", "TestInt32.Max", "Max", "Max", "max")
- AssertError(t, errs, "TestInt32.MinMax", "TestInt32.MinMax", "MinMax", "MinMax", "min")
- AssertError(t, errs, "TestInt32.Lt", "TestInt32.Lt", "Lt", "Lt", "lt")
- AssertError(t, errs, "TestInt32.Lte", "TestInt32.Lte", "Lte", "Lte", "lte")
- AssertError(t, errs, "TestInt32.Gt", "TestInt32.Gt", "Gt", "Gt", "gt")
- AssertError(t, errs, "TestInt32.Gte", "TestInt32.Gte", "Gte", "Gte", "gte")
- AssertError(t, errs, "TestInt32.OmitEmpty", "TestInt32.OmitEmpty", "OmitEmpty", "OmitEmpty", "max")
- }
- func TestStructUint64Validation(t *testing.T) {
- validate := New()
- tSuccess := &TestUint64{
- Required: 1,
- Len: 10,
- Min: 1,
- Max: 10,
- MinMax: 5,
- OmitEmpty: 0,
- }
- errs := validate.Struct(tSuccess)
- Equal(t, errs, nil)
- tFail := &TestUint64{
- Required: 0,
- Len: 11,
- Min: 0,
- Max: 11,
- MinMax: 0,
- OmitEmpty: 11,
- }
- errs = validate.Struct(tFail)
- // Assert Top Level
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 6)
- // Assert Fields
- AssertError(t, errs, "TestUint64.Required", "TestUint64.Required", "Required", "Required", "required")
- AssertError(t, errs, "TestUint64.Len", "TestUint64.Len", "Len", "Len", "len")
- AssertError(t, errs, "TestUint64.Min", "TestUint64.Min", "Min", "Min", "min")
- AssertError(t, errs, "TestUint64.Max", "TestUint64.Max", "Max", "Max", "max")
- AssertError(t, errs, "TestUint64.MinMax", "TestUint64.MinMax", "MinMax", "MinMax", "min")
- AssertError(t, errs, "TestUint64.OmitEmpty", "TestUint64.OmitEmpty", "OmitEmpty", "OmitEmpty", "max")
- }
- func TestStructFloat64Validation(t *testing.T) {
- validate := New()
- tSuccess := &TestFloat64{
- Required: 1,
- Len: 10,
- Min: 1,
- Max: 10,
- MinMax: 5,
- OmitEmpty: 0,
- }
- errs := validate.Struct(tSuccess)
- Equal(t, errs, nil)
- tFail := &TestFloat64{
- Required: 0,
- Len: 11,
- Min: 0,
- Max: 11,
- MinMax: 0,
- OmitEmpty: 11,
- }
- errs = validate.Struct(tFail)
- // Assert Top Level
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 6)
- // Assert Fields
- AssertError(t, errs, "TestFloat64.Required", "TestFloat64.Required", "Required", "Required", "required")
- AssertError(t, errs, "TestFloat64.Len", "TestFloat64.Len", "Len", "Len", "len")
- AssertError(t, errs, "TestFloat64.Min", "TestFloat64.Min", "Min", "Min", "min")
- AssertError(t, errs, "TestFloat64.Max", "TestFloat64.Max", "Max", "Max", "max")
- AssertError(t, errs, "TestFloat64.MinMax", "TestFloat64.MinMax", "MinMax", "MinMax", "min")
- AssertError(t, errs, "TestFloat64.OmitEmpty", "TestFloat64.OmitEmpty", "OmitEmpty", "OmitEmpty", "max")
- }
- func TestStructSliceValidation(t *testing.T) {
- validate := New()
- tSuccess := &TestSlice{
- Required: []int{1},
- Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
- Min: []int{1, 2},
- Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
- MinMax: []int{1, 2, 3, 4, 5},
- OmitEmpty: nil,
- }
- errs := validate.Struct(tSuccess)
- Equal(t, errs, nil)
- tFail := &TestSlice{
- Required: nil,
- Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
- Min: []int{},
- Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
- MinMax: []int{},
- OmitEmpty: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
- }
- errs = validate.Struct(tFail)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 6)
- // Assert Field Errors
- AssertError(t, errs, "TestSlice.Required", "TestSlice.Required", "Required", "Required", "required")
- AssertError(t, errs, "TestSlice.Len", "TestSlice.Len", "Len", "Len", "len")
- AssertError(t, errs, "TestSlice.Min", "TestSlice.Min", "Min", "Min", "min")
- AssertError(t, errs, "TestSlice.Max", "TestSlice.Max", "Max", "Max", "max")
- AssertError(t, errs, "TestSlice.MinMax", "TestSlice.MinMax", "MinMax", "MinMax", "min")
- AssertError(t, errs, "TestSlice.OmitEmpty", "TestSlice.OmitEmpty", "OmitEmpty", "OmitEmpty", "max")
- fe := getError(errs, "TestSlice.Len", "TestSlice.Len")
- NotEqual(t, fe, nil)
- Equal(t, fe.Field(), "Len")
- Equal(t, fe.StructField(), "Len")
- Equal(t, fe.Namespace(), "TestSlice.Len")
- Equal(t, fe.StructNamespace(), "TestSlice.Len")
- Equal(t, fe.Tag(), "len")
- Equal(t, fe.ActualTag(), "len")
- Equal(t, fe.Param(), "10")
- Equal(t, fe.Kind(), reflect.Slice)
- Equal(t, fe.Type(), reflect.TypeOf([]int{}))
- _, ok := fe.Value().([]int)
- Equal(t, ok, true)
- }
- func TestInvalidStruct(t *testing.T) {
- validate := New()
- s := &SubTest{
- Test: "1",
- }
- err := validate.Struct(s.Test)
- NotEqual(t, err, nil)
- Equal(t, err.Error(), "validator: (nil string)")
- err = validate.Struct(nil)
- NotEqual(t, err, nil)
- Equal(t, err.Error(), "validator: (nil)")
- err = validate.StructPartial(nil, "SubTest.Test")
- NotEqual(t, err, nil)
- Equal(t, err.Error(), "validator: (nil)")
- err = validate.StructExcept(nil, "SubTest.Test")
- NotEqual(t, err, nil)
- Equal(t, err.Error(), "validator: (nil)")
- }
- func TestInvalidValidatorFunction(t *testing.T) {
- validate := New()
- s := &SubTest{
- Test: "1",
- }
- PanicMatches(t, func() { _ = validate.Var(s.Test, "zzxxBadFunction") }, "Undefined validation function 'zzxxBadFunction' on field ''")
- }
- func TestCustomFieldName(t *testing.T) {
- validate := New()
- validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
- name := strings.SplitN(fld.Tag.Get("schema"), ",", 2)[0]
- if name == "-" {
- return ""
- }
- return name
- })
- type A struct {
- B string `schema:"b" validate:"required"`
- C string `schema:"c" validate:"required"`
- D []bool `schema:"d" validate:"required"`
- E string `schema:"-" validate:"required"`
- }
- a := &A{}
- err := validate.Struct(a)
- NotEqual(t, err, nil)
- errs := err.(ValidationErrors)
- Equal(t, len(errs), 4)
- Equal(t, getError(errs, "A.b", "A.B").Field(), "b")
- Equal(t, getError(errs, "A.c", "A.C").Field(), "c")
- Equal(t, getError(errs, "A.d", "A.D").Field(), "d")
- Equal(t, getError(errs, "A.E", "A.E").Field(), "E")
- v2 := New()
- err = v2.Struct(a)
- NotEqual(t, err, nil)
- errs = err.(ValidationErrors)
- Equal(t, len(errs), 4)
- Equal(t, getError(errs, "A.B", "A.B").Field(), "B")
- Equal(t, getError(errs, "A.C", "A.C").Field(), "C")
- Equal(t, getError(errs, "A.D", "A.D").Field(), "D")
- Equal(t, getError(errs, "A.E", "A.E").Field(), "E")
- }
- func TestMutipleRecursiveExtractStructCache(t *testing.T) {
- validate := New()
- type Recursive struct {
- Field *string `validate:"required,len=5,ne=string"`
- }
- var test Recursive
- current := reflect.ValueOf(test)
- name := "Recursive"
- proceed := make(chan struct{})
- sc := validate.extractStructCache(current, name)
- ptr := fmt.Sprintf("%p", sc)
- for i := 0; i < 100; i++ {
- go func() {
- <-proceed
- sc := validate.extractStructCache(current, name)
- Equal(t, ptr, fmt.Sprintf("%p", sc))
- }()
- }
- close(proceed)
- }
- // Thanks @robbrockbank, see https://github.com/go-playground/validator/issues/249
- func TestPointerAndOmitEmpty(t *testing.T) {
- validate := New()
- type Test struct {
- MyInt *int `validate:"omitempty,gte=2,lte=255"`
- }
- val1 := 0
- val2 := 256
- t1 := Test{MyInt: &val1} // This should fail validation on gte because value is 0
- t2 := Test{MyInt: &val2} // This should fail validate on lte because value is 256
- t3 := Test{MyInt: nil} // This should succeed validation because pointer is nil
- errs := validate.Struct(t1)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.MyInt", "Test.MyInt", "MyInt", "MyInt", "gte")
- errs = validate.Struct(t2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.MyInt", "Test.MyInt", "MyInt", "MyInt", "lte")
- errs = validate.Struct(t3)
- Equal(t, errs, nil)
- type TestIface struct {
- MyInt interface{} `validate:"omitempty,gte=2,lte=255"`
- }
- ti1 := TestIface{MyInt: &val1} // This should fail validation on gte because value is 0
- ti2 := TestIface{MyInt: &val2} // This should fail validate on lte because value is 256
- ti3 := TestIface{MyInt: nil} // This should succeed validation because pointer is nil
- errs = validate.Struct(ti1)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestIface.MyInt", "TestIface.MyInt", "MyInt", "MyInt", "gte")
- errs = validate.Struct(ti2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestIface.MyInt", "TestIface.MyInt", "MyInt", "MyInt", "lte")
- errs = validate.Struct(ti3)
- Equal(t, errs, nil)
- }
- func TestRequired(t *testing.T) {
- validate := New()
- validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
- name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
- if name == "-" {
- return ""
- }
- return name
- })
- type Test struct {
- Value interface{} `validate:"required"`
- }
- var test Test
- err := validate.Struct(test)
- NotEqual(t, err, nil)
- AssertError(t, err.(ValidationErrors), "Test.Value", "Test.Value", "Value", "Value", "required")
- }
- func TestTranslations(t *testing.T) {
- en := en.New()
- uni := ut.New(en, en, fr.New())
- trans, _ := uni.GetTranslator("en")
- fr, _ := uni.GetTranslator("fr")
- validate := New()
- err := validate.RegisterTranslation("required", trans,
- func(ut ut.Translator) (err error) {
- // using this stype because multiple translation may have to be added for the full translation
- if err = ut.Add("required", "{0} is a required field", false); err != nil {
- return
- }
- return
- }, func(ut ut.Translator, fe FieldError) string {
- t, err := ut.T(fe.Tag(), fe.Field())
- if err != nil {
- fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError))
- return fe.(*fieldError).Error()
- }
- return t
- })
- Equal(t, err, nil)
- err = validate.RegisterTranslation("required", fr,
- func(ut ut.Translator) (err error) {
- // using this stype because multiple translation may have to be added for the full translation
- if err = ut.Add("required", "{0} est un champ obligatoire", false); err != nil {
- return
- }
- return
- }, func(ut ut.Translator, fe FieldError) string {
- t, transErr := ut.T(fe.Tag(), fe.Field())
- if transErr != nil {
- fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError))
- return fe.(*fieldError).Error()
- }
- return t
- })
- Equal(t, err, nil)
- type Test struct {
- Value interface{} `validate:"required"`
- }
- var test Test
- err = validate.Struct(test)
- NotEqual(t, err, nil)
- errs := err.(ValidationErrors)
- Equal(t, len(errs), 1)
- fe := errs[0]
- Equal(t, fe.Tag(), "required")
- Equal(t, fe.Namespace(), "Test.Value")
- Equal(t, fe.Translate(trans), fmt.Sprintf("%s is a required field", fe.Field()))
- Equal(t, fe.Translate(fr), fmt.Sprintf("%s est un champ obligatoire", fe.Field()))
- nl := nl.New()
- uni2 := ut.New(nl, nl)
- trans2, _ := uni2.GetTranslator("nl")
- Equal(t, fe.Translate(trans2), "Key: 'Test.Value' Error:Field validation for 'Value' failed on the 'required' tag")
- terrs := errs.Translate(trans)
- Equal(t, len(terrs), 1)
- v, ok := terrs["Test.Value"]
- Equal(t, ok, true)
- Equal(t, v, fmt.Sprintf("%s is a required field", fe.Field()))
- terrs = errs.Translate(fr)
- Equal(t, len(terrs), 1)
- v, ok = terrs["Test.Value"]
- Equal(t, ok, true)
- Equal(t, v, fmt.Sprintf("%s est un champ obligatoire", fe.Field()))
- type Test2 struct {
- Value string `validate:"gt=1"`
- }
- var t2 Test2
- err = validate.Struct(t2)
- NotEqual(t, err, nil)
- errs = err.(ValidationErrors)
- Equal(t, len(errs), 1)
- fe = errs[0]
- Equal(t, fe.Tag(), "gt")
- Equal(t, fe.Namespace(), "Test2.Value")
- Equal(t, fe.Translate(trans), "Key: 'Test2.Value' Error:Field validation for 'Value' failed on the 'gt' tag")
- }
- func TestTranslationErrors(t *testing.T) {
- en := en.New()
- uni := ut.New(en, en, fr.New())
- trans, _ := uni.GetTranslator("en")
- err := trans.Add("required", "{0} is a required field", false) // using translator outside of validator also
- Equal(t, err, nil)
- validate := New()
- err = validate.RegisterTranslation("required", trans,
- func(ut ut.Translator) (err error) {
- // using this stype because multiple translation may have to be added for the full translation
- if err = ut.Add("required", "{0} is a required field", false); err != nil {
- return
- }
- return
- }, func(ut ut.Translator, fe FieldError) string {
- t, err := ut.T(fe.Tag(), fe.Field())
- if err != nil {
- fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError))
- return fe.(*fieldError).Error()
- }
- return t
- })
- NotEqual(t, err, nil)
- Equal(t, err.Error(), "error: conflicting key 'required' rule 'Unknown' with text '{0} is a required field' for locale 'en', value being ignored")
- }
- func TestStructFiltered(t *testing.T) {
- p1 := func(ns []byte) bool {
- if bytes.HasSuffix(ns, []byte("NoTag")) || bytes.HasSuffix(ns, []byte("Required")) {
- return false
- }
- return true
- }
- p2 := func(ns []byte) bool {
- if bytes.HasSuffix(ns, []byte("SubSlice[0].Test")) ||
- bytes.HasSuffix(ns, []byte("SubSlice[0]")) ||
- bytes.HasSuffix(ns, []byte("SubSlice")) ||
- bytes.HasSuffix(ns, []byte("Sub")) ||
- bytes.HasSuffix(ns, []byte("SubIgnore")) ||
- bytes.HasSuffix(ns, []byte("Anonymous")) ||
- bytes.HasSuffix(ns, []byte("Anonymous.A")) {
- return false
- }
- return true
- }
- p3 := func(ns []byte) bool {
- return !bytes.HasSuffix(ns, []byte("SubTest.Test"))
- }
- // p4 := []string{
- // "A",
- // }
- tPartial := &TestPartial{
- NoTag: "NoTag",
- Required: "Required",
- SubSlice: []*SubTest{
- {
- Test: "Required",
- },
- {
- Test: "Required",
- },
- },
- Sub: &SubTest{
- Test: "1",
- },
- SubIgnore: &SubTest{
- Test: "",
- },
- Anonymous: struct {
- A string `validate:"required"`
- ASubSlice []*SubTest `validate:"required,dive"`
- SubAnonStruct []struct {
- Test string `validate:"required"`
- OtherTest string `validate:"required"`
- } `validate:"required,dive"`
- }{
- A: "1",
- ASubSlice: []*SubTest{
- {
- Test: "Required",
- },
- {
- Test: "Required",
- },
- },
- SubAnonStruct: []struct {
- Test string `validate:"required"`
- OtherTest string `validate:"required"`
- }{
- {"Required", "RequiredOther"},
- {"Required", "RequiredOther"},
- },
- },
- }
- validate := New()
- // the following should all return no errors as everything is valid in
- // the default state
- errs := validate.StructFilteredCtx(context.Background(), tPartial, p1)
- Equal(t, errs, nil)
- errs = validate.StructFiltered(tPartial, p2)
- Equal(t, errs, nil)
- // this isn't really a robust test, but is ment to illustrate the ANON CASE below
- errs = validate.StructFiltered(tPartial.SubSlice[0], p3)
- Equal(t, errs, nil)
- // mod tParial for required feild and re-test making sure invalid fields are NOT required:
- tPartial.Required = ""
- // inversion and retesting Partial to generate failures:
- errs = validate.StructFiltered(tPartial, p1)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.Required", "TestPartial.Required", "Required", "Required", "required")
- // reset Required field, and set nested struct
- tPartial.Required = "Required"
- tPartial.Anonymous.A = ""
- // will pass as unset feilds is not going to be tested
- errs = validate.StructFiltered(tPartial, p1)
- Equal(t, errs, nil)
- // will fail as unset feild is tested
- errs = validate.StructFiltered(tPartial, p2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.Anonymous.A", "TestPartial.Anonymous.A", "A", "A", "required")
- // reset nested struct and unset struct in slice
- tPartial.Anonymous.A = "Required"
- tPartial.SubSlice[0].Test = ""
- // these will pass as unset item is NOT tested
- errs = validate.StructFiltered(tPartial, p1)
- Equal(t, errs, nil)
- errs = validate.StructFiltered(tPartial, p2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required")
- Equal(t, len(errs.(ValidationErrors)), 1)
- // Unset second slice member concurrently to test dive behavior:
- tPartial.SubSlice[1].Test = ""
- errs = validate.StructFiltered(tPartial, p1)
- Equal(t, errs, nil)
- errs = validate.StructFiltered(tPartial, p2)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required")
- // reset struct in slice, and unset struct in slice in unset posistion
- tPartial.SubSlice[0].Test = "Required"
- // these will pass as the unset item is NOT tested
- errs = validate.StructFiltered(tPartial, p1)
- Equal(t, errs, nil)
- errs = validate.StructFiltered(tPartial, p2)
- Equal(t, errs, nil)
- tPartial.SubSlice[1].Test = "Required"
- tPartial.Anonymous.SubAnonStruct[0].Test = ""
- // these will pass as the unset item is NOT tested
- errs = validate.StructFiltered(tPartial, p1)
- Equal(t, errs, nil)
- errs = validate.StructFiltered(tPartial, p2)
- Equal(t, errs, nil)
- dt := time.Now()
- err := validate.StructFiltered(&dt, func(ns []byte) bool { return true })
- NotEqual(t, err, nil)
- Equal(t, err.Error(), "validator: (nil *time.Time)")
- }
- func TestRequiredPtr(t *testing.T) {
- type Test struct {
- Bool *bool `validate:"required"`
- }
- validate := New()
- f := false
- test := Test{
- Bool: &f,
- }
- err := validate.Struct(test)
- Equal(t, err, nil)
- tr := true
- test.Bool = &tr
- err = validate.Struct(test)
- Equal(t, err, nil)
- test.Bool = nil
- err = validate.Struct(test)
- NotEqual(t, err, nil)
- errs, ok := err.(ValidationErrors)
- Equal(t, ok, true)
- Equal(t, len(errs), 1)
- AssertError(t, errs, "Test.Bool", "Test.Bool", "Bool", "Bool", "required")
- type Test2 struct {
- Bool bool `validate:"required"`
- }
- var test2 Test2
- err = validate.Struct(test2)
- NotEqual(t, err, nil)
- errs, ok = err.(ValidationErrors)
- Equal(t, ok, true)
- Equal(t, len(errs), 1)
- AssertError(t, errs, "Test2.Bool", "Test2.Bool", "Bool", "Bool", "required")
- test2.Bool = true
- err = validate.Struct(test2)
- Equal(t, err, nil)
- type Test3 struct {
- Arr []string `validate:"required"`
- }
- var test3 Test3
- err = validate.Struct(test3)
- NotEqual(t, err, nil)
- errs, ok = err.(ValidationErrors)
- Equal(t, ok, true)
- Equal(t, len(errs), 1)
- AssertError(t, errs, "Test3.Arr", "Test3.Arr", "Arr", "Arr", "required")
- test3.Arr = make([]string, 0)
- err = validate.Struct(test3)
- Equal(t, err, nil)
- type Test4 struct {
- Arr *[]string `validate:"required"` // I know I know pointer to array, just making sure validation works as expected...
- }
- var test4 Test4
- err = validate.Struct(test4)
- NotEqual(t, err, nil)
- errs, ok = err.(ValidationErrors)
- Equal(t, ok, true)
- Equal(t, len(errs), 1)
- AssertError(t, errs, "Test4.Arr", "Test4.Arr", "Arr", "Arr", "required")
- arr := make([]string, 0)
- test4.Arr = &arr
- err = validate.Struct(test4)
- Equal(t, err, nil)
- }
- func TestAlphaUnicodeValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"abc", true},
- {"this is a test string", false},
- {"这是一个测试字符串", true},
- {"123", false},
- {"<>@;.-=", false},
- {"ひらがな・カタカナ、.漢字", false},
- {"あいうえおfoobar", true},
- {"test@example.com", false},
- {"1234abcDE", false},
- {"カタカナ", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "alphaunicode")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d Alpha Unicode failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d Alpha Unicode failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "alphaunicode" {
- t.Fatalf("Index: %d Alpha Unicode failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestAlphanumericUnicodeValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"abc", true},
- {"this is a test string", false},
- {"这是一个测试字符串", true},
- {"\u0031\u0032\u0033", true}, // unicode 5
- {"123", true},
- {"<>@;.-=", false},
- {"ひらがな・カタカナ、.漢字", false},
- {"あいうえおfoobar", true},
- {"test@example.com", false},
- {"1234abcDE", true},
- {"カタカナ", true},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "alphanumunicode")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d Alphanum Unicode failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d Alphanum Unicode failed Error: %s", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "alphanumunicode" {
- t.Fatalf("Index: %d Alphanum Unicode failed Error: %s", i, errs)
- }
- }
- }
- }
- }
- func TestArrayStructNamespace(t *testing.T) {
- validate := New()
- validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
- name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
- if name == "-" {
- return ""
- }
- return name
- })
- type child struct {
- Name string `json:"name" validate:"required"`
- }
- var input struct {
- Children []child `json:"children" validate:"required,gt=0,dive"`
- }
- input.Children = []child{{"ok"}, {""}}
- errs := validate.Struct(input)
- NotEqual(t, errs, nil)
- ve := errs.(ValidationErrors)
- Equal(t, len(ve), 1)
- AssertError(t, errs, "children[1].name", "Children[1].Name", "name", "Name", "required")
- }
- func TestMapStructNamespace(t *testing.T) {
- validate := New()
- validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
- name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
- if name == "-" {
- return ""
- }
- return name
- })
- type child struct {
- Name string `json:"name" validate:"required"`
- }
- var input struct {
- Children map[int]child `json:"children" validate:"required,gt=0,dive"`
- }
- input.Children = map[int]child{
- 0: {Name: "ok"},
- 1: {Name: ""},
- }
- errs := validate.Struct(input)
- NotEqual(t, errs, nil)
- ve := errs.(ValidationErrors)
- Equal(t, len(ve), 1)
- AssertError(t, errs, "children[1].name", "Children[1].Name", "name", "Name", "required")
- }
- func TestFieldLevelName(t *testing.T) {
- type Test struct {
- String string `validate:"custom1" json:"json1"`
- Array []string `validate:"dive,custom2" json:"json2"`
- Map map[string]string `validate:"dive,custom3" json:"json3"`
- Array2 []string `validate:"custom4" json:"json4"`
- Map2 map[string]string `validate:"custom5" json:"json5"`
- }
- var res1, res2, res3, res4, res5, alt1, alt2, alt3, alt4, alt5 string
- validate := New()
- validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
- name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
- if name == "-" {
- return ""
- }
- return name
- })
- err := validate.RegisterValidation("custom1", func(fl FieldLevel) bool {
- res1 = fl.FieldName()
- alt1 = fl.StructFieldName()
- return true
- })
- Equal(t, err, nil)
- err = validate.RegisterValidation("custom2", func(fl FieldLevel) bool {
- res2 = fl.FieldName()
- alt2 = fl.StructFieldName()
- return true
- })
- Equal(t, err, nil)
- err = validate.RegisterValidation("custom3", func(fl FieldLevel) bool {
- res3 = fl.FieldName()
- alt3 = fl.StructFieldName()
- return true
- })
- Equal(t, err, nil)
- err = validate.RegisterValidation("custom4", func(fl FieldLevel) bool {
- res4 = fl.FieldName()
- alt4 = fl.StructFieldName()
- return true
- })
- Equal(t, err, nil)
- err = validate.RegisterValidation("custom5", func(fl FieldLevel) bool {
- res5 = fl.FieldName()
- alt5 = fl.StructFieldName()
- return true
- })
- Equal(t, err, nil)
- test := Test{
- String: "test",
- Array: []string{"1"},
- Map: map[string]string{"test": "test"},
- }
- errs := validate.Struct(test)
- Equal(t, errs, nil)
- Equal(t, res1, "json1")
- Equal(t, alt1, "String")
- Equal(t, res2, "json2[0]")
- Equal(t, alt2, "Array[0]")
- Equal(t, res3, "json3[test]")
- Equal(t, alt3, "Map[test]")
- Equal(t, res4, "json4")
- Equal(t, alt4, "Array2")
- Equal(t, res5, "json5")
- Equal(t, alt5, "Map2")
- }
- func TestValidateStructRegisterCtx(t *testing.T) {
- var ctxVal string
- fnCtx := func(ctx context.Context, fl FieldLevel) bool {
- ctxVal = ctx.Value(&ctxVal).(string)
- return true
- }
- var ctxSlVal string
- slFn := func(ctx context.Context, sl StructLevel) {
- ctxSlVal = ctx.Value(&ctxSlVal).(string)
- }
- type Test struct {
- Field string `validate:"val"`
- }
- var tst Test
- validate := New()
- err := validate.RegisterValidationCtx("val", fnCtx)
- Equal(t, err, nil)
- validate.RegisterStructValidationCtx(slFn, Test{})
- ctx := context.WithValue(context.Background(), &ctxVal, "testval")
- ctx = context.WithValue(ctx, &ctxSlVal, "slVal")
- errs := validate.StructCtx(ctx, tst)
- Equal(t, errs, nil)
- Equal(t, ctxVal, "testval")
- Equal(t, ctxSlVal, "slVal")
- }
- func TestHostnameRFC952Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"test.example.com", true},
- {"example.com", true},
- {"example24.com", true},
- {"test.example24.com", true},
- {"test24.example24.com", true},
- {"example", true},
- {"EXAMPLE", true},
- {"1.foo.com", false},
- {"test.example.com.", false},
- {"example.com.", false},
- {"example24.com.", false},
- {"test.example24.com.", false},
- {"test24.example24.com.", false},
- {"example.", false},
- {"192.168.0.1", false},
- {"email@example.com", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652", false},
- {"2001:cdba:0:0:0:0:3257:9652", false},
- {"2001:cdba::3257:9652", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "hostname")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "hostname" {
- t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
- }
- }
- }
- }
- }
- func TestHostnameRFC1123Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"test.example.com", true},
- {"example.com", true},
- {"example24.com", true},
- {"test.example24.com", true},
- {"test24.example24.com", true},
- {"example", true},
- {"1.foo.com", true},
- {"test.example.com.", false},
- {"example.com.", false},
- {"example24.com.", false},
- {"test.example24.com.", false},
- {"test24.example24.com.", false},
- {"example.", false},
- {"192.168.0.1", true},
- {"email@example.com", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652", false},
- {"2001:cdba:0:0:0:0:3257:9652", false},
- {"2001:cdba::3257:9652", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "hostname_rfc1123")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "hostname_rfc1123" {
- t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
- }
- }
- }
- }
- }
- func TestHostnameRFC1123AliasValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"test.example.com", true},
- {"example.com", true},
- {"example24.com", true},
- {"test.example24.com", true},
- {"test24.example24.com", true},
- {"example", true},
- {"1.foo.com", true},
- {"test.example.com.", false},
- {"example.com.", false},
- {"example24.com.", false},
- {"test.example24.com.", false},
- {"test24.example24.com.", false},
- {"example.", false},
- {"192.168.0.1", true},
- {"email@example.com", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652", false},
- {"2001:cdba:0:0:0:0:3257:9652", false},
- {"2001:cdba::3257:9652", false},
- }
- validate := New()
- validate.RegisterAlias("hostname", "hostname_rfc1123")
- for i, test := range tests {
- errs := validate.Var(test.param, "hostname")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "hostname" {
- t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
- }
- }
- }
- }
- }
- func TestFQDNValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"test.example.com", true},
- {"example.com", true},
- {"example24.com", true},
- {"test.example24.com", true},
- {"test24.example24.com", true},
- {"test.example.com.", true},
- {"example.com.", true},
- {"example24.com.", true},
- {"test.example24.com.", true},
- {"test24.example24.com.", true},
- {"test24.example24.com..", false},
- {"example", false},
- {"192.168.0.1", false},
- {"email@example.com", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652", false},
- {"2001:cdba:0:0:0:0:3257:9652", false},
- {"2001:cdba::3257:9652", false},
- {"", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "fqdn")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d fqdn failed Error: %v", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d fqdn failed Error: %v", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "fqdn" {
- t.Fatalf("Index: %d fqdn failed Error: %v", i, errs)
- }
- }
- }
- }
- }
- func TestIsDefault(t *testing.T) {
- validate := New()
- type Inner struct {
- String string `validate:"isdefault"`
- }
- type Test struct {
- String string `validate:"isdefault"`
- Inner *Inner `validate:"isdefault"`
- }
- var tt Test
- errs := validate.Struct(tt)
- Equal(t, errs, nil)
- tt.Inner = &Inner{String: ""}
- errs = validate.Struct(tt)
- NotEqual(t, errs, nil)
- fe := errs.(ValidationErrors)[0]
- Equal(t, fe.Field(), "Inner")
- Equal(t, fe.Namespace(), "Test.Inner")
- Equal(t, fe.Tag(), "isdefault")
- validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
- name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
- if name == "-" {
- return ""
- }
- return name
- })
- type Inner2 struct {
- String string `validate:"isdefault"`
- }
- type Test2 struct {
- Inner Inner2 `validate:"isdefault" json:"inner"`
- }
- var t2 Test2
- errs = validate.Struct(t2)
- Equal(t, errs, nil)
- t2.Inner.String = "Changed"
- errs = validate.Struct(t2)
- NotEqual(t, errs, nil)
- fe = errs.(ValidationErrors)[0]
- Equal(t, fe.Field(), "inner")
- Equal(t, fe.Namespace(), "Test2.inner")
- Equal(t, fe.Tag(), "isdefault")
- }
- func TestUniqueValidation(t *testing.T) {
- tests := []struct {
- param interface{}
- expected bool
- }{
- // Arrays
- {[2]string{"a", "b"}, true},
- {[2]int{1, 2}, true},
- {[2]float64{1, 2}, true},
- {[2]interface{}{"a", "b"}, true},
- {[2]interface{}{"a", 1}, true},
- {[2]float64{1, 1}, false},
- {[2]int{1, 1}, false},
- {[2]string{"a", "a"}, false},
- {[2]interface{}{"a", "a"}, false},
- {[4]interface{}{"a", 1, "b", 1}, false},
- // Slices
- {[]string{"a", "b"}, true},
- {[]int{1, 2}, true},
- {[]float64{1, 2}, true},
- {[]interface{}{"a", "b"}, true},
- {[]interface{}{"a", 1}, true},
- {[]float64{1, 1}, false},
- {[]int{1, 1}, false},
- {[]string{"a", "a"}, false},
- {[]interface{}{"a", "a"}, false},
- {[]interface{}{"a", 1, "b", 1}, false},
- // Maps
- {map[string]string{"one": "a", "two": "b"}, true},
- {map[string]int{"one": 1, "two": 2}, true},
- {map[string]float64{"one": 1, "two": 2}, true},
- {map[string]interface{}{"one": "a", "two": "b"}, true},
- {map[string]interface{}{"one": "a", "two": 1}, true},
- {map[string]float64{"one": 1, "two": 1}, false},
- {map[string]int{"one": 1, "two": 1}, false},
- {map[string]string{"one": "a", "two": "a"}, false},
- {map[string]interface{}{"one": "a", "two": "a"}, false},
- {map[string]interface{}{"one": "a", "two": 1, "three": "b", "four": 1}, false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "unique")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d unique failed Error: %v", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d unique failed Error: %v", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "unique" {
- t.Fatalf("Index: %d unique failed Error: %v", i, errs)
- }
- }
- }
- }
- PanicMatches(t, func() { _ = validate.Var(1.0, "unique") }, "Bad field type float64")
- }
- func TestHTMLValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"<html>", true},
- {"<script>", true},
- {"<stillworks>", true},
- {"</html", false},
- {"</script>", true},
- {"<//script>", false},
- {"<123nonsense>", false},
- {"test", false},
- {"&example", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "html")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d html failed Error: %v", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d html failed Error: %v", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "html" {
- t.Fatalf("Index: %d html failed Error: %v", i, errs)
- }
- }
- }
- }
- }
- func TestHTMLEncodedValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"<", true},
- {"¯", true},
- {"�", true},
- {"ð", true},
- {"<", true},
- {"¯", true},
- {"�", true},
- {"ð", true},
- {"&#ab", true},
- {"<", true},
- {">", true},
- {""", true},
- {"&", true},
- {"#x0a", false},
- {"&x00", false},
- {"z", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "html_encoded")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d html_encoded failed Error: %v", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d html_enocded failed Error: %v", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "html_encoded" {
- t.Fatalf("Index: %d html_encoded failed Error: %v", i, errs)
- }
- }
- }
- }
- }
- func TestURLEncodedValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"%20", true},
- {"%af", true},
- {"%ff", true},
- {"<%az", false},
- {"%test%", false},
- {"a%b", false},
- {"1%2", false},
- {"%%a%%", false},
- }
- validate := New()
- for i, test := range tests {
- errs := validate.Var(test.param, "url_encoded")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d url_encoded failed Error: %v", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d url_enocded failed Error: %v", i, errs)
- } else {
- val := getError(errs, "", "")
- if val.Tag() != "url_encoded" {
- t.Fatalf("Index: %d url_encoded failed Error: %v", i, errs)
- }
- }
- }
- }
- }
- func TestKeys(t *testing.T) {
- type Test struct {
- Test1 map[string]string `validate:"gt=0,dive,keys,eq=testkey,endkeys,eq=testval" json:"test1"`
- Test2 map[int]int `validate:"gt=0,dive,keys,eq=3,endkeys,eq=4" json:"test2"`
- Test3 map[int]int `validate:"gt=0,dive,keys,eq=3,endkeys" json:"test3"`
- }
- var tst Test
- validate := New()
- err := validate.Struct(tst)
- NotEqual(t, err, nil)
- Equal(t, len(err.(ValidationErrors)), 3)
- AssertError(t, err.(ValidationErrors), "Test.Test1", "Test.Test1", "Test1", "Test1", "gt")
- AssertError(t, err.(ValidationErrors), "Test.Test2", "Test.Test2", "Test2", "Test2", "gt")
- AssertError(t, err.(ValidationErrors), "Test.Test3", "Test.Test3", "Test3", "Test3", "gt")
- tst.Test1 = map[string]string{
- "testkey": "testval",
- }
- tst.Test2 = map[int]int{
- 3: 4,
- }
- tst.Test3 = map[int]int{
- 3: 4,
- }
- err = validate.Struct(tst)
- Equal(t, err, nil)
- tst.Test1["badtestkey"] = "badtestvalue"
- tst.Test2[10] = 11
- err = validate.Struct(tst)
- NotEqual(t, err, nil)
- errs := err.(ValidationErrors)
- Equal(t, len(errs), 4)
- AssertDeepError(t, errs, "Test.Test1[badtestkey]", "Test.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq", "eq")
- AssertDeepError(t, errs, "Test.Test1[badtestkey]", "Test.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq", "eq")
- AssertDeepError(t, errs, "Test.Test2[10]", "Test.Test2[10]", "Test2[10]", "Test2[10]", "eq", "eq")
- AssertDeepError(t, errs, "Test.Test2[10]", "Test.Test2[10]", "Test2[10]", "Test2[10]", "eq", "eq")
- type Test2 struct {
- NestedKeys map[[1]string]string `validate:"gt=0,dive,keys,dive,eq=innertestkey,endkeys,eq=outertestval"`
- }
- var tst2 Test2
- err = validate.Struct(tst2)
- NotEqual(t, err, nil)
- Equal(t, len(err.(ValidationErrors)), 1)
- AssertError(t, err.(ValidationErrors), "Test2.NestedKeys", "Test2.NestedKeys", "NestedKeys", "NestedKeys", "gt")
- tst2.NestedKeys = map[[1]string]string{
- [1]string{"innertestkey"}: "outertestval",
- }
- err = validate.Struct(tst2)
- Equal(t, err, nil)
- tst2.NestedKeys[[1]string{"badtestkey"}] = "badtestvalue"
- err = validate.Struct(tst2)
- NotEqual(t, err, nil)
- errs = err.(ValidationErrors)
- Equal(t, len(errs), 2)
- AssertDeepError(t, errs, "Test2.NestedKeys[[badtestkey]][0]", "Test2.NestedKeys[[badtestkey]][0]", "NestedKeys[[badtestkey]][0]", "NestedKeys[[badtestkey]][0]", "eq", "eq")
- AssertDeepError(t, errs, "Test2.NestedKeys[[badtestkey]]", "Test2.NestedKeys[[badtestkey]]", "NestedKeys[[badtestkey]]", "NestedKeys[[badtestkey]]", "eq", "eq")
- // test bad tag definitions
- PanicMatches(t, func() { _ = validate.Var(map[string]string{"key": "val"}, "endkeys,dive,eq=val") }, "'endkeys' tag encountered without a corresponding 'keys' tag")
- PanicMatches(t, func() { _ = validate.Var(1, "keys,eq=1,endkeys") }, "'keys' tag must be immediately preceded by the 'dive' tag")
- // test custom tag name
- validate = New()
- validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
- name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
- if name == "-" {
- return ""
- }
- return name
- })
- err = validate.Struct(tst)
- NotEqual(t, err, nil)
- errs = err.(ValidationErrors)
- Equal(t, len(errs), 4)
- AssertDeepError(t, errs, "Test.test1[badtestkey]", "Test.Test1[badtestkey]", "test1[badtestkey]", "Test1[badtestkey]", "eq", "eq")
- AssertDeepError(t, errs, "Test.test1[badtestkey]", "Test.Test1[badtestkey]", "test1[badtestkey]", "Test1[badtestkey]", "eq", "eq")
- AssertDeepError(t, errs, "Test.test2[10]", "Test.Test2[10]", "test2[10]", "Test2[10]", "eq", "eq")
- AssertDeepError(t, errs, "Test.test2[10]", "Test.Test2[10]", "test2[10]", "Test2[10]", "eq", "eq")
- }
- // Thanks @adrian-sgn specific test for your specific scenario
- func TestKeysCustomValidation(t *testing.T) {
- type LangCode string
- type Label map[LangCode]string
- type TestMapStructPtr struct {
- Label Label `validate:"dive,keys,lang_code,endkeys,required"`
- }
- validate := New()
- err := validate.RegisterValidation("lang_code", func(fl FieldLevel) bool {
- validLangCodes := map[LangCode]struct{}{
- "en": {},
- "es": {},
- "pt": {},
- }
- _, ok := validLangCodes[fl.Field().Interface().(LangCode)]
- return ok
- })
- Equal(t, err, nil)
- label := Label{
- "en": "Good morning!",
- "pt": "",
- "es": "¡Buenos días!",
- "xx": "Bad key",
- "xxx": "",
- }
- err = validate.Struct(TestMapStructPtr{label})
- NotEqual(t, err, nil)
- errs := err.(ValidationErrors)
- Equal(t, len(errs), 4)
- AssertDeepError(t, errs, "TestMapStructPtr.Label[xx]", "TestMapStructPtr.Label[xx]", "Label[xx]", "Label[xx]", "lang_code", "lang_code")
- AssertDeepError(t, errs, "TestMapStructPtr.Label[pt]", "TestMapStructPtr.Label[pt]", "Label[pt]", "Label[pt]", "required", "required")
- AssertDeepError(t, errs, "TestMapStructPtr.Label[xxx]", "TestMapStructPtr.Label[xxx]", "Label[xxx]", "Label[xxx]", "lang_code", "lang_code")
- AssertDeepError(t, errs, "TestMapStructPtr.Label[xxx]", "TestMapStructPtr.Label[xxx]", "Label[xxx]", "Label[xxx]", "required", "required")
- // find specific error
- var e FieldError
- for _, e = range errs {
- if e.Namespace() == "TestMapStructPtr.Label[xxx]" {
- break
- }
- }
- Equal(t, e.Param(), "")
- Equal(t, e.Value().(LangCode), LangCode("xxx"))
- for _, e = range errs {
- if e.Namespace() == "TestMapStructPtr.Label[xxx]" && e.Tag() == "required" {
- break
- }
- }
- Equal(t, e.Param(), "")
- Equal(t, e.Value().(string), "")
- }
- func TestKeyOrs(t *testing.T) {
- type Test struct {
- Test1 map[string]string `validate:"gt=0,dive,keys,eq=testkey|eq=testkeyok,endkeys,eq=testval" json:"test1"`
- }
- var tst Test
- validate := New()
- err := validate.Struct(tst)
- NotEqual(t, err, nil)
- Equal(t, len(err.(ValidationErrors)), 1)
- AssertError(t, err.(ValidationErrors), "Test.Test1", "Test.Test1", "Test1", "Test1", "gt")
- tst.Test1 = map[string]string{
- "testkey": "testval",
- }
- err = validate.Struct(tst)
- Equal(t, err, nil)
- tst.Test1["badtestkey"] = "badtestval"
- err = validate.Struct(tst)
- NotEqual(t, err, nil)
- errs := err.(ValidationErrors)
- Equal(t, len(errs), 2)
- AssertDeepError(t, errs, "Test.Test1[badtestkey]", "Test.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq=testkey|eq=testkeyok", "eq=testkey|eq=testkeyok")
- AssertDeepError(t, errs, "Test.Test1[badtestkey]", "Test.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq", "eq")
- validate.RegisterAlias("okkey", "eq=testkey|eq=testkeyok")
- type Test2 struct {
- Test1 map[string]string `validate:"gt=0,dive,keys,okkey,endkeys,eq=testval" json:"test1"`
- }
- var tst2 Test2
- err = validate.Struct(tst2)
- NotEqual(t, err, nil)
- Equal(t, len(err.(ValidationErrors)), 1)
- AssertError(t, err.(ValidationErrors), "Test2.Test1", "Test2.Test1", "Test1", "Test1", "gt")
- tst2.Test1 = map[string]string{
- "testkey": "testval",
- }
- err = validate.Struct(tst2)
- Equal(t, err, nil)
- tst2.Test1["badtestkey"] = "badtestval"
- err = validate.Struct(tst2)
- NotEqual(t, err, nil)
- errs = err.(ValidationErrors)
- Equal(t, len(errs), 2)
- AssertDeepError(t, errs, "Test2.Test1[badtestkey]", "Test2.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "okkey", "eq=testkey|eq=testkeyok")
- AssertDeepError(t, errs, "Test2.Test1[badtestkey]", "Test2.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq", "eq")
- }
- func TestStructLevelValidationsPointerPassing(t *testing.T) {
- v1 := New()
- v1.RegisterStructValidation(StructValidationTestStruct, &TestStruct{})
- tst := &TestStruct{
- String: "good value",
- }
- errs := v1.Struct(tst)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestStruct.StringVal", "TestStruct.String", "StringVal", "String", "badvalueteststruct")
- }
- func TestDirValidation(t *testing.T) {
- validate := New()
- tests := []struct {
- title string
- param string
- expected bool
- }{
- {"existing dir", "testdata", true},
- {"existing self dir", ".", true},
- {"existing parent dir", "..", true},
- {"empty dir", "", false},
- {"missing dir", "non_existing_testdata", false},
- {"a file not a directory", filepath.Join("testdata", "a.go"), false},
- }
- for _, test := range tests {
- errs := validate.Var(test.param, "dir")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Test: '%s' failed Error: %s", test.title, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Test: '%s' failed Error: %s", test.title, errs)
- }
- }
- }
- PanicMatches(t, func() {
- _ = validate.Var(2, "dir")
- }, "Bad field type int")
- }
- func TestStartsWithValidation(t *testing.T) {
- tests := []struct {
- Value string `validate:"startswith=(/^ヮ^)/*:・゚✧"`
- Tag string
- ExpectedNil bool
- }{
- {Value: "(/^ヮ^)/*:・゚✧ glitter", Tag: "startswith=(/^ヮ^)/*:・゚✧", ExpectedNil: true},
- {Value: "abcd", Tag: "startswith=(/^ヮ^)/*:・゚✧", ExpectedNil: false},
- }
- validate := New()
- for i, s := range tests {
- errs := validate.Var(s.Value, s.Tag)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- errs = validate.Struct(s)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- }
- }
- func TestEndsWithValidation(t *testing.T) {
- tests := []struct {
- Value string `validate:"endswith=(/^ヮ^)/*:・゚✧"`
- Tag string
- ExpectedNil bool
- }{
- {Value: "glitter (/^ヮ^)/*:・゚✧", Tag: "endswith=(/^ヮ^)/*:・゚✧", ExpectedNil: true},
- {Value: "(/^ヮ^)/*:・゚✧ glitter", Tag: "endswith=(/^ヮ^)/*:・゚✧", ExpectedNil: false},
- }
- validate := New()
- for i, s := range tests {
- errs := validate.Var(s.Value, s.Tag)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- errs = validate.Struct(s)
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- }
- }
- func TestRequiredWith(t *testing.T) {
- type Inner struct {
- Field *string
- }
- fieldVal := "test"
- test := struct {
- Inner *Inner
- FieldE string `validate:"omitempty" json:"field_e"`
- FieldER string `validate:"required_with=FieldE" json:"field_er"`
- Field1 string `validate:"omitempty" json:"field_1"`
- Field2 *string `validate:"required_with=Field1" json:"field_2"`
- Field3 map[string]string `validate:"required_with=Field2" json:"field_3"`
- Field4 interface{} `validate:"required_with=Field3" json:"field_4"`
- Field5 string `validate:"required_with=Inner.Field" json:"field_5"`
- }{
- Inner: &Inner{Field: &fieldVal},
- Field2: &fieldVal,
- Field3: map[string]string{"key": "val"},
- Field4: "test",
- Field5: "test",
- }
- validate := New()
- errs := validate.Struct(test)
- Equal(t, errs, nil)
- test2 := struct {
- Inner *Inner
- Inner2 *Inner
- FieldE string `validate:"omitempty" json:"field_e"`
- FieldER string `validate:"required_with=FieldE" json:"field_er"`
- Field1 string `validate:"omitempty" json:"field_1"`
- Field2 *string `validate:"required_with=Field1" json:"field_2"`
- Field3 map[string]string `validate:"required_with=Field2" json:"field_3"`
- Field4 interface{} `validate:"required_with=Field2" json:"field_4"`
- Field5 string `validate:"required_with=Field3" json:"field_5"`
- Field6 string `validate:"required_with=Inner.Field" json:"field_6"`
- Field7 string `validate:"required_with=Inner2.Field" json:"field_7"`
- }{
- Inner: &Inner{Field: &fieldVal},
- Field2: &fieldVal,
- }
- errs = validate.Struct(test2)
- NotEqual(t, errs, nil)
- ve := errs.(ValidationErrors)
- Equal(t, len(ve), 3)
- AssertError(t, errs, "Field3", "Field3", "Field3", "Field3", "required_with")
- AssertError(t, errs, "Field4", "Field4", "Field4", "Field4", "required_with")
- AssertError(t, errs, "Field6", "Field6", "Field6", "Field6", "required_with")
- }
- func TestRequiredWithAll(t *testing.T) {
- type Inner struct {
- Field *string
- }
- fieldVal := "test"
- test := struct {
- Inner *Inner
- FieldE string `validate:"omitempty" json:"field_e"`
- FieldER string `validate:"required_with_all=FieldE" json:"field_er"`
- Field1 string `validate:"omitempty" json:"field_1"`
- Field2 *string `validate:"required_with_all=Field1" json:"field_2"`
- Field3 map[string]string `validate:"required_with_all=Field2" json:"field_3"`
- Field4 interface{} `validate:"required_with_all=Field3" json:"field_4"`
- Field5 string `validate:"required_with_all=Inner.Field" json:"field_5"`
- }{
- Inner: &Inner{Field: &fieldVal},
- Field1: "test_field1",
- Field2: &fieldVal,
- Field3: map[string]string{"key": "val"},
- Field4: "test",
- Field5: "test",
- }
- validate := New()
- errs := validate.Struct(test)
- Equal(t, errs, nil)
- test2 := struct {
- Inner *Inner
- Inner2 *Inner
- FieldE string `validate:"omitempty" json:"field_e"`
- FieldER string `validate:"required_with_all=FieldE" json:"field_er"`
- Field1 string `validate:"omitempty" json:"field_1"`
- Field2 *string `validate:"required_with_all=Field1" json:"field_2"`
- Field3 map[string]string `validate:"required_with_all=Field2" json:"field_3"`
- Field4 interface{} `validate:"required_with_all=Field1 FieldE" json:"field_4"`
- Field5 string `validate:"required_with_all=Inner.Field Field2" json:"field_5"`
- Field6 string `validate:"required_with_all=Inner2.Field Field2" json:"field_6"`
- }{
- Inner: &Inner{Field: &fieldVal},
- Field2: &fieldVal,
- }
- errs = validate.Struct(test2)
- NotEqual(t, errs, nil)
- ve := errs.(ValidationErrors)
- Equal(t, len(ve), 2)
- AssertError(t, errs, "Field3", "Field3", "Field3", "Field3", "required_with_all")
- AssertError(t, errs, "Field5", "Field5", "Field5", "Field5", "required_with_all")
- }
- func TestRequiredWithout(t *testing.T) {
- type Inner struct {
- Field *string
- }
- fieldVal := "test"
- test := struct {
- Inner *Inner
- Field1 string `validate:"omitempty" json:"field_1"`
- Field2 *string `validate:"required_without=Field1" json:"field_2"`
- Field3 map[string]string `validate:"required_without=Field2" json:"field_3"`
- Field4 interface{} `validate:"required_without=Field3" json:"field_4"`
- Field5 string `validate:"required_without=Field3" json:"field_5"`
- }{
- Inner: &Inner{Field: &fieldVal},
- Field2: &fieldVal,
- Field3: map[string]string{"key": "val"},
- Field4: "test",
- Field5: "test",
- }
- validate := New()
- errs := validate.Struct(test)
- Equal(t, errs, nil)
- test2 := struct {
- Inner *Inner
- Inner2 *Inner
- Field1 string `json:"field_1"`
- Field2 *string `validate:"required_without=Field1" json:"field_2"`
- Field3 map[string]string `validate:"required_without=Field2" json:"field_3"`
- Field4 interface{} `validate:"required_without=Field3" json:"field_4"`
- Field5 string `validate:"required_without=Field3" json:"field_5"`
- Field6 string `validate:"required_without=Field1" json:"field_6"`
- Field7 string `validate:"required_without=Inner.Field" json:"field_7"`
- Field8 string `validate:"required_without=Inner.Field" json:"field_8"`
- }{
- Inner: &Inner{},
- Field3: map[string]string{"key": "val"},
- Field4: "test",
- Field5: "test",
- }
- errs = validate.Struct(&test2)
- NotEqual(t, errs, nil)
- ve := errs.(ValidationErrors)
- Equal(t, len(ve), 4)
- AssertError(t, errs, "Field2", "Field2", "Field2", "Field2", "required_without")
- AssertError(t, errs, "Field6", "Field6", "Field6", "Field6", "required_without")
- AssertError(t, errs, "Field7", "Field7", "Field7", "Field7", "required_without")
- AssertError(t, errs, "Field8", "Field8", "Field8", "Field8", "required_without")
- }
- func TestRequiredWithoutAll(t *testing.T) {
- fieldVal := "test"
- test := struct {
- Field1 string `validate:"omitempty" json:"field_1"`
- Field2 *string `validate:"required_without_all=Field1" json:"field_2"`
- Field3 map[string]string `validate:"required_without_all=Field2" json:"field_3"`
- Field4 interface{} `validate:"required_without_all=Field3" json:"field_4"`
- Field5 string `validate:"required_without_all=Field3" json:"field_5"`
- }{
- Field1: "",
- Field2: &fieldVal,
- Field3: map[string]string{"key": "val"},
- Field4: "test",
- Field5: "test",
- }
- validate := New()
- errs := validate.Struct(test)
- Equal(t, errs, nil)
- test2 := struct {
- Field1 string `validate:"omitempty" json:"field_1"`
- Field2 *string `validate:"required_without_all=Field1" json:"field_2"`
- Field3 map[string]string `validate:"required_without_all=Field2" json:"field_3"`
- Field4 interface{} `validate:"required_without_all=Field3" json:"field_4"`
- Field5 string `validate:"required_without_all=Field3" json:"field_5"`
- Field6 string `validate:"required_without_all=Field1 Field3" json:"field_6"`
- }{
- Field3: map[string]string{"key": "val"},
- Field4: "test",
- Field5: "test",
- }
- errs = validate.Struct(test2)
- NotEqual(t, errs, nil)
- ve := errs.(ValidationErrors)
- Equal(t, len(ve), 1)
- AssertError(t, errs, "Field2", "Field2", "Field2", "Field2", "required_without_all")
- }
- func TestLookup(t *testing.T) {
- type Lookup struct {
- FieldA *string `json:"fieldA,omitempty" validate:"required_without=FieldB"`
- FieldB *string `json:"fieldB,omitempty" validate:"required_without=FieldA"`
- }
- fieldAValue := "1232"
- lookup := Lookup{
- FieldA: &fieldAValue,
- FieldB: nil,
- }
- Equal(t, New().Struct(lookup), nil)
- }
- func TestAbilityToValidateNils(t *testing.T) {
- type TestStruct struct {
- Test *string `validate:"nil"`
- }
- ts := TestStruct{}
- val := New()
- fn := func(fl FieldLevel) bool {
- return fl.Field().Kind() == reflect.Ptr && fl.Field().IsNil()
- }
- err := val.RegisterValidation("nil", fn, true)
- Equal(t, err, nil)
- errs := val.Struct(ts)
- Equal(t, errs, nil)
- str := "string"
- ts.Test = &str
- errs = val.Struct(ts)
- NotEqual(t, errs, nil)
- }
|