Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better golden filenames #35

Merged
merged 5 commits into from
Mar 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ val compilerOptions = Seq(
)

val circeVersion = "0.13.0"
val previousCirceGoldenVersion = "0.2.0"

def priorTo2_13(scalaVersion: String): Boolean =
CrossVersion.partialVersion(scalaVersion) match {
Expand Down Expand Up @@ -65,6 +66,7 @@ lazy val golden = crossProject(JSPlatform, JVMPlatform)
.settings(allSettings)
.settings(
moduleName := "circe-golden",
mimaPreviousArtifacts := Set("io.circe" %% "circe-golden" % previousCirceGoldenVersion),
libraryDependencies ++= Seq(
"io.circe" %%% "circe-core" % circeVersion,
"io.circe" %%% "circe-parser" % circeVersion,
Expand Down Expand Up @@ -100,9 +102,7 @@ lazy val publishSettings = Seq(
licenses := Seq("Apache 2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0")),
publishMavenStyle := true,
publishArtifact in Test := false,
pomIncludeRepository := { _ =>
false
},
pomIncludeRepository := { _ => false },
publishTo := {
val nexus = "https://oss.sonatype.org/"
if (isSnapshot.value)
Expand Down
32 changes: 32 additions & 0 deletions examples/example-1/src/main/scala/io/circe/examples/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,35 @@ object Foo {
}
}
}

case class MyList[A](value: List[A])

object MyList {
import cats.kernel.instances.list._

implicit def eqMyList[A](implicit A: Eq[A]): Eq[MyList[A]] = Eq.by[MyList[A], List[A]](_.value)
implicit def arbitraryMyList[A](implicit A: Arbitrary[A]): Arbitrary[MyList[A]] =
Arbitrary(Arbitrary.arbitrary[List[A]].map(as => MyList(as.take(2))))

implicit def encodeMyList[A](implicit A: Encoder[A]): Encoder[MyList[A]] =
Encoder[List[A]].contramap(_.value)

implicit def decodeMyList[A](implicit A: Decoder[A]): Decoder[MyList[A]] =
Decoder[List[A]].map(MyList(_))
}

case class MyTuple[A, B](value: (A, B))

object MyTuple {
import cats.kernel.instances.tuple._

implicit def eqMyTuple[A, B](implicit A: Eq[A], B: Eq[B]): Eq[MyTuple[A, B]] = Eq.by[MyTuple[A, B], (A, B)](_.value)
implicit def arbitraryMyTuple[A, B](implicit A: Arbitrary[A], B: Arbitrary[B]): Arbitrary[MyTuple[A, B]] =
Arbitrary(Arbitrary.arbitrary[(A, B)].map(MyTuple(_)))

implicit def encodeMyTuple[A, B](implicit A: Encoder[A], B: Encoder[B]): Encoder[MyTuple[A, B]] =
Encoder[(A, B)].contramap(_.value)

implicit def decodeMyTuple[A, B](implicit A: Decoder[A], B: Decoder[B]): Decoder[MyTuple[A, B]] =
Decoder[(A, B)].map(MyTuple(_))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[
{
"Bar" : {
"i" : 1354708449,
"s" : "Ꚁ⭨⧫惬丄ҹᜐ챿踕敉㾣ꪸ뾼ḣɉ뻃ᨵ倳腂䱚௓͍᳸뎪茤ÿ恨쿝഻컰眔ꜜ㦶휅␿㉘믏ሯ列㓘奈ო杏뫜ꏧ뻹莦蹦觀ᷔ빩⡿둍썑솾ﮨォ죅딘獔䑫䅋邚奱뷛弙⸜䤉裏䟬롹輅癟勅뉴篵啲ྟ쪹跰ꥧ䞡ᚋ᱑ᶦ⫂﹙ⵧ"
}
},
{
"Bam" : {
"w" : {
"x" : 4614758925641204259
},
"d" : -6.218054213507078E100
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"x" : 8448299872450029541
},
{
"x" : -9223372036854775808
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
[
[
{
"x" : -5802440138672620113
},
{
"x" : -1977652276563982404
}
],
[
[
{
"Bar" : {
"i" : 1,
"s" : "겋摥ල䣾峝烇솠뫶⾝喇ᢃ덗戄탅뭖礷焝윲毪ො얼ɱ氡廔築뎃蹒향丧拻⍾䁟鲅웥畛븓佣ⷓᰲㇷ셹䈒鏒첝玪盢✦弥᥹ⷤⳤ㬉ࢳ鸎농⵵洵붴됟바뫚돀䘻咾傘䉸"
}
},
{
"Bam" : {
"w" : {
"x" : 62346120588563582
},
"d" : 4.5895418521896643E-234
}
}
],
[
{
"Baz" : [
"Ⳗ碈㿦厺籛륃",
"劾稉ཆ⺪鮝⌶口콂猞홙ᔀ⿩펌ꝶ豫ڂ鸏눢Ζກ稒ʟ᩷莣迥Ᏺ嚴劙꫆䦊爄쒊ꭲ䂵핺수怵偒ヿ뤃䈞㪵ⴜ᤿恏厨ꠟᒲ繌鿬ഀ萿ᶜ쳍뉍쇖嵡肃⻌ꈖ㽚塜ꏡ핇宲왺䫪灳闷",
"૧鮟畎㷟尾뙘ࠉ斾ﲁ쮿七ﹶ༚⑙㼿咢틃辩ీ❩⻀ۋꗢ⾗䩮椉僮ힶ憼侘둚堸釳誒ᎎ욱㖤ᨭꤞ趀壈ᒘ팫갎鳶柮䐠욗頰䇧䁾ﱸ䎄죺⇺",
"셐憋䑘藞帊唥殟喡趱桝행댭쮄좂俥椷年栢ਟ셶Ṭ⠈龜꽲풲刜䏊┏톬릻╪햜ﰩ杌粟﷼淉ꇝ⻅⍾偀᷼鰤꛷垀⬁ꪈ䁎ꐡ毝錵馐瘘㔬ާ鞘磊뢦욑兡單쾩໅鄁蒍ႂ臓ퟳब",
"಩챁㓒ﺐ亠᥌ꩉꤤ刀搕쮱℅絀镟뀱ٝ楽༷⤅㤄Ä囂膝홾邆ᝈ眗ஐ",
"䯲䊔",
"⢴舐ᐡ뚓嘎뮜䰲恸﫹䤡눋瓹␌ᡞ疁觑퇸የ鐘",
"貹ശ㿍肯閿늗쀽Ӡ복﨔탨赶㬨䉪큵쩎讻珊鍇柆๞ꃊ⑫࠹懳뼑磓엧엿䬸焪麟ꐁ䳳嵃ꪔ쓲ᵬﶚ㐮⽛!⿈ৡ뭵舻갽䣅樫짯샆藢*튰鋐㪗ﬞ῵䭰徼镾벫㒆",
"䲞琄棒뽏͍痸刄餚鴭莇鹈涺Ⳉ铗롱鐤绥⓮ⲉ㌸̑",
"齆铼瑧酯˙癁Ͻ贯룏錫⨎㱀ফꥸ澪賨ᩂ늅玿䰮䐿帰W㫁ೠ猟ᇭ濏ﳢꅎ궝毻ፋ绋ꧣ毣晾ͬ䕙窸",
"릪鲎Ꜵṫᶎ皋ȿ퀵ꎼㄸ繼㚬鶍쳴覫踩尃릮ൈ׃䉵덿〙ᨂ熾ᆂ㖅੣˻댇觋脒ǒ떍㐇鲢R嬱ʨᤙ䒜荘藔ㅜꈘ抽",
"桔⪡ِ剟崙첇ᶅ⥡橡績檈ﭺ⫦鍥ퟎ廬蓬ފ砰饜헽귛呹⊱簰벯쵽艹脷ﵝ糀ﯫ≥鴍Ⰷꎔ鋧⚏ﳣ䞭≜罨㜳쮗ᖣꆘ녂✑爓馗᰼泵괕✐嫉ꍥﲔ儁騖㡴戎岛ᩴꭦ嶅們ゔ妧뿡᎝젅Ϡ",
"ꓖᢕῖᏏ있喵嬥誦鄂,ኍ艭⧳뺤៩悾㻛뮟檾挿ꃥ▮貰ꁍ矵슄변㺬圓⋂뀧䞎켜⪎ꓑ璍풫鷍ⅽ횥茴ᡇ梉왡碸놩艛䅦쒡㯕늪ৱ컽嘕᪲椘뫹몶῀멷诣㔲뇤䚣뺴䚧▼议㡥汉ﵞ鉁肇쮄㐈ꋵ㘡莈䤈玆䌷꤃혈ኄ鬕솩",
"ఴ漠㧮ꟹ噽즤棻臭䷕韩㠇㚄䧲鰆䉹놨ᦾᏘ禂㦝䫔㡏篂⾇鋝樧臂튓㰱孳향꫉멓ㆺᜒ휅梽饔ﴻ쳇ꬔ㸹쁝뵍ᱭ곆毝㈱輳량釪ତऺ驈㦍ᯅ购傴曭",
"莱퍇芅쿐螒㯳倈휟昞ꖘᦌ埵˲㻃乾摎꽌ߘယ玡ﰴ澚𤋮ஏ䡿≯瞈ɍㆣ鷛鯰鼳ᓟ볹煻㍜踠馦ㄐㆽ釆롵앚⿔뱚⏺멄ꞛ籺醶⌯涶뱅ꀂ叔豊採Ӕ䗡济䧟ꎅ꓾彃叶痭賥ೖ䂀먩곭∷樤눅䦳ㆸ潃띌颙䴨.苃繒Ě䎝䉕쑮ꌽ⯓ꈳ鞶ᘗ漨㕑",
"磮◷䳫읁鿣踋靃⎥煭进阰垸䝥艽",
"ᤨ⼁頊₽᝻ḹ㘔샦戴ꏞ蜷둭䕎枅ꙃỲƪಃ瀤橖췡终㠻ꐠ奲錂焷⿪팘ⶡྠ㶆욍쓙ᆣ䜽週ƻ䄨渾꫷鏒莛쏵嗟耱㿲抮ꜰ粂콥ထ푊ᱹ켠ﰗ퓛♿璝驥莂ꁧ冒쓶ꌎ࿧",
"使鏽퀩傕쇈ᆙ褻㙧렵ﮎ邃โꤿ欿쿏밫雂僸捍糢♀⎫ຠজ쫵಴㑻䃖䬐鍔몮㣮⠽৫ㄎ孳뙥蓤트评㼈뉟ࡁ囯펜駓樟錗䐽ꨒ㏻",
"敟設౮ﷸ嚙अ⽗窒ꬓⶺ曈䋷랚쳙࣑맀窾⧶슨㸜漷옰僐⤺툳௶赵뱷Ҽ滞枕ꤏ嘶矕שּ껽ⲵ䘜쯻﯑㷨湓↦缏ӈ檽씏ム蠕ꃑ䙑跂熻╽襂烏溱嘩",
"낫펼뷝螖ᅋ鑺㐇髟뽖뗀៩",
"튾ᐇ픡慨裢迈폃萪῝٦賜昞ﯚṬ糎퉉థ䜠䦴⩠敲ȧ핋䆤쳈鍴쳫艢㓿ⵠ䫔䂣ﶟ骼즱뼕꥕槃魬訖챙翚䒞諳畿展靆㖂م釅䘂靹ᔭ쀯糸㖝⺛뼥쥗⼲៬ꪨ詨㋬惭䕟쳽鐤ফ諭땳ࡾ稪씈ら噣雪氢㶿꯸⛵웸鷠䖿",
"枋﷞等餝밈ⓧ䮎᜽䵬䲖释㚟Ș濼ଂ琱碀Ⰷ椵鞢ᒐ娰獼㫂羊呺慳鈌䰏䩒瞱㎟꿰ꝼ⯧칳산옜퐖l㋮顱欽ⶂᬑ޺熊ϖ断斉䘜넡操뢫쵏隷佘퀋╗犑켐塘ꥬ怋ڀ䤅윫䟧뢲ꞷ婏模᪅延",
"吥摁薱㭓廿汥樂熱剫쌌昽꺨ഖ寯锈䊝礡띴₏䢔릇⫘ᥙ큍㨝ﵮ뷇꾁녘⣋⚐鰗륞䜻虙ϳ﷔ᴀ",
"ჳ扵趞ṳꒆ겁먧ꭾ袕䩖놁楁䗃䳓덉쮹빪돝用鯑̢뙚窗袹탢툔摺",
"눷᮫蒙䁺⹬䛺㩤䝓帰鐹癪訋縬咇藦ၭᵁ",
"闥䬯譝ェ⤠핓୆묚憾稄䛤蔚ݮ䕡꘏躭騒퍨ኘ惍⛺醠먪㉨⽸Ꜯ♎⬧米夕",
"斕ᯈ抦퓜渙꺩孎࠿㗎྆ﱃ䄮髞㗙曁鲝㸮읠軐麤셈䞽拏⥄恒့ኅ콭ہ矉Ըﯪⶊﯟ䔭愅沫湄꠮三霑⩸灳᭪䔦㽠㺠굖怒概ચሕ鱚壿毁뺊㓍춺깵㝵⥿ꢀ溂䱹甎뱈뽻徚롴㌃ᧁ꼾撏⸆䖾坪",
"鄉劫冏⏘忨⨘ᄒ帰䶣ꗯ䝏⛜湐玣븫꒩扰旆袍果ǚ紵ᬍ덭ﵾ憌㶼忉嚑ꆓ汖ꫬ┸挬ಕb뮚ʨ坢ᒯ㋊Ƹ꣭훦ꄀ䊲࢘须䚐鳖던㲘萻颾䨵㐻ᧈ糚冗漼꼽ሞ蹏堢㢝⽴增羑ﵵ鴾孏㚰㰺汪⓲짔覐ݘ⏫Ğ콨젾蜇⡲쿖",
"힪䅕✷厅␁ํ孡眊쾏乪癐츍⭑⌚コ⋟敻㡼辩㐻Ṛ犑",
"擇䙑泥敜︱貿叉恼῾趧晎乵篨斍䗇푚ﳖⷦ㋿Ț쯷䮝覶￵눣⠲螛ꅽ泎믥屸ꕭቌ꿌녯傌鰉告ᆤ돯䴏滨⦯꽃렀吞칤䢿ຕ稇廠홞",
"䩂ᔩ쫓턇寫群癍錃驀ㄐ኿뒰逋᧐렿阶깄뇵蕫흨㏖౯蕯➼騾惡ꂙ諏휢꽛ჿ輻ⶤﴓ",
"딳啐ѫ㸏颡鞯渆㲗",
"䖞枿媻룪￶䔉Ȓ⽦䨟ኈ沬漞䜭沉뚾⇕蠫陲ូ雴֢㗮㹱Æ꘿灍꘩䞍嶂Թ톓혉஖⼔缃䈺巘嶜녘ࠢ씳ᕖ멵뙄ꨨ蠭ꮩ⁌膦Շꖹ⻜䵔捰対㰌蓶⯘Ⱗ졂◫열鋳ષ",
"츌ଣ녩蛏ꈂ铔ﲛ혥飯炲郄忺﫻ᕁ嘁๗බ鑨⁾ᔷꁂܹ뱔郯霞杮꫱䒽੡笩蓎㰰蹺壘┓䯶༃噶㻕퉦蟂蜥堗ꁅⷰ褟✷쳞᧊紜㩗욼㊦缏",
"҉僝뚽⭁⁆猛⫲ﲰƍ巗↰ꫀ獞굫治⏡⃵ﬔ眞䯹軻逥⃂遉賴黸₍息假⧁釷㠢皑䴘꽋嬚ㅉ끓엡菀㈇В對缢ꐵ昔ꂜ喣",
"ꭹ壏苀ㆁ᫼셔큟呅놏弅ﳶᛷ紁码聃࠺츁䨫⁩Ᾱ塚훗絿ᷕ⳧耾㡗誾ήﻍ艇쇙肹⑞כֿ",
"ﭒ丨嗘獨竨ﭽӒ䫢ꂥ鬋ㄣ䆃㋞絅אָ켏矱뭺㉟튂偧䪺뵙箭懼짅횭⑕⢕ጸ邬뎣؀ે",
"ퟙ₱쓋鶒䳈ᇒ귺恴ꏭꓜዟี㓏狢皅⢆⸿蟨ᬊ㾿櫣ṇ創"
]
},
{
"Bar" : {
"i" : 0,
"s" : "㇏띌⪧낔Ὶ漱痽ߦ䬙ಟ►捣鲋䨥鵃貲ᘊꨅ掻鍯᳠ほ<액튺钶兩ጸ훭뙲࠱힛란칎骧⬢᥿䬪珵"
}
}
]
]
]
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.circe.examples

import cats.instances.list._
import io.circe.testing.instances._
import io.circe.testing.golden._
import org.scalatest.flatspec.AnyFlatSpec
Expand All @@ -9,4 +10,14 @@ import org.typelevel.discipline.scalatest.FlatSpecDiscipline
class ExamplesSuite extends AnyFlatSpec with FlatSpecDiscipline with Configuration {
checkAll("GoldenCodec[Foo]", GoldenCodecTests[Foo](10).goldenCodec)
checkAll("GoldenCodec[Wub]", GoldenCodecTests[Wub].goldenCodec)
// Validate that golden filenames don't collide for type constructors applied
// to different arguments.
checkAll("GoldenCodec[MyList[Foo]]", GoldenCodecTests[MyList[Foo]].goldenCodec)
checkAll("GoldenCodec[MyList[Wub]]", GoldenCodecTests[MyList[Wub]].goldenCodec)

// Validated that deeply nested types are successfully given golden filenames.
checkAll(
"GoldenCodec[MyTuple[MyList[Wub], MyList[MyList[Foo]]]]",
GoldenCodecTests[MyTuple[MyList[Wub], MyList[MyList[Foo]]]].goldenCodec
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@ abstract class ResourceFileGoldenCodecLaws[A](
private[this] val resourceDir: File = resourcePackage.foldLeft(resourceRootDir) {
case (acc, p) => new File(acc, p)
}
private[this] val GoldenFilePattern: Regex = s"^$name-(.{44})\\.json$$".r
private[this] val GoldenFilePattern: Regex = "^-(.{44})\\.json$".r

private[this] lazy val loadGoldenFiles: Try[List[(A, String)]] =
Resources.open(resourceRootPath).flatMap { dirSource =>
val files = dirSource.getLines.flatMap {
case name @ GoldenFilePattern(seed) => Some((seed, name))
case _ => None
case fileName if fileName.startsWith(name) =>
fileName.drop(name.length) match {
case GoldenFilePattern(seed) => Some((seed, fileName))
case _ => None
}
case _ => None
}.toList.traverse[Try, (A, String)] {
case (seed, name) =>
val contents = Resources.open(resourceRootPath + name).map { source =>
Expand Down Expand Up @@ -64,9 +68,7 @@ abstract class ResourceFileGoldenCodecLaws[A](
}

protected lazy val goldenExamples: Try[List[(A, String)]] =
loadGoldenFiles.flatMap { fs =>
if (fs.isEmpty) generateGoldenFiles else loadGoldenFiles
}
loadGoldenFiles.flatMap(fs => if (fs.isEmpty) generateGoldenFiles else loadGoldenFiles)
}

object ResourceFileGoldenCodecLaws {
Expand All @@ -84,8 +86,8 @@ object ResourceFileGoldenCodecLaws {
}

def apply[A](
count: Int,
size: Int
size: Int,
count: Int
)(
implicit decodeA: Decoder[A],
encodeA: Encoder[A],
Expand Down
11 changes: 8 additions & 3 deletions golden/src/main/scala/io/circe/testing/golden/Resources.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package io.circe.testing.golden

import java.io.File
import scala.io.Source
import scala.reflect.runtime.universe.TypeTag
import scala.reflect.runtime.universe.{ Type, TypeTag }
import scala.util.Try

/**
Expand Down Expand Up @@ -36,8 +36,13 @@ object Resources {
/**
* Attempt to guess the name of the type indicated by the provided type tag.
*/
def inferName[A](implicit A: TypeTag[A]): String =
A.tpe.typeSymbol.name.decodedName.toString
def inferName[A](implicit A: TypeTag[A]): String = inferNameForType(A.tpe)

private def inferNameForType(tpe: Type): String = {
val base = tpe.typeSymbol.name.decodedName.toString

(base :: tpe.typeArgs.map(inferNameForType)).mkString("_")
}

def open(path: String): Try[Source] = Try(
Source.fromInputStream(getClass.getResourceAsStream(path))
Expand Down
1 change: 1 addition & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
addSbtPlugin("com.dwijnand" % "sbt-travisci" % "1.2.0")
addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.13")
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.1")
addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.7.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.3")
addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "1.0.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.4.0")
Expand Down