Add a Kotlin codegen flavor to Room's Kotlin test app.

This will enable us to test the integration app with both Java and Kotlin codegen.

Test: ./gradlew :room:integration-tests:room-testapp-kotlin:connectedWithKspGenKotlinDebugAndroidTest
Change-Id: I5166dc89db18c0a458f7d97f6101e252adb9be28
diff --git a/room/integration-tests/kotlintestapp/build.gradle b/room/integration-tests/kotlintestapp/build.gradle
index e23da19..35f2d71 100644
--- a/room/integration-tests/kotlintestapp/build.gradle
+++ b/room/integration-tests/kotlintestapp/build.gradle
@@ -18,7 +18,7 @@
 // -Dorg.gradle.debug=true
 // -Dkotlin.compiler.execution.strategy="in-process"
 
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+import com.google.devtools.ksp.gradle.KspTask
 
 plugins {
     id("AndroidXPlugin")
@@ -45,7 +45,8 @@
 
     sourceSets {
         androidTestWithKapt.assets.srcDirs += files("$projectDir/schemas".toString())
-        androidTestWithKsp.assets.srcDirs += files("$projectDir/schemas-ksp".toString())
+        androidTestWithKspGenJava.assets.srcDirs += files("$projectDir/schemas-ksp".toString())
+        androidTestWithKspGenKotlin.assets.srcDirs += files("$projectDir/schemas-ksp".toString())
     }
 
     flavorDimensions "processorConfiguration"
@@ -60,7 +61,10 @@
                 }
             }
         }
-        withKsp {
+        withKspGenJava {
+            dimension "processorConfiguration"
+        }
+        withKspGenKotlin {
             dimension "processorConfiguration"
         }
     }
@@ -79,7 +83,10 @@
     implementation(libs.multidex)
     // depend on the shadowed version so that it tests with the shipped artifact
     // this is a temporary attribute until KSP and AndroidX plugin supports variants.
-    kspAndroidTestWithKsp(
+    kspAndroidTestWithKspGenJava(
+            project(path: ":room:room-compiler", configuration: "shadowAndImplementation")
+    )
+    kspAndroidTestWithKspGenKotlin(
             project(path: ":room:room-compiler", configuration: "shadowAndImplementation")
     )
     kaptAndroidTestWithKapt(
@@ -118,7 +125,13 @@
     testImplementation(libs.mockitoCore)
 }
 
-// KSP does not support argument per flavor so we set it to global instead.
+// KSP does not support argument per flavor so we set schema location globally, for other per
+// flavor options we use flavor named tasks. See https://github.com/google/ksp/issues/861.
 ksp {
     arg("room.schemaLocation","$projectDir/schemas-ksp".toString())
 }
+tasks.withType(KspTask).configureEach { kspTask ->
+    if (kspTask.name.contains("GenKotlin")) {
+        kspTask.apOptions.put("room.generateKotlin", "true")
+    }
+}
diff --git a/room/integration-tests/kotlintestapp/schemas-ksp/androidx.room.integration.kotlintestapp.migration.MigrationDbKotlin/8.json b/room/integration-tests/kotlintestapp/schemas-ksp/androidx.room.integration.kotlintestapp.migration.MigrationDbKotlin/8.json
new file mode 100644
index 0000000..5ff99a1
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/schemas-ksp/androidx.room.integration.kotlintestapp.migration.MigrationDbKotlin/8.json
@@ -0,0 +1,120 @@
+{
+  "formatVersion": 1,
+  "database": {
+    "version": 8,
+    "identityHash": "7c65736dc87e4f5bf7bf54e1ef798ec2",
+    "entities": [
+      {
+        "tableName": "Entity1",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `name` TEXT, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "name",
+            "columnName": "name",
+            "affinity": "TEXT",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "autoGenerate": false,
+          "columnNames": [
+            "id"
+          ]
+        },
+        "indices": [
+          {
+            "name": "index_Entity1_name",
+            "unique": true,
+            "columnNames": [
+              "name"
+            ],
+            "orders": [],
+            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Entity1_name` ON `${TABLE_NAME}` (`name`)"
+          }
+        ],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "Entity2",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `addedInV3` TEXT, `name` TEXT, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "addedInV3",
+            "columnName": "addedInV3",
+            "affinity": "TEXT",
+            "notNull": false
+          },
+          {
+            "fieldPath": "name",
+            "columnName": "name",
+            "affinity": "TEXT",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "autoGenerate": false,
+          "columnNames": [
+            "id"
+          ]
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "Entity4",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `name` TEXT, PRIMARY KEY(`id`), FOREIGN KEY(`name`) REFERENCES `Entity1`(`name`) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED)",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "name",
+            "columnName": "name",
+            "affinity": "TEXT",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "autoGenerate": false,
+          "columnNames": [
+            "id"
+          ]
+        },
+        "indices": [],
+        "foreignKeys": [
+          {
+            "table": "Entity1",
+            "onDelete": "NO ACTION",
+            "onUpdate": "NO ACTION",
+            "columns": [
+              "name"
+            ],
+            "referencedColumns": [
+              "name"
+            ]
+          }
+        ]
+      }
+    ],
+    "views": [],
+    "setupQueries": [
+      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '7c65736dc87e4f5bf7bf54e1ef798ec2')"
+    ]
+  }
+}
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/schemas/androidx.room.integration.kotlintestapp.migration.MigrationDbKotlin/8.json b/room/integration-tests/kotlintestapp/schemas/androidx.room.integration.kotlintestapp.migration.MigrationDbKotlin/8.json
new file mode 100644
index 0000000..5ff99a1
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/schemas/androidx.room.integration.kotlintestapp.migration.MigrationDbKotlin/8.json
@@ -0,0 +1,120 @@
+{
+  "formatVersion": 1,
+  "database": {
+    "version": 8,
+    "identityHash": "7c65736dc87e4f5bf7bf54e1ef798ec2",
+    "entities": [
+      {
+        "tableName": "Entity1",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `name` TEXT, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "name",
+            "columnName": "name",
+            "affinity": "TEXT",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "autoGenerate": false,
+          "columnNames": [
+            "id"
+          ]
+        },
+        "indices": [
+          {
+            "name": "index_Entity1_name",
+            "unique": true,
+            "columnNames": [
+              "name"
+            ],
+            "orders": [],
+            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Entity1_name` ON `${TABLE_NAME}` (`name`)"
+          }
+        ],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "Entity2",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `addedInV3` TEXT, `name` TEXT, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "addedInV3",
+            "columnName": "addedInV3",
+            "affinity": "TEXT",
+            "notNull": false
+          },
+          {
+            "fieldPath": "name",
+            "columnName": "name",
+            "affinity": "TEXT",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "autoGenerate": false,
+          "columnNames": [
+            "id"
+          ]
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "Entity4",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `name` TEXT, PRIMARY KEY(`id`), FOREIGN KEY(`name`) REFERENCES `Entity1`(`name`) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED)",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "name",
+            "columnName": "name",
+            "affinity": "TEXT",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "autoGenerate": false,
+          "columnNames": [
+            "id"
+          ]
+        },
+        "indices": [],
+        "foreignKeys": [
+          {
+            "table": "Entity1",
+            "onDelete": "NO ACTION",
+            "onUpdate": "NO ACTION",
+            "columns": [
+              "name"
+            ],
+            "referencedColumns": [
+              "name"
+            ]
+          }
+        ]
+      }
+    ],
+    "views": [],
+    "setupQueries": [
+      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '7c65736dc87e4f5bf7bf54e1ef798ec2')"
+    ]
+  }
+}
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/RoomTestConfig.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/RoomTestConfig.kt
index 1d20a98..fb04b08 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/RoomTestConfig.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/RoomTestConfig.kt
@@ -27,7 +27,7 @@
      * This can help enable/disable certain tests for ksp
      */
     val isKsp
-        get() = BuildConfig.FLAVOR == "withKsp"
+        get() = BuildConfig.FLAVOR.startsWith("withKsp")
 }
 
 /**
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationDbKotlin.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationDbKotlin.kt
index 4d21e0e..0aa25f1 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationDbKotlin.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationDbKotlin.kt
@@ -18,6 +18,7 @@
 
 import android.content.ContentValues
 import android.database.sqlite.SQLiteDatabase
+import androidx.room.AutoMigration
 import androidx.room.Dao
 import androidx.room.Database
 import androidx.room.Entity
@@ -33,10 +34,14 @@
 
 @Database(
     version = MigrationDbKotlin.LATEST_VERSION,
-    entities = arrayOf(
-        MigrationDbKotlin.Entity1::class, MigrationDbKotlin.Entity2::class,
+    entities = [
+        MigrationDbKotlin.Entity1::class,
+        MigrationDbKotlin.Entity2::class,
         MigrationDbKotlin.Entity4::class
-    )
+    ],
+    autoMigrations = [
+        AutoMigration(7, 8)
+    ]
 )
 abstract class MigrationDbKotlin : RoomDatabase() {
 
@@ -61,7 +66,8 @@
     data class Entity3(
         @PrimaryKey var id: Int = 0,
         @get:Ignore var removedInV5: String?,
-        var name: String?
+        var name: String?,
+        var addedInV8: Int = 1
     ) { // added in version 4, removed at 6
         companion object {
             val TABLE_NAME = "Entity3"
@@ -142,6 +148,6 @@
     }
 
     companion object {
-        const val LATEST_VERSION = 7
+        const val LATEST_VERSION = 8
     }
 }
diff --git a/room/scripts/ksp-kapt-comparison.sh b/room/scripts/ksp-kapt-comparison.sh
index 2e19578..8de53fa 100755
--- a/room/scripts/ksp-kapt-comparison.sh
+++ b/room/scripts/ksp-kapt-comparison.sh
@@ -13,7 +13,7 @@
 # move to the project directory
 cd $PROJECT_DIR;
 
-KSP_TASK=":room:integration-tests:room-testapp-kotlin:kspWithKspDebugAndroidTestKotlin"
+KSP_TASK=":room:integration-tests:room-testapp-kotlin:kspWithKspGenJavaDebugAndroidTestKotlin"
 KAPT_TASK=":room:integration-tests:room-testapp-kotlin:kaptGenerateStubsWithKaptDebugAndroidTestKotlin \
     :room:integration-tests:room-testapp-kotlin:kaptWithKaptDebugAndroidTestKotlin"
 # parses the given profile file, extracts task durations that we are interested in and adds them to the global tracking
diff --git a/room/scripts/profile.sh b/room/scripts/profile.sh
index e8c912e..1e34203 100755
--- a/room/scripts/profile.sh
+++ b/room/scripts/profile.sh
@@ -6,7 +6,7 @@
     echo "usage: ./profile.sh <gradle tasks>
     ./profile.sh --name my_run \
         --target gradle \
-        :room:integration-tests:room-testapp-kotlin:kspWithKspDebugAndroidTestKotlin \
+        :room:integration-tests:room-testapp-kotlin:kspWithKspGenJavaDebugAndroidTestKotlin \
         --filter *K2JVMCompiler*
     ./profile.sh --name my_run \
         --target test \
@@ -93,7 +93,7 @@
                 ADDITIONAL_AGENT_PARAMS="$ADDITIONAL_AGENT_PARAMS,include=*AbstractKapt3Extension*"
                 AGENT_TARGET="gradle"
             elif [ "$2" = "ksp" ]; then
-                GRADLE_ARGS=":room:integration-tests:room-testapp-kotlin:kspWithKspDebugAndroidTestKotlin"
+                GRADLE_ARGS=":room:integration-tests:room-testapp-kotlin:kspWithKspGenJavaDebugAndroidTestKotlin"
                 ADDITIONAL_AGENT_PARAMS="$ADDITIONAL_AGENT_PARAMS,include=*AbstractKotlinSymbolProcessingExtension*"
                 AGENT_TARGET="gradle"
             else