Fix subtasks-file lookup to not fail when preloaded from another file

Before this change, plugin failed to lookup a subtasks-file when
a task with this subtasks-file was preloaded using a task
reference [1]. While preloading a task, all the subtasks are copied
to the current task. Since the subtasks-file property was a String,
it does not maintain the information regarding the location of the
subtasks-file. Thus, fix this issue by using ConfigSourcedValue as
the type for subtasks-file property, which helps in tracking the
location of the subtasks-file. Add tests for the same.

[1]
file: `All-Projects:refs/meta/config:task.config`
```
[root "root task"]
    applicable = status:open
    preload-task = %sample group^Sample task with subtasks-file
```

file: `All-Users:refs/groups/<uuid of sample group>:task.config`
```
[task "Sample task with subtasks-file"]
  applicable = is:open
  pass = is:open
  subtasks-file = bar.config
```

file: `All-Users:refs/groups/<uuid of sample group>:task/bar.config`
```
[task "Sample task"]
  applicable = is:open
  pass = True
```

Change-Id: Icb1c548655eace95fefa2093bdc827276e0908d8
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
index 55d2f48..53897b5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
@@ -67,7 +67,7 @@
     public List<ConfigSourcedValue> subTasks;
     public List<ConfigSourcedValue> subTasksExternals;
     public List<ConfigSourcedValue> subTasksFactories;
-    public List<String> subTasksFiles;
+    public List<ConfigSourcedValue> subTasksFiles;
 
     public boolean isVisible;
     public boolean isMasqueraded;
@@ -98,7 +98,10 @@
           getStringList(s, KEY_SUBTASKS_FACTORY).stream()
               .map(subTask -> ConfigSourcedValue.create(s.file(), subTask))
               .collect(Collectors.toList());
-      subTasksFiles = getStringList(s, KEY_SUBTASKS_FILE);
+      subTasksFiles =
+          getStringList(s, KEY_SUBTASKS_FILE).stream()
+              .map(fileName -> ConfigSourcedValue.create(s.file(), fileName))
+              .collect(Collectors.toList());
     }
 
     protected TaskBase(TaskBase base) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
index b34dccd..1c6f31e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
@@ -386,10 +386,13 @@
       }
 
       protected void addSubTasksFiles() {
-        for (String file : task.subTasksFiles) {
+        for (ConfigSourcedValue configSourcedValue : task.subTasksFiles) {
           try {
             addPreloaded(
-                preloader.getTasks(FileKey.create(task.key().branch(), resolveTaskFileName(file))));
+                preloader.getTasks(
+                    FileKey.create(
+                        configSourcedValue.sourceFile().branch(),
+                        resolveTaskFileName(configSourcedValue.value()))));
           } catch (ConfigInvalidException | IOException e) {
             addInvalidNode();
           }
diff --git a/src/main/resources/Documentation/test/task_states.md b/src/main/resources/Documentation/test/task_states.md
index 273e21d..7a6a8d0 100644
--- a/src/main/resources/Documentation/test/task_states.md
+++ b/src/main/resources/Documentation/test/task_states.md
@@ -2615,6 +2615,36 @@
    ]
 }
 
+[root "Root Preload from group ref which has subtasks-file"]
+  preload-task = %{non_secret_group_name_without_space}^Sample task with subtasks-file
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root Preload from group ref which has subtasks-file",
+   "status" : "PASS",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Absolute Task 1",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Absolute Task 2",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Absolute Task",
+         "status" : "PASS"
+      }
+   ]
+}
+
 [root "Root Preload from user ref"]
   preload-task = @testuser/dir/relative.config^Relative Task
 
@@ -3656,6 +3686,13 @@
   pass = is:open
 ```
 
+file: `All-Users:refs/groups/{sharded_non_secret_group_uuid_without_space}:task/foo.config`
+```
+[task "Absolute Task"]
+  applicable = is:open
+  pass = is:open
+```
+
 file: `All-Users:refs/groups/{sharded_non_secret_group_uuid_without_space}:task.config`
 ```
 [task "task in group root config file 1"]
@@ -3684,6 +3721,13 @@
 [task "task in group root config file 2"]
   applicable = is:open
   pass = is:open
+
+[task "Sample task with subtasks-file"]
+  applicable = is:open
+  pass = is:open
+  set-my-prop = foo.config
+  subtasks-file = foo/bar.config
+  subtasks-file = ${my-prop}
 ```
 
 file: `All-Users:refs/groups/{sharded_non_secret_group_uuid_with_space}:task/foo/bar.config`