From 4a323b21ce36c7e9a7206fe4dcae96335efe293e Mon Sep 17 00:00:00 2001
From: Danielku15 <danielku15@coderline.net>
Date: Tue, 1 Nov 2022 13:53:29 +0100
Subject: [PATCH 1/2] Fix null/undefined lyrics which cause exporter to fail

---
 .../kotlin/alphaTab/collections/List.kt       |   4 ++++
 src/model/Track.ts                            |   1 +
 test-data/guitarpro7/lyrics-null.gp           | Bin 0 -> 12329 bytes
 test/exporter/Gp7Exporter.test.ts             |  18 ++++++++++++------
 4 files changed, 17 insertions(+), 6 deletions(-)
 create mode 100644 test-data/guitarpro7/lyrics-null.gp

diff --git a/src.kotlin/alphaTab/alphaTab/src/commonMain/kotlin/alphaTab/collections/List.kt b/src.kotlin/alphaTab/alphaTab/src/commonMain/kotlin/alphaTab/collections/List.kt
index d3068d39d..a131a50ae 100644
--- a/src.kotlin/alphaTab/alphaTab/src/commonMain/kotlin/alphaTab/collections/List.kt
+++ b/src.kotlin/alphaTab/alphaTab/src/commonMain/kotlin/alphaTab/collections/List.kt
@@ -39,6 +39,10 @@ public class List<T> : Iterable<T> {
         _data.add(item)
     }
 
+    public fun fill(item: T) {
+        _data.fill(item)
+    }
+
     public fun push(items: List<T>) {
         _data.addAll(items._data)
     }
diff --git a/src/model/Track.ts b/src/model/Track.ts
index 1fdb6282d..4ee42e73e 100644
--- a/src/model/Track.ts
+++ b/src/model/Track.ts
@@ -102,6 +102,7 @@ export class Track {
                         // initialize lyrics list for beat if required
                         if (!beat.lyrics) {
                             beat.lyrics = new Array<string>(lyrics.length);
+                            beat.lyrics.fill("");
                         }
                         // assign chunk
                         beat.lyrics[li] = lyric.chunks[ci];
diff --git a/test-data/guitarpro7/lyrics-null.gp b/test-data/guitarpro7/lyrics-null.gp
new file mode 100644
index 0000000000000000000000000000000000000000..c9a3f91b16cdae6c30342ef7ba2898b0ab1be08c
GIT binary patch
literal 12329
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

literal 0
HcmV?d00001

diff --git a/test/exporter/Gp7Exporter.test.ts b/test/exporter/Gp7Exporter.test.ts
index eb1245645..5f8e4b061 100644
--- a/test/exporter/Gp7Exporter.test.ts
+++ b/test/exporter/Gp7Exporter.test.ts
@@ -14,8 +14,7 @@ describe('Gp7ExporterTest', () => {
         const data = await TestPlatform.loadFile('test-data/' + name);
         try {
             return ScoreLoader.loadScoreFromBytes(data);
-        }
-        catch (e) {
+        } catch (e) {
             return null;
         }
     };
@@ -30,7 +29,10 @@ describe('Gp7ExporterTest', () => {
         return new Gp7Exporter().export(score, null);
     };
 
-    const testRoundTripEqual: (name: string, ignoreKeys: string[] | null) => Promise<void> = async (name: string, ignoreKeys: string[] | null = null): Promise<void> => {
+    const testRoundTripEqual: (name: string, ignoreKeys: string[] | null) => Promise<void> = async (
+        name: string,
+        ignoreKeys: string[] | null = null
+    ): Promise<void> => {
         try {
             const expected = await loadScore(name);
             if (!expected) {
@@ -42,7 +44,7 @@ describe('Gp7ExporterTest', () => {
             const actual = prepareGp7ImporterWithBytes(exported).readScore();
 
             const expectedJson = JsonConverter.scoreToJsObject(expected);
-            const actualJson = JsonConverter.scoreToJsObject(actual)
+            const actualJson = JsonConverter.scoreToJsObject(actual);
 
             if (!ComparisonHelpers.expectJsonEqual(expectedJson, actualJson, '<' + fileName + '>', ignoreKeys)) {
                 await TestPlatform.saveFile(fileName, exported);
@@ -109,7 +111,7 @@ describe('Gp7ExporterTest', () => {
         await testRoundTripEqual(`conversion/full-song.gpx`, [
             'accidentalmode', // gets upgraded from default
             'percussionarticulations', // gets added
-            'percussionarticulation', // gets added
+            'percussionarticulation' // gets added
         ]);
     });
 
@@ -136,8 +138,12 @@ describe('Gp7ExporterTest', () => {
         const actual = prepareGp7ImporterWithBytes(exported).readScore();
 
         const expectedJson = JsonConverter.scoreToJsObject(expected);
-        const actualJson = JsonConverter.scoreToJsObject(actual)
+        const actualJson = JsonConverter.scoreToJsObject(actual);
 
         ComparisonHelpers.expectJsonEqual(expectedJson, actualJson, '<alphatex>', ['accidentalmode']);
     });
+
+    it('gp7-lyrics-null', async () => {
+        await testRoundTripEqual('guitarpro7/lyrics-null.gp', null);
+    });
 });

From 3ac15561810de42374d6b9dd4a393da13dabb07e Mon Sep 17 00:00:00 2001
From: Danielku15 <danielku15@coderline.net>
Date: Tue, 1 Nov 2022 13:58:56 +0100
Subject: [PATCH 2/2] Ensure empty-string is falsy

---
 src.csharp/AlphaTab.Test/Test/Globals.cs                 | 9 ++++++++-
 .../src/androidTest/kotlin/alphaTab/test/Globals.kt      | 7 ++++++-
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src.csharp/AlphaTab.Test/Test/Globals.cs b/src.csharp/AlphaTab.Test/Test/Globals.cs
index 05660269e..13e2c6bb3 100644
--- a/src.csharp/AlphaTab.Test/Test/Globals.cs
+++ b/src.csharp/AlphaTab.Test/Test/Globals.cs
@@ -87,7 +87,14 @@ public void ToBeTrue()
 
         public void ToBeFalsy()
         {
-            Assert.AreEqual(default!, _actual, _message);
+            if (_actual is string s) 
+            {
+                Assert.IsTrue(string.IsNullOrEmpty(s), _message);
+            }
+            else 
+            {
+                Assert.AreEqual(default!, _actual, _message);
+            }
         }
 
         public void ToThrowError(Type expected)
diff --git a/src.kotlin/alphaTab/alphaTab/src/androidTest/kotlin/alphaTab/test/Globals.kt b/src.kotlin/alphaTab/alphaTab/src/androidTest/kotlin/alphaTab/test/Globals.kt
index 0f6d5ff93..b30652f2f 100644
--- a/src.kotlin/alphaTab/alphaTab/src/androidTest/kotlin/alphaTab/test/Globals.kt
+++ b/src.kotlin/alphaTab/alphaTab/src/androidTest/kotlin/alphaTab/test/Globals.kt
@@ -68,7 +68,12 @@ public class Expector<T> {
     }
 
     public fun toBeFalsy() {
-        kotlin.test.assertNull(_actual, _message)
+        val actual = _actual;
+        if(actual is String){
+            kotlin.test.assertTrue(actual.isEmpty(), _message)
+        } else {
+            kotlin.test.assertNull(_actual, _message)
+        }
     }
 
     public fun toThrowError(expected: KClass<out Exception>) {