File size: 2,846 Bytes
eae8f62
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// SPDX-License-Identifier: Apache-2.0
package com.laya

import java.io.File
import org.junit.Assert.assertTrue

/** Reads an explicitly supplied fixture bundle without depending on a conversion checkout. */
object LayaTestData {
  private val dataRoot: File by lazy {
    val path =
      requireNotNull(System.getProperty("laya.testData")) {
        "Set LAYA_TEST_DATA to the fixture bundle directory; see scripts/TEST_DATA.md"
      }
    File(path).canonicalFile.also {
      require(File(it, "fixtures").isDirectory) {
        "Missing fixtures: $it; see scripts/TEST_DATA.md"
      }
    }
  }
  val tokenizer: LayaTokenizer by lazy { LayaTokenizer(required("host_assets/tokenizer.json")) }

  fun required(relative: String): File =
    File(dataRoot, relative).also {
      require(it.isFile) { "Required local test fixture is missing: $it" }
    }

  fun read(relative: String): Any? = LayaJson.parse(required(relative))

  fun rows(window: Int): List<Map<String, Any?>> =
    LayaJson.asArray(read("fixtures/ml_rows_s$window.json")).map(LayaJson::asObject)

  fun ints(value: Any?): IntArray =
    LayaJson.asArray(value).map { (it as Number).toInt() }.toIntArray()

  fun floats(value: Any?): FloatArray =
    LayaJson.asArray(value).map { (it as Number).toFloat() }.toFloatArray()

  fun report(name: String, data: Any?) {
    val directory = File(requireNotNull(System.getProperty("laya.testResults")))
    val destination = File(directory, name)
    requireNotNull(destination.parentFile).mkdirs()
    destination.writeText(LayaJson.stringify(data) + "\n", Charsets.UTF_8)
  }

  /** Exact dictionaries, with Python's numeric equality and explicit object insertion order. */
  fun difference(expected: Any?, actual: Any?, path: String = "$"): String? {
    if (expected is Number && actual is Number) {
      return if (expected.toDouble() == actual.toDouble()) null
      else "$path expected=$expected actual=$actual"
    }
    if (expected is Map<*, *> && actual is Map<*, *>) {
      if (expected.keys.toList() != actual.keys.toList())
        return "$path keys expected=${expected.keys} actual=${actual.keys}"
      for (key in expected.keys) difference(expected[key], actual[key], "$path.$key")?.let {
        return it
      }
      return null
    }
    if (expected is List<*> && actual is List<*>) {
      if (expected.size != actual.size)
        return "$path size expected=${expected.size} actual=${actual.size}"
      for (i in expected.indices) difference(expected[i], actual[i], "$path[$i]")?.let {
        return it
      }
      return null
    }
    return if (expected == actual) null else "$path expected=$expected actual=$actual"
  }

  fun assertNoFailures(label: String, failures: List<Map<String, Any?>>) {
    assertTrue("$label: ${failures.size} failures; ${failures.take(8)}", failures.isEmpty())
  }
}