Is it possible to pass two dir files and assert al...
# kotest
j
Is it possible to pass two dir files and assert all files and directories have the same structure and content?
j
Sounds like a fun assertion to write, I'm not sure that it exists though
s
yeah sounds like a useful addition
dir1 shouldHaveSomeStrutureAs dir2
feel free to call it what you want
sameContents sameTree etc
l
we should differentiate between `deep`/`recursive` in a way (maybe an optional parameter) as well
j
Should I file an issue?
I am going to create a PR
👍 1
👍🏻 1
s
val p = Runtime.getRuntime().exec("""reg query "HKU\S-1-5-19"""")
what does that do
j
I called
shouldHaveSameTreeAndContents
to be more explicit, feels free to suggest if I should change it
I don't know, I didn't write that
s
oh lol
you just changed formatting ?
j
maybe that line is appearing because the format was different in one function
s
the name is a touch verbose, what about
shouldHaveSameStructure
?
j
I rename to that 🙂
Done
s
will merge once green
👍 1
j
@sam I checking one documentation website is same than another, I got issues related to the content of the file can be different
\
instead of
/
and so on
so I am doing something like this
Copy code
expectFiles.zip(actualFiles).forEach { (expect, actual) ->
    expect.replaceSlash()
    actual.replaceSlash()
    when {
        expect.extension == "gz" -> println("`.gz` files are ignored")
        expect.extension == "json" -> println("`.gz` files are ignored")
        expect.isDirectory -> actual.shouldBeADirectory()
        expect.isFile -> actual.shouldHaveSameContentAs(actual)
    }
}
s
the filename or the contents of the file ?
j
what do you thing if we add a
transform
lambda and
filter
predicate?
the content inside the file
the gradle plugin I use to generate the content
generates the files differently in windows vs macos
s
the lambdas would work
I didn't realize we were checking file contents
I thought were just checking file tree
j
nono, tree + content
s
I mus have missed that
j
that was the reason I named it
shouldHaveSameTreeAndContents
s
yeah I see now
j
Is this jvm only?
s
yeah
j
yeah
files api is not ready in kmp
j
Should we try to use system.fileseperaror?
s
wanna rename it back 🙂
j
okio is almost there tho
nono
the function is working fine
the merged one
technically the files have different content
s
I think the name same strucutre only makes sense for file names / tree
not actual contents
j
so what should I do?
in my case I was thinking if you see feasible I add another function to bypass those issues
s
I think if we start comparing file contents we're gonna run into all kinds of issues
j
no no, there is no issues with that, only if files are generated or something so
s
ok
I still think it's useful to have an assertion that only checks structure too
j
for example this gradle plugin generates html files with
\
in its content in windows
s
right
j
what do you think about three functions
structure
structure + content
structure + content + transform + filtering
s
yes that works
I like that
j
ie:
fun File.shouldHaveSameStructure(file: File, transform: transform: (T) -> Unit, filter: (T) -> Boolean)
I am going to add them
s
ok
j
Can you use "mutate" instead of transform perhaps?
s
I think transform is a more common name than mutate
j
Huh I deduced what it did from the type, it wasn't clear to me
Also
other: File
s
Actually yeah, what is T ?
j
yeah you have right
should be
s
Do like a ByteArray or something
j
filter (File, File) -> boolean
s
or file
j
in my case, I am filtering all gz files
s
why double file on the filter ?
j
technically you are comparing pairs of files
s
It's a filter, shouldn't it be File -> Boolean
j
probably having only one file is enough, "because they should be the same", but not sure if there is use case where you can filter using the file B instead of file A or viceversa
or even both
i.e. filter { a, b -> a.readLines().size == 1 && b.readLines().size == 2 }
s
I thought the filter function would "normalize" it
if it's actuallying comparing the files then call it compare
j
Copy code
fun File.shouldHaveSameStructure(
  file: File,
  filter: (expect: File, actual: File) -> Boolean
) {
  val expectFiles = this.walkTopDown().toList()
  val actualFiles = file.walkTopDown().toList()

  expectFiles shouldBeSameSizeAs actualFiles

  expectFiles.zip(actualFiles) { expect, actual ->
    when {
      filter(expect, actual) -> {}
      expect.isDirectory -> actual.shouldBeADirectory()
      expect.isFile -> expect shouldHavePath actual.path
      else -> error("There is an unexpected error analyzing file trees")
    }
  }
}
what do you think?
s
I wouldn't call it filter. Filter implies you are filtering things out. Here you are comparing. So I would call it compare, or isEqual or something
👍 1
But other than that, I like
j
techncally, you are filtering that comparison
s
I dunno, it doesn't seem right to me
I know you are filtering the file contents, but I'd never expect a function called filter to compare two things
j
but the function is not comparing, is filtering
one sample
Copy code
fileA.shouldHaveSameStructure(fileB, filter = { a, b -> a.extension == "html" })
s
so what's b doing here ?
you don't use the b arg
j
when it is going to be compared the file a with b, if a is a json, it is filtered
yeah
but you can do different comparison
ie
Copy code
fileA.shouldHaveSameStructure(fileB, filter = { a, b -> a.readlines().size == 2 || b.readlines().size == 5 })
s
you're not filtering anything there. You're applying a predicate to the files.
j
Are we trying to test that two file trees have the same structure ignoring nodes based on some predicate?
j
I am removing from the comparison all files with have those predicates
s
so you are filtering files FROM the comparison ?
If so why can't it just be File -> Boolean
j
it can, but a and b can be different, so maybe there can be use cases where you need both
@Jim both trees are identical, but you can remove from the comparison some files
for example, a tree generated in windows and a tree generated in macos, I want to filter if the file extension is
.gz
what name should I put @sam? compare is weird for me, because I am not comparing, I am comparing and removing from the comparison
j
Yeah so File -> Boolean makes sense here
j
and about the
filter
name?
j
Yeah I think so, it should apply the same filter to both files in the comparison but hide that from the tester I think,
it
instead of
a, b
s
filter is fine if it's File -> Boolean
j
Copy code
fun File.shouldHaveSameStructure(
  file: File,
  filter: (File) -> Boolean
) {
  val expectFiles = this.walkTopDown().toList()
  val actualFiles = file.walkTopDown().toList()

  expectFiles shouldBeSameSizeAs actualFiles

  expectFiles.zip(actualFiles) { expect, actual ->
    when {
      filter(expect) -> {}
      expect.isDirectory -> actual.shouldBeADirectory()
      expect.isFile -> expect shouldHavePath actual.path
      else -> error("There is an unexpected error analyzing file trees")
    }
  }
}
s
if it's File,File -> Boolean then filter is odd
Yep, either
Copy code
fun File.shouldHaveSameStructure(
  file: File,
  filter: (File) -> Boolean
)
or
Copy code
fun File.shouldHaveSameStructure(
  file: File,
  filterLhs: (File) -> Boolean,
  filterRhs: (File-> Boolean,
)
If you really really want to filter the two sides separately
j
I like that
about
transform
, I should do that too?
s
personally, I'd keep it simple for now
can always add more stuff later
j
and about filterLhs and Rhs, should be
&&
or
||
Copy code
filterLhs(expect) && filterRhs(actual) -> {}
s
|| makes sense to me
j
yep
I would like to add the transform one because I need it too, I think it can be useful for codegen files comparison where the file content can vary only in separators or something so
s
Ok then :)
j
should I separate the transform there in two transform functions, or in this case it is better to have only one transform?
s
I don't really have an opinion on that so we can just go with whatver you think is best
j
my use case a and b have different content because the codegen, so I want to transform the files "to be the same" (if really they are the same and only separators are the problem)
I think it should be one
s
Ok that's cool
j
well, technically with the filter functions I can achieve that
well, no, because there is separated
Copy code
fun File.shouldHaveSameStructure(
  file: File,
  filterLhs: (File) -> Boolean,
  filterRhs: (File) -> Boolean,
) {
if I remerge them into one, there is no need to add another with transform
I know understand your
compare
, my head did "tick"
👍🏻 1