12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765 |
- 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: "",
- },
- }
- 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()
- }
- validate.RegisterValidation("isequaltestfunc", fn)
- 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)
- 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",
- }
- 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
- 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")
- trans.Add("required", "{0} is a required field", false) // using translator outside of validator also
- 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
- })
- validate.RegisterValidation("custom1", func(fl FieldLevel) bool {
- res1 = fl.FieldName()
- alt1 = fl.StructFieldName()
- return true
- })
- validate.RegisterValidation("custom2", func(fl FieldLevel) bool {
- res2 = fl.FieldName()
- alt2 = fl.StructFieldName()
- return true
- })
- validate.RegisterValidation("custom3", func(fl FieldLevel) bool {
- res3 = fl.FieldName()
- alt3 = fl.StructFieldName()
- return true
- })
- validate.RegisterValidation("custom4", func(fl FieldLevel) bool {
- res4 = fl.FieldName()
- alt4 = fl.StructFieldName()
- return true
- })
- validate.RegisterValidation("custom5", func(fl FieldLevel) bool {
- res5 = fl.FieldName()
- alt5 = fl.StructFieldName()
- return true
- })
- 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()
- validate.RegisterValidationCtx("val", fnCtx)
- 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()
- validate.RegisterValidation("lang_code", func(fl FieldLevel) bool {
- validLangCodes := map[LangCode]struct{}{
- "en": {},
- "es": {},
- "pt": {},
- }
- _, ok := validLangCodes[fl.Field().Interface().(LangCode)]
- return ok
- })
- 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) {
- fieldVal := "test"
- test := struct {
- 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=Field3" json:"field_5"`
- }{
- Field1: "test_field1",
- Field2: &fieldVal,
- Field3: map[string]string{"key": "val"},
- Field4: "test",
- Field5: "test",
- }
- validate := New()
- errs := validate.Struct(test)
- if errs != nil {
- t.Fatalf("failed Error: %s", errs)
- }
- }
- func TestRequiredWithAll(t *testing.T) {
- fieldVal := "test"
- test := struct {
- 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=Field3" json:"field_5"`
- }{
- Field1: "test_field1",
- Field2: &fieldVal,
- Field3: map[string]string{"key": "val"},
- Field4: "test",
- Field5: "test",
- }
- validate := New()
- errs := validate.Struct(test)
- if errs != nil {
- t.Fatalf("failed Error: %s", errs)
- }
- }
- func TestRequiredWithout(t *testing.T) {
- fieldVal := "test"
- test := struct {
- 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"`
- }{
- Field2: &fieldVal,
- Field3: map[string]string{"key": "val"},
- Field4: "test",
- Field5: "test",
- }
- validate := New()
- errs := validate.Struct(test)
- if errs != nil {
- t.Fatalf("failed Error: %s", errs)
- }
- test2 := struct {
- 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"`
- Field6 string `validate:"required_without=Field1" json:"field_6"`
- }{
- Field3: map[string]string{"key": "val"},
- Field4: "test",
- Field5: "test",
- }
- errs = validate.Struct(&test2)
- if errs == nil {
- t.Fatalf("failed Error: %s", errs)
- }
- }
- 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)
- if errs != nil {
- t.Fatalf("failed Error: %s", errs)
- }
- 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" json:"field_6"`
- }{
- Field3: map[string]string{"key": "val"},
- Field4: "test",
- Field5: "test",
- }
- errs = validate.Struct(test2)
- if errs == nil {
- t.Fatalf("failed Error: %s", errs)
- }
- }
|