Passed first set of builder tests.
This commit is contained in:
@@ -47,6 +47,34 @@ final class SwiftMathRenderTests: XCTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
func getTestData() -> [TestRecord] {
|
||||
[
|
||||
TestRecord(build: "x", atomType: [.variable ], types: [], result: "x"),
|
||||
TestRecord(build: "1", atomType: [.number ] , types: [], result: "1"),
|
||||
TestRecord(build: "*", atomType: [.binaryOperator ] ,types: [], result:"*"),
|
||||
TestRecord(build: "+", atomType: [.binaryOperator ], types: [], result:"+"),
|
||||
TestRecord(build: ".", atomType: [.number ], types: [], result:"."),
|
||||
TestRecord(build: "(", atomType: [.open ], types: [], result:"(" ),
|
||||
TestRecord(build: ")", atomType: [.close ], types: [], result:")"),
|
||||
TestRecord(build: ",", atomType: [.punctuation], types: [], result:","),
|
||||
TestRecord(build: "!", atomType: [.close], types: [], result:"!"),
|
||||
TestRecord(build: "=", atomType: [.relation], types: [], result:"="),
|
||||
TestRecord(build: "x+2", atomType: [.variable, .binaryOperator, .number ], types: [], result:"x+2"),
|
||||
// spaces are ignored
|
||||
TestRecord(build: "(2.3 * 8)", atomType: [.open, .number, .number, .number, .binaryOperator, .number , .close ], types: [], result:"(2.3*8)"),
|
||||
// braces are just for grouping
|
||||
TestRecord(build: "5{3+4}", atomType: [.number, .number, .binaryOperator, .number], types: [], result:"53+4"),
|
||||
// commands
|
||||
TestRecord(build: "\\pi+\\theta\\geq 3",atomType: [.variable, .binaryOperator, .variable, .relation, .number], types: [], result:"\\pi +\\theta \\geq 3"),
|
||||
// aliases
|
||||
TestRecord(build: "\\pi\\ne 5 \\land 3", atomType: [.variable, .relation, .number, .binaryOperator, .number], types: [], result:"\\pi \\neq 5\\wedge 3"),
|
||||
// control space
|
||||
TestRecord(build: "x \\ y", atomType: [ .variable, .ordinary, .variable], types: [], result:"x\\ y"),
|
||||
// spacing
|
||||
TestRecord(build: "x \\quad y \\; z \\! q", atomType: [ .variable, .space, .variable,.space, .variable, .space, .variable], types: [], result:"x\\quad y\\; z\\! q")
|
||||
]
|
||||
}
|
||||
|
||||
func getTestDataSuperScript() -> [TestRecord] {
|
||||
[
|
||||
TestRecord(build: "x^2", atomType: [.variable], types: [.number], result: "x^{2}"),
|
||||
@@ -124,14 +152,69 @@ final class SwiftMathRenderTests: XCTestCase {
|
||||
TestRecord2(build: "\\left( 2 \\right.", type1: [ .inner], number: 0, type2: [ .number], left: "(", right: "", result: "\\left( 2\\right. ")
|
||||
]
|
||||
}
|
||||
|
||||
func getTestDataParseErrors() -> [(String, MTParseErrors)] {
|
||||
return [
|
||||
("}a", .mismatchBraces),
|
||||
("\\notacommand", .invalidCommand),
|
||||
("\\sqrt[5+3", .characterNotFound),
|
||||
("{5+3", .mismatchBraces),
|
||||
("5+3}", .mismatchBraces),
|
||||
("{1+\\frac{3+2", .mismatchBraces),
|
||||
("1+\\left", .missingDelimiter),
|
||||
("\\left(\\frac12\\right", .missingDelimiter),
|
||||
("\\left 5 + 3 \\right)", .invalidDelimiter),
|
||||
("\\left(\\frac12\\right + 3", .invalidDelimiter),
|
||||
("\\left\\lmoustache 5 + 3 \\right)", .invalidDelimiter),
|
||||
("\\left(\\frac12\\right\\rmoustache + 3", .invalidDelimiter),
|
||||
("5 + 3 \\right)", .missingLeft),
|
||||
("\\left(\\frac12", .missingRight),
|
||||
("\\left(5 + \\left| \\frac12 \\right)", .missingRight),
|
||||
("5+ \\left|\\frac12\\right| \\right)", .missingLeft),
|
||||
("\\begin matrix \\end matrix", .characterNotFound), // missing {
|
||||
("\\begin", .characterNotFound), // missing {
|
||||
("\\begin{", .characterNotFound), // missing }
|
||||
("\\begin{matrix parens}", .characterNotFound), // missing } (no spaces in env)
|
||||
("\\begin{matrix} x", .missingEnd),
|
||||
("\\begin{matrix} x \\end", .characterNotFound), // missing {
|
||||
("\\begin{matrix} x \\end + 3", .characterNotFound), // missing {
|
||||
("\\begin{matrix} x \\end{", .characterNotFound), // missing }
|
||||
("\\begin{matrix} x \\end{matrix + 3", .characterNotFound), // missing }
|
||||
("\\begin{matrix} x \\end{pmatrix}", .invalidEnv),
|
||||
("x \\end{matrix}", .missingBegin),
|
||||
("\\begin{notanenv} x \\end{notanenv}", .invalidEnv),
|
||||
("\\begin{matrix} \\notacommand \\end{matrix}", .invalidCommand),
|
||||
("\\begin{displaylines} x & y \\end{displaylines}", .invalidNumColumns),
|
||||
("\\begin{eqalign} x \\end{eqalign}", .invalidNumColumns),
|
||||
("\\nolimits", .invalidLimits),
|
||||
("\\frac\\limits{1}{2}", .invalidLimits)
|
||||
]
|
||||
}
|
||||
|
||||
func testBuilder() throws {
|
||||
let data = getTestData()
|
||||
for testCase in data {
|
||||
let str = testCase.build
|
||||
var error = NSError()
|
||||
let list = MTMathListBuilder.build(fromString: str, error: &error)
|
||||
XCTAssert(error.code == 0)
|
||||
let desc = "Error for string:\(str)"
|
||||
let atomTypes = testCase.atomType
|
||||
self.checkAtomTypes(list, types:atomTypes, desc:desc)
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, testCase.result, desc)
|
||||
}
|
||||
}
|
||||
|
||||
func testSuperScript() throws {
|
||||
let data = getTestDataSuperScript()
|
||||
for testCase in data {
|
||||
let str = testCase.build
|
||||
var error:NSError?
|
||||
var error = NSError()
|
||||
let list = MTMathListBuilder.build(fromString: str, error:&error)
|
||||
XCTAssertNil(error)
|
||||
XCTAssert(error.code == NSNotFound)
|
||||
let desc = "Error for string:\(str)"
|
||||
let atomTypes = testCase.atomType
|
||||
checkAtomTypes(list, types:atomTypes, desc:desc)
|
||||
@@ -163,9 +246,9 @@ final class SwiftMathRenderTests: XCTestCase {
|
||||
let data = getTestDataSubScript()
|
||||
for testCase in data {
|
||||
let str = testCase.build
|
||||
var error:NSError?
|
||||
var error = NSError()
|
||||
let list = MTMathListBuilder.build(fromString: str, error:&error)
|
||||
XCTAssertNil(error)
|
||||
XCTAssert(error.code == NSNotFound)
|
||||
let desc = "Error for string:\(str)"
|
||||
let atomTypes = testCase.atomType
|
||||
checkAtomTypes(list, types:atomTypes, desc:desc)
|
||||
@@ -197,9 +280,9 @@ final class SwiftMathRenderTests: XCTestCase {
|
||||
let data = getTestDataSuperSubScript()
|
||||
for testCase in data {
|
||||
let str = testCase.build
|
||||
var error:NSError?
|
||||
var error = NSError()
|
||||
let list = MTMathListBuilder.build(fromString: str, error:&error)
|
||||
XCTAssertNil(error)
|
||||
XCTAssert(error.code == NSNotFound)
|
||||
let desc = "Error for string:\(str)"
|
||||
let atomTypes = testCase.atomType
|
||||
checkAtomTypes(list, types:atomTypes, desc:desc)
|
||||
@@ -425,7 +508,7 @@ final class SwiftMathRenderTests: XCTestCase {
|
||||
for testCase in data {
|
||||
let str = testCase.build
|
||||
|
||||
var error:NSError?
|
||||
var error = NSError()
|
||||
let list = MTMathListBuilder.build(fromString: str, error: &error)!
|
||||
|
||||
XCTAssertNotNil(list, str);
|
||||
@@ -455,7 +538,825 @@ final class SwiftMathRenderTests: XCTestCase {
|
||||
XCTAssertEqual(latex, testCase.result, str);
|
||||
}
|
||||
}
|
||||
|
||||
func testOver() throws {
|
||||
let str = "1 \\over c";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc);
|
||||
XCTAssertEqual((list.atoms.count), 1, desc);
|
||||
let frac = list.atoms[0] as! MTFraction
|
||||
XCTAssertEqual(frac.type, .fraction, desc);
|
||||
XCTAssertEqual(frac.nucleus, "", desc);
|
||||
XCTAssertTrue(frac.hasRule);
|
||||
XCTAssertNil(frac.rightDelimiter);
|
||||
XCTAssertNil(frac.leftDelimiter);
|
||||
|
||||
var subList = frac.numerator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
var atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .number, desc);
|
||||
XCTAssertEqual(atom.nucleus, "1", desc);
|
||||
|
||||
atom = list.atoms[0];
|
||||
subList = frac.denominator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc);
|
||||
XCTAssertEqual(atom.nucleus, "c", desc);
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\frac{1}{c}", desc);
|
||||
}
|
||||
|
||||
func testOverInParens() throws {
|
||||
let str = "5 + {1 \\over c} + 8";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc);
|
||||
XCTAssertEqual((list.atoms.count), 5, desc);
|
||||
let types = [MTMathAtomType.number, .binaryOperator, .fraction, .binaryOperator, .number]
|
||||
self.checkAtomTypes(list, types:types, desc:desc)
|
||||
|
||||
let frac = list.atoms[2] as! MTFraction
|
||||
XCTAssertEqual(frac.type, .fraction, desc);
|
||||
XCTAssertEqual(frac.nucleus, "", desc);
|
||||
XCTAssertTrue(frac.hasRule);
|
||||
XCTAssertNil(frac.rightDelimiter);
|
||||
XCTAssertNil(frac.leftDelimiter);
|
||||
|
||||
var subList = frac.numerator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
var atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .number, desc);
|
||||
XCTAssertEqual(atom.nucleus, "1", desc);
|
||||
|
||||
atom = list.atoms[0];
|
||||
subList = frac.denominator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc);
|
||||
XCTAssertEqual(atom.nucleus, "c", desc);
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "5+\\frac{1}{c}+8", desc);
|
||||
}
|
||||
|
||||
func testAtop() throws {
|
||||
let str = "1 \\atop c";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc);
|
||||
XCTAssertEqual((list.atoms.count), 1, desc);
|
||||
let frac = list.atoms[0] as! MTFraction
|
||||
XCTAssertEqual(frac.type, .fraction, desc);
|
||||
XCTAssertEqual(frac.nucleus, "", desc);
|
||||
XCTAssertFalse(frac.hasRule);
|
||||
XCTAssertNil(frac.rightDelimiter);
|
||||
XCTAssertNil(frac.leftDelimiter);
|
||||
|
||||
var subList = frac.numerator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
var atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .number, desc);
|
||||
XCTAssertEqual(atom.nucleus, "1", desc);
|
||||
|
||||
atom = list.atoms[0];
|
||||
subList = frac.denominator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc);
|
||||
XCTAssertEqual(atom.nucleus, "c", desc);
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "{1 \\atop c}", desc);
|
||||
}
|
||||
|
||||
func testAtopInParens() throws {
|
||||
let str = "5 + {1 \\atop c} + 8";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc);
|
||||
XCTAssertEqual((list.atoms.count), 5, desc);
|
||||
let types = [MTMathAtomType.number, .binaryOperator, .fraction, .binaryOperator, .number]
|
||||
self.checkAtomTypes(list, types:types, desc:desc)
|
||||
|
||||
let frac = list.atoms[2] as! MTFraction
|
||||
XCTAssertEqual(frac.type, .fraction, desc);
|
||||
XCTAssertEqual(frac.nucleus, "", desc);
|
||||
XCTAssertFalse(frac.hasRule);
|
||||
XCTAssertNil(frac.rightDelimiter);
|
||||
XCTAssertNil(frac.leftDelimiter);
|
||||
|
||||
var subList = frac.numerator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
var atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .number, desc);
|
||||
XCTAssertEqual(atom.nucleus, "1", desc);
|
||||
|
||||
atom = list.atoms[0];
|
||||
subList = frac.denominator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc);
|
||||
XCTAssertEqual(atom.nucleus, "c", desc);
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "5+{1 \\atop c}+8", desc);
|
||||
}
|
||||
|
||||
func testChoose() throws {
|
||||
let str = "n \\choose k";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc);
|
||||
XCTAssertEqual((list.atoms.count), 1, desc);
|
||||
let frac = list.atoms[0] as! MTFraction
|
||||
XCTAssertEqual(frac.type, .fraction, desc);
|
||||
XCTAssertEqual(frac.nucleus, "", desc);
|
||||
XCTAssertFalse(frac.hasRule);
|
||||
XCTAssertEqual(frac.rightDelimiter, ")");
|
||||
XCTAssertEqual(frac.leftDelimiter, "(");
|
||||
|
||||
var subList = frac.numerator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
var atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc);
|
||||
XCTAssertEqual(atom.nucleus, "n", desc);
|
||||
|
||||
atom = list.atoms[0];
|
||||
subList = frac.denominator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc);
|
||||
XCTAssertEqual(atom.nucleus, "k", desc);
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "{n \\choose k}", desc);
|
||||
}
|
||||
|
||||
func testBrack() throws {
|
||||
let str = "n \\brack k";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc);
|
||||
XCTAssertEqual((list.atoms.count), 1, desc);
|
||||
let frac = list.atoms[0] as! MTFraction
|
||||
XCTAssertEqual(frac.type, .fraction, desc);
|
||||
XCTAssertEqual(frac.nucleus, "", desc);
|
||||
XCTAssertFalse(frac.hasRule);
|
||||
XCTAssertEqual(frac.rightDelimiter, "]");
|
||||
XCTAssertEqual(frac.leftDelimiter, "[");
|
||||
|
||||
var subList = frac.numerator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
var atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc);
|
||||
XCTAssertEqual(atom.nucleus, "n", desc);
|
||||
|
||||
atom = list.atoms[0];
|
||||
subList = frac.denominator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc);
|
||||
XCTAssertEqual(atom.nucleus, "k", desc);
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "{n \\brack k}", desc);
|
||||
}
|
||||
|
||||
func testBrace() throws {
|
||||
let str = "n \\brace k";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc);
|
||||
XCTAssertEqual((list.atoms.count), 1, desc);
|
||||
let frac = list.atoms[0] as! MTFraction
|
||||
XCTAssertEqual(frac.type, .fraction, desc);
|
||||
XCTAssertEqual(frac.nucleus, "", desc);
|
||||
XCTAssertFalse(frac.hasRule);
|
||||
XCTAssertEqual(frac.rightDelimiter, "}");
|
||||
XCTAssertEqual(frac.leftDelimiter, "{");
|
||||
|
||||
var subList = frac.numerator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
var atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc);
|
||||
XCTAssertEqual(atom.nucleus, "n", desc);
|
||||
|
||||
atom = list.atoms[0];
|
||||
subList = frac.denominator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc);
|
||||
XCTAssertEqual(atom.nucleus, "k", desc);
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "{n \\brace k}", desc);
|
||||
}
|
||||
|
||||
func testBinom() throws {
|
||||
let str = "\\binom{n}{k}";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc);
|
||||
XCTAssertEqual((list.atoms.count), 1, desc);
|
||||
let frac = list.atoms[0] as! MTFraction
|
||||
XCTAssertEqual(frac.type, .fraction, desc);
|
||||
XCTAssertEqual(frac.nucleus, "", desc);
|
||||
XCTAssertFalse(frac.hasRule);
|
||||
XCTAssertEqual(frac.rightDelimiter, ")");
|
||||
XCTAssertEqual(frac.leftDelimiter, "(");
|
||||
|
||||
var subList = frac.numerator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
var atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc);
|
||||
XCTAssertEqual(atom.nucleus, "n", desc);
|
||||
|
||||
atom = list.atoms[0];
|
||||
subList = frac.denominator!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc);
|
||||
XCTAssertEqual(atom.nucleus, "k", desc);
|
||||
|
||||
// convert it back to latex (binom converts to choose)
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "{n \\choose k}", desc);
|
||||
}
|
||||
|
||||
func testOverLine() throws {
|
||||
let str = "\\overline 2";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc);
|
||||
XCTAssertEqual((list.atoms.count), 1, desc);
|
||||
let over = list.atoms[0] as! MTOverLine
|
||||
XCTAssertEqual(over.type, .overline, desc);
|
||||
XCTAssertEqual(over.nucleus, "", desc);
|
||||
|
||||
let subList = over.innerList!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
let atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .number, desc);
|
||||
XCTAssertEqual(atom.nucleus, "2", desc);
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\overline{2}", desc);
|
||||
}
|
||||
|
||||
func testUnderline() throws {
|
||||
let str = "\\underline 2";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc);
|
||||
XCTAssertEqual((list.atoms.count), 1, desc);
|
||||
let under = list.atoms[0] as! MTUnderLine
|
||||
XCTAssertEqual(under.type, .underline, desc);
|
||||
XCTAssertEqual(under.nucleus, "", desc);
|
||||
|
||||
let subList = under.innerList!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
let atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .number, desc);
|
||||
XCTAssertEqual(atom.nucleus, "2", desc);
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\underline{2}", desc);
|
||||
}
|
||||
|
||||
func testAccent() throws {
|
||||
let str = "\\bar x";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc);
|
||||
XCTAssertEqual((list.atoms.count), 1, desc);
|
||||
let accent = list.atoms[0] as! MTAccent
|
||||
XCTAssertEqual(accent.type, .accent, desc);
|
||||
XCTAssertEqual(accent.nucleus, "\u{0304}", desc);
|
||||
|
||||
let subList = accent.innerList!
|
||||
XCTAssertNotNil(subList, desc);
|
||||
XCTAssertEqual((subList.atoms.count), 1, desc);
|
||||
let atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc);
|
||||
XCTAssertEqual(atom.nucleus, "x", desc);
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\bar{x}", desc);
|
||||
}
|
||||
|
||||
func testMathSpace() throws {
|
||||
let str = "\\!";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc);
|
||||
XCTAssertEqual((list.atoms.count), 1, desc);
|
||||
let space = list.atoms[0] as! MTMathSpace
|
||||
XCTAssertEqual(space.type, .space, desc);
|
||||
XCTAssertEqual(space.nucleus, "", desc);
|
||||
XCTAssertEqual(space.space, -3);
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\! ", desc);
|
||||
}
|
||||
|
||||
func testMathStyle() throws {
|
||||
let str = "\\textstyle y \\scriptstyle x";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc);
|
||||
XCTAssertEqual((list.atoms.count), 4, desc);
|
||||
let style = list.atoms[0] as! MTMathStyle
|
||||
XCTAssertEqual(style.type, .style, desc);
|
||||
XCTAssertEqual(style.nucleus, "", desc);
|
||||
XCTAssertEqual(style.style, .text);
|
||||
|
||||
let style2 = list.atoms[2] as! MTMathStyle
|
||||
XCTAssertEqual(style2.type, .style, desc);
|
||||
XCTAssertEqual(style2.nucleus, "", desc);
|
||||
XCTAssertEqual(style2.style, .script);
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\textstyle y\\scriptstyle x", desc);
|
||||
}
|
||||
|
||||
func testMatrix() throws {
|
||||
let str = "\\begin{matrix} x & y \\\\ z & w \\end{matrix}";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
|
||||
XCTAssertNotNil(list);
|
||||
XCTAssertEqual((list.atoms.count), 1);
|
||||
let table = list.atoms[0] as! MTMathTable
|
||||
XCTAssertEqual(table.type, .table);
|
||||
XCTAssertEqual(table.nucleus, "");
|
||||
XCTAssertEqual(table.environment, "matrix");
|
||||
XCTAssertEqual(table.interRowAdditionalSpacing, 0);
|
||||
XCTAssertEqual(table.interColumnSpacing, 18);
|
||||
XCTAssertEqual(table.numRows, 2);
|
||||
XCTAssertEqual(table.numColumns, 2);
|
||||
|
||||
for i in 0..<2 {
|
||||
let alignment = table.get(alignmentForColumn:i)
|
||||
XCTAssertEqual(alignment, .center);
|
||||
for j in 0..<2 {
|
||||
let cell = table.cells[j][i];
|
||||
XCTAssertEqual(cell.atoms.count, 2);
|
||||
let style = cell.atoms[0] as! MTMathStyle
|
||||
XCTAssertEqual(style.type, .style);
|
||||
XCTAssertEqual(style.style, .text);
|
||||
|
||||
let atom = cell.atoms[1];
|
||||
XCTAssertEqual(atom.type, .variable);
|
||||
}
|
||||
}
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\begin{matrix}x&y\\\\ z&w\\end{matrix}");
|
||||
}
|
||||
|
||||
func testPMatrix() throws {
|
||||
let str = "\\begin{pmatrix} x & y \\\\ z & w \\end{pmatrix}";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
|
||||
XCTAssertNotNil(list);
|
||||
XCTAssertEqual((list.atoms.count), 1);
|
||||
let inner = list.atoms[0] as! MTInner
|
||||
XCTAssertEqual(inner.type, .inner, str);
|
||||
XCTAssertEqual(inner.nucleus, "", str);
|
||||
|
||||
let innerList = inner.innerList!
|
||||
XCTAssertNotNil(innerList, str);
|
||||
|
||||
XCTAssertNotNil(inner.leftBoundary, str);
|
||||
XCTAssertEqual(inner.leftBoundary!.type, .boundary, str);
|
||||
XCTAssertEqual(inner.leftBoundary!.nucleus, "(", str);
|
||||
|
||||
XCTAssertNotNil(inner.rightBoundary, str);
|
||||
XCTAssertEqual(inner.rightBoundary!.type, .boundary, str);
|
||||
XCTAssertEqual(inner.rightBoundary!.nucleus, ")", str);
|
||||
|
||||
XCTAssertEqual((innerList.atoms.count), 1);
|
||||
let table = innerList.atoms[0] as! MTMathTable
|
||||
XCTAssertEqual(table.type, .table);
|
||||
XCTAssertEqual(table.nucleus, "");
|
||||
XCTAssertEqual(table.environment, "matrix");
|
||||
XCTAssertEqual(table.interRowAdditionalSpacing, 0);
|
||||
XCTAssertEqual(table.interColumnSpacing, 18);
|
||||
XCTAssertEqual(table.numRows, 2);
|
||||
XCTAssertEqual(table.numColumns, 2);
|
||||
|
||||
for i in 0..<2 {
|
||||
let alignment = table.get(alignmentForColumn:i)
|
||||
XCTAssertEqual(alignment, .center);
|
||||
for j in 0..<2 {
|
||||
let cell = table.cells[j][i];
|
||||
XCTAssertEqual(cell.atoms.count, 2);
|
||||
let style = cell.atoms[0] as! MTMathStyle
|
||||
XCTAssertEqual(style.type, .style);
|
||||
XCTAssertEqual(style.style, .text);
|
||||
|
||||
let atom = cell.atoms[1];
|
||||
XCTAssertEqual(atom.type, .variable);
|
||||
}
|
||||
}
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\left( \\begin{matrix}x&y\\\\ z&w\\end{matrix}\\right) ");
|
||||
}
|
||||
|
||||
func testDefaultTable() throws {
|
||||
let str = "x \\\\ y";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
|
||||
XCTAssertNotNil(list);
|
||||
XCTAssertEqual(list.atoms.count, 1);
|
||||
let table = list.atoms[0] as! MTMathTable
|
||||
XCTAssertEqual(table.type, .table);
|
||||
XCTAssertEqual(table.nucleus, "");
|
||||
XCTAssertNil(table.environment);
|
||||
XCTAssertEqual(table.interRowAdditionalSpacing, 1);
|
||||
XCTAssertEqual(table.interColumnSpacing, 0);
|
||||
XCTAssertEqual(table.numRows, 2);
|
||||
XCTAssertEqual(table.numColumns, 1);
|
||||
|
||||
for i in 0..<1 {
|
||||
let alignment = table.get(alignmentForColumn: i)
|
||||
XCTAssertEqual(alignment, .left);
|
||||
for j in 0..<2 {
|
||||
let cell = table.cells[j][i];
|
||||
XCTAssertEqual(cell.atoms.count, 1);
|
||||
let atom = cell.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable);
|
||||
}
|
||||
}
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "x\\\\ y");
|
||||
}
|
||||
|
||||
func testDefaultTableWithCols() throws {
|
||||
let str = "x & y \\\\ z & w";
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
|
||||
XCTAssertNotNil(list);
|
||||
XCTAssertEqual((list.atoms.count), 1);
|
||||
let table = list.atoms[0] as! MTMathTable
|
||||
XCTAssertEqual(table.type, .table);
|
||||
XCTAssertEqual(table.nucleus, "");
|
||||
XCTAssertNil(table.environment);
|
||||
XCTAssertEqual(table.interRowAdditionalSpacing, 1);
|
||||
XCTAssertEqual(table.interColumnSpacing, 0);
|
||||
XCTAssertEqual(table.numRows, 2);
|
||||
XCTAssertEqual(table.numColumns, 2);
|
||||
|
||||
for i in 0..<2 {
|
||||
let alignment = table.get(alignmentForColumn:i)
|
||||
XCTAssertEqual(alignment, .left);
|
||||
for j in 0..<2 {
|
||||
let cell = table.cells[j][i];
|
||||
XCTAssertEqual(cell.atoms.count, 1);
|
||||
let atom = cell.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable);
|
||||
}
|
||||
}
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "x&y\\\\ z&w");
|
||||
}
|
||||
|
||||
func testEqalign() throws {
|
||||
let str1 = "\\begin{eqalign}x&y\\\\ z&w\\end{eqalign}";
|
||||
let str2 = "\\begin{split}x&y\\\\ z&w\\end{split}";
|
||||
let str3 = "\\begin{aligned}x&y\\\\ z&w\\end{aligned}";
|
||||
for str in [str1, str2, str3] {
|
||||
let list = MTMathListBuilder.build(fromString:str)!
|
||||
|
||||
XCTAssertNotNil(list);
|
||||
XCTAssertEqual((list.atoms.count), 1);
|
||||
let table = list.atoms[0] as! MTMathTable
|
||||
XCTAssertEqual(table.type, .table);
|
||||
XCTAssertEqual(table.nucleus, "");
|
||||
XCTAssertEqual(table.interRowAdditionalSpacing, 1);
|
||||
XCTAssertEqual(table.interColumnSpacing, 0);
|
||||
XCTAssertEqual(table.numRows, 2);
|
||||
XCTAssertEqual(table.numColumns, 2);
|
||||
|
||||
for i in 0..<2 {
|
||||
let alignment = table.get(alignmentForColumn:i)
|
||||
XCTAssertEqual(alignment, (i == 0) ? .right: .left);
|
||||
for j in 0..<2 {
|
||||
let cell = table.cells[j][i];
|
||||
if (i == 0) {
|
||||
XCTAssertEqual(cell.atoms.count, 1);
|
||||
let atom = cell.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable);
|
||||
} else {
|
||||
XCTAssertEqual(cell.atoms.count, 2);
|
||||
self.checkAtomTypes(cell, types:[.ordinary, .variable], desc:str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, str);
|
||||
}
|
||||
}
|
||||
|
||||
func testDisplayLines() throws {
|
||||
let str1 = "\\begin{displaylines}x\\\\ y\\end{displaylines}";
|
||||
let str2 = "\\begin{gather}x\\\\ y\\end{gather}";
|
||||
for str in [str1, str2] {
|
||||
let list = MTMathListBuilder.build(fromString:str)
|
||||
|
||||
XCTAssertNotNil(list)
|
||||
XCTAssertEqual(list?.atoms.count, 1);
|
||||
let table = list?.atoms[0] as! MTMathTable
|
||||
XCTAssertEqual(table.type, .table);
|
||||
XCTAssertEqual(table.nucleus, "");
|
||||
XCTAssertEqual(table.interRowAdditionalSpacing, 1);
|
||||
XCTAssertEqual(table.interColumnSpacing, 0);
|
||||
XCTAssertEqual(table.numRows, 2);
|
||||
XCTAssertEqual(table.numColumns, 1);
|
||||
|
||||
for i in 0..<1 {
|
||||
let alignment = table.get(alignmentForColumn:i)
|
||||
XCTAssertEqual(alignment, .center);
|
||||
for j in 0..<2 {
|
||||
let cell = table.cells[j][i];
|
||||
XCTAssertEqual(cell.atoms.count, 1);
|
||||
let atom = cell.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable);
|
||||
}
|
||||
}
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, str);
|
||||
}
|
||||
}
|
||||
|
||||
func testErrors() throws {
|
||||
let data = getTestDataParseErrors()
|
||||
for testCase in data {
|
||||
let str = testCase.0
|
||||
var error = NSError()
|
||||
let list = MTMathListBuilder.build(fromString: str, error:&error)
|
||||
let desc = "Error for string:\(str)"
|
||||
XCTAssertNil(list, desc)
|
||||
XCTAssertNotNil(error, desc)
|
||||
XCTAssertEqual(error.domain, MTParseError, desc)
|
||||
let num = testCase.1
|
||||
let code = num.rawValue
|
||||
XCTAssertEqual(error.code, code, desc)
|
||||
}
|
||||
}
|
||||
|
||||
func testCustom() throws {
|
||||
let str = "\\lcm(a,b)";
|
||||
var error = NSError()
|
||||
var list = MTMathListBuilder.build(fromString: str, error:&error)
|
||||
XCTAssertNil(list);
|
||||
XCTAssert(error.code == NSNotFound)
|
||||
|
||||
MTMathAtomFactory.add(latexSymbol: "lcm", value: MTMathAtomFactory.operatorWithName("lcm", limits:false))
|
||||
list = MTMathListBuilder.build(fromString: str, error:&error)
|
||||
let atomTypes = [MTMathAtomType.largeOperator, .open, .variable, .punctuation, .variable, .close]
|
||||
self.checkAtomTypes(list, types:atomTypes, desc:"Error for lcm")
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\lcm (a,b)");
|
||||
}
|
||||
|
||||
func testFontSingle() throws {
|
||||
let str = "\\mathbf x";
|
||||
let list = MTMathListBuilder.build(fromString: str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc)
|
||||
XCTAssertEqual(list.atoms.count, 1, desc)
|
||||
let atom = list.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc)
|
||||
XCTAssertEqual(atom.nucleus, "x", desc)
|
||||
XCTAssertEqual(atom.fontStyle, .bold)
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\mathbf{x}", desc)
|
||||
}
|
||||
|
||||
func testFontOneChar() throws {
|
||||
let str = "\\cal xy";
|
||||
let list = MTMathListBuilder.build(fromString: str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc)
|
||||
XCTAssertEqual((list.atoms.count), 2, desc)
|
||||
var atom = list.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc)
|
||||
XCTAssertEqual(atom.nucleus, "x", desc)
|
||||
XCTAssertEqual(atom.fontStyle, .caligraphic);
|
||||
|
||||
atom = list.atoms[1];
|
||||
XCTAssertEqual(atom.type, .variable, desc)
|
||||
XCTAssertEqual(atom.nucleus, "y", desc)
|
||||
XCTAssertEqual(atom.fontStyle, .defaultStyle);
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\mathcal{x}y", desc)
|
||||
}
|
||||
|
||||
func testFontMultipleChars() throws {
|
||||
let str = "\\frak{xy}";
|
||||
let list = MTMathListBuilder.build(fromString: str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc)
|
||||
XCTAssertEqual((list.atoms.count), 2, desc)
|
||||
var atom = list.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc)
|
||||
XCTAssertEqual(atom.nucleus, "x", desc)
|
||||
XCTAssertEqual(atom.fontStyle, .fraktur);
|
||||
|
||||
atom = list.atoms[1];
|
||||
XCTAssertEqual(atom.type, .variable, desc)
|
||||
XCTAssertEqual(atom.nucleus, "y", desc)
|
||||
XCTAssertEqual(atom.fontStyle, .fraktur);
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\mathfrak{xy}", desc)
|
||||
}
|
||||
|
||||
func testFontOneCharInside() throws {
|
||||
let str = "\\sqrt \\mathrm x y";
|
||||
let list = MTMathListBuilder.build(fromString: str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc)
|
||||
XCTAssertEqual((list.atoms.count), 2, desc)
|
||||
|
||||
let rad = list.atoms[0] as! MTRadical
|
||||
XCTAssertEqual(rad.type, .radical, desc)
|
||||
XCTAssertEqual(rad.nucleus, "", desc)
|
||||
|
||||
let subList = rad.radicand!
|
||||
var atom = subList.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc)
|
||||
XCTAssertEqual(atom.nucleus, "x", desc)
|
||||
XCTAssertEqual(atom.fontStyle, .roman);
|
||||
|
||||
atom = list.atoms[1];
|
||||
XCTAssertEqual(atom.type, .variable, desc)
|
||||
XCTAssertEqual(atom.nucleus, "y", desc)
|
||||
XCTAssertEqual(atom.fontStyle, .defaultStyle)
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\sqrt{\\mathrm{x}}y", desc)
|
||||
}
|
||||
|
||||
func testText() throws {
|
||||
let str = "\\text{x y}";
|
||||
let list = MTMathListBuilder.build(fromString: str)!
|
||||
let desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc)
|
||||
XCTAssertEqual((list.atoms.count), 3, desc)
|
||||
var atom = list.atoms[0];
|
||||
XCTAssertEqual(atom.type, .variable, desc)
|
||||
XCTAssertEqual(atom.nucleus, "x", desc)
|
||||
XCTAssertEqual(atom.fontStyle, .roman);
|
||||
|
||||
atom = list.atoms[1];
|
||||
XCTAssertEqual(atom.type, .ordinary, desc)
|
||||
XCTAssertEqual(atom.nucleus, " ", desc)
|
||||
|
||||
atom = list.atoms[2];
|
||||
XCTAssertEqual(atom.type, .variable, desc)
|
||||
XCTAssertEqual(atom.nucleus, "y", desc)
|
||||
XCTAssertEqual(atom.fontStyle, .roman);
|
||||
|
||||
|
||||
// convert it back to latex
|
||||
let latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\mathrm{x\\ y}", desc)
|
||||
}
|
||||
|
||||
func testLimits() throws {
|
||||
// Int with no limits (default)
|
||||
var str = "\\int";
|
||||
var list = MTMathListBuilder.build(fromString: str)!
|
||||
var desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc)
|
||||
XCTAssertEqual((list.atoms.count), 1, desc)
|
||||
var op = list.atoms[0] as! MTLargeOperator
|
||||
XCTAssertEqual(op.type, .largeOperator, desc)
|
||||
XCTAssertFalse(op.limits);
|
||||
|
||||
// convert it back to latex
|
||||
var latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\int ", desc)
|
||||
|
||||
// Int with limits
|
||||
str = "\\int\\limits"
|
||||
list = MTMathListBuilder.build(fromString: str)!
|
||||
desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc)
|
||||
XCTAssertEqual((list.atoms.count), 1, desc)
|
||||
op = list.atoms[0] as! MTLargeOperator
|
||||
XCTAssertEqual(op.type, .largeOperator, desc)
|
||||
XCTAssertTrue(op.limits);
|
||||
|
||||
// convert it back to latex
|
||||
latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\int \\limits ", desc)
|
||||
}
|
||||
|
||||
func testNoLimits() throws {
|
||||
// Sum with limits (default)
|
||||
var str = "\\sum";
|
||||
var list = MTMathListBuilder.build(fromString: str)!
|
||||
var desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc)
|
||||
XCTAssertEqual((list.atoms.count), 1, desc)
|
||||
var op = list.atoms[0] as! MTLargeOperator
|
||||
XCTAssertEqual(op.type, .largeOperator, desc)
|
||||
XCTAssertTrue(op.limits);
|
||||
|
||||
// convert it back to latex
|
||||
var latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\sum ", desc)
|
||||
|
||||
// Int with limits
|
||||
str = "\\sum\\nolimits";
|
||||
list = MTMathListBuilder.build(fromString: str)!
|
||||
desc = "Error for string:\(str)"
|
||||
|
||||
XCTAssertNotNil(list, desc)
|
||||
XCTAssertEqual(list.atoms.count, 1, desc)
|
||||
op = list.atoms[0] as! MTLargeOperator
|
||||
XCTAssertEqual(op.type, .largeOperator, desc)
|
||||
XCTAssertFalse(op.limits);
|
||||
|
||||
// convert it back to latex
|
||||
latex = MTMathListBuilder.mathListToString(list)
|
||||
XCTAssertEqual(latex, "\\sum \\nolimits ", desc)
|
||||
}
|
||||
|
||||
// func testPerformanceExample() throws {
|
||||
// // This is an example of a performance test case.
|
||||
|
||||
Reference in New Issue
Block a user