Repository: getgauge/gauge (go)

Issue:
gauge run gets stuck on step applying tags filter for parallel execution
Prerequisites:
$ gauge -v
Gauge version: 1.0.7
Commit Hash: ed7b4fd

Plugins
flash (0.0.2)
html-report (4.0.9)
python (0.3.7)
screenshot (0.0.1)
spectacle (0.1.4)
xml-report (0.2.3)

default.properties:
allow_filtered_parallel_execution = true

### Notes
Our automation suite contains now 200+ specs, and 800+ scenarios. When trying to use tags filtering for parallel execution, the execution gets stuck at step _"Applying tags filter_
I tried the feature on new, very basic project and it worked fine. So I'm assuming it has to be related to the large number on scenarios. Unfortunately, I can't share our automation tests, but maybe someone can investigate.

This is a log from a run ( I've stopped the execution after about 30 minutes of waiting)

`
gauge run specs/sanity --parallel --only "\!no-parallel" --log-level debug --machine-readable --fail-safe 
{"type":"out","message":"gauge run specs/sanity"}
{"type":"out","message":"fail-safe : [true]"}
{"type":"out","message":"log-level : [debug]"}
{"type":"out","message":"machine-readable : [true]"}
{"type":"out","message":"only : [\\!no-parallel]"}
{"type":"out","message":"parallel : [true]"}
{"type":"out","message":"'gauge_environment' set to 'default'"}
{"type":"out","message":"Created gauge_screenshots_dir at /home/marius/workspace/auto/figtesting/website_sanity_tests/.gauge/screenshots"}
{"type":"out","message":"Plugin python is already installed."}
{"type":"out","message":"Plugin html-report is already installed."}
{"type":"out","message":"Plugin spectacle is already installed."}
{"type":"out","message":"Plugin flash is already installed."}
{"type":"out","message":"Plugin xml-report is already installed."}
{"type":"out","message":"Parsing started."}
{"type":"out","message":"Started concepts parsing."}
{"type":"out","message":"102 concepts parsing completed."}
{"type":"out","message":"Started specifications parsing."}
{"type":"out","message":"206 specifications parsing completed."}
{"type":"out","message":"Parsing completed."}
{"type":"out","message":"Staring python runner"}
{"type":"out","message":"Checking updates..."}
{"type":"out","message":"Downloading https://downloads.getgauge.io/plugin/flash?l=python\u0026p=flash,html-report,python,screenshot,spectacle,xml-report\u0026o=linux\u0026a=amd64"}
{"type":"out","message":"Python: 3.5.3"}
{"type":"out","message":"Loading step implemetations from /home/marius/workspace/auto/figtesting/website_sanity_tests/step_impl dirs."}
{"type":"out","message":"Downloading https://downloads.getgauge.io/plugin/html-report?l=python\u0026p=flash,html-report,python,screenshot,spectacle,xml-report\u0026o=linux\u0026a=amd64"}
{"type":"out","message":"Downloading https://downloads.getgauge.io/plugin/python?l=python\u0026p=flash,html-report,python,screenshot,spectacle,xml-report\u0026o=linux\u0026a=amd64"}
{"type":"out","message":"Downloading https://downloads.getgauge.io/plugin/screenshot?l=python\u0026p=flash,html-report,python,screenshot,spectacle,xml-report\u0026o=linux\u0026a=amd64"}
{"type":"out","message":"Downloading https://downloads.getgauge.io/plugin/spectacle?l=python\u0026p=flash,html-report,python,screenshot,spectacle,xml-report\u0026o=linux\u0026a=amd64"}
{"type":"out","message":"Downloading https://downloads.getgauge.io/plugin/xml-report?l=python\u0026p=flash,html-report,python,screenshot,spectacle,xml-report\u0026o=linux\u0026a=amd64"}
{"type":"out","message":"Starting TCP server.."}
{"type":"out","message":"Connecting to port 35163"}
{"type":"out","message":"Established connection to runner."}
{"type":"out","message":"Validation started."}
{"type":"out","message":"Validation completed."}
{"type":"out","message":"Sending kill message to runner."}
{"type":"out","message":"Runner with PID:13302 has exited"}
{"type":"out","message":"Run started"}
{"type":"out","message":"Starting Html Report plugin"}
{"type":"suiteStart"}
{"type":"out","message":"Attempting to connect to grpc server at port: 44871"}
{"type":"out","message":"Successfully made the connection with plugin with port: 44871"}
{"type":"out","message":"Starting Flash plugin"}
{"type":"out","message":"[Flash] Starting progress reporting at http://127.0.0.1:5678"}
{"type":"out","message":"Attempting to connect to grpc server at port: 42025"}
{"type":"out","message":"Successfully made the connection with plugin with port: 42025"}
{"type":"out","message":"Starting Xml Report plugin"}
{"type":"out","message":"Attempting to connect to grpc server at port: 37937"}
{"type":"out","message":"Successfully made the connection with plugin with port: 37937"}
{"type":"out","message":"Applying tags filter: \\!no-parallel"}`

Pull request description:
Fixe for data driven execution when scenario data table are used with parallel tag filters.
Fixes #1585

Signed-off-by: Dharmendra Singh <dharmenn@thoughtworks.com>

Patch:
diff --git a/parser/dataTableSpecs.go b/parser/dataTableSpecs.go
index d98a8d68..28aeac42 100644
--- a/parser/dataTableSpecs.go
+++ b/parser/dataTableSpecs.go
@@ -24,14 +24,16 @@ func GetSpecsForDataTableRows(s []*gauge.Specification, errMap *gauge.BuildError
 				if len(tableRelatedScenarios) > 0 {
 					s := createSpecsForTableRows(spec, tableRelatedScenarios, errMap)
 					s[0].Scenarios = append(s[0].Scenarios, nonTableRelatedScenarios...)
+					for _, scn := range nonTableRelatedScenarios {
+						s[0].Items = append(s[0].Items, scn)
+					}
 					specs = append(specs, s...)
 				} else {
 					specs = append(specs, createSpec(copyScenarios(nonTableRelatedScenarios, gauge.Table{}, 0, errMap), &gauge.Table{}, spec, errMap))
 				}
 			}
 		} else {
-			spec.Scenarios = copyScenarios(spec.Scenarios, gauge.Table{}, 0, errMap)
-			specs = append(specs, spec)
+			specs = append(specs, createSpec(copyScenarios(spec.Scenarios, gauge.Table{}, 0, errMap), &gauge.Table{}, spec, errMap))
 		}
 	}
 	return


Test patch:
diff --git a/parser/dataTableSpecs_test.go b/parser/dataTableSpecs_test.go
index d0ea649a..82051b90 100644
--- a/parser/dataTableSpecs_test.go
+++ b/parser/dataTableSpecs_test.go
@@ -12,6 +12,7 @@ import (
 	"encoding/json"
 	"reflect"
 
+	"github.com/getgauge/gauge/env"
 	"github.com/getgauge/gauge/gauge"
 )
 
@@ -102,6 +103,68 @@ func TestGetSpecsForDataTableRows(t *testing.T) {
 	}
 }
 
+func TestGetSpecsForDataTableRowsShouldHaveEqualNumberOfScenearioInSpecsScenariosAndItemCollection(t *testing.T) {
+	specs := []*gauge.Specification{
+		{
+			Heading: &gauge.Heading{},
+			Scenarios: []*gauge.Scenario{
+				{Steps: []*gauge.Step{{Args: []*gauge.StepArg{{Value: "header", ArgType: gauge.Dynamic, Name: "header"}}}}},
+				{Steps: []*gauge.Step{{Args: []*gauge.StepArg{{Value: "param1", ArgType: gauge.Static, Name: "param1"}}}}},
+			},
+			DataTable: gauge.DataTable{Table: *gauge.NewTable([]string{"header"}, [][]gauge.TableCell{
+				{{Value: "row1", CellType: gauge.Static}, {Value: "row2", CellType: gauge.Static}},
+			}, 0)},
+		},
+	}
+	actualSpecs := GetSpecsForDataTableRows(specs, gauge.NewBuildErrors())
+	if !containsScenario(actualSpecs[0].Scenarios, actualSpecs[0].Items) {
+		itemsJSON, _ := json.Marshal(actualSpecs[0].Items)
+		scnJSON, _ := json.Marshal(actualSpecs[0].Scenarios)
+		t.Errorf("Failed: Wanted items:\n\n%s\n\nto contain all scenarios: \n\n%s", itemsJSON, scnJSON)
+	}
+}
+
+func containsScenario(scenarios []*gauge.Scenario, items []gauge.Item) bool {
+	for _, scenario := range scenarios {
+		contains := false
+		for _, item := range items {
+			if item.Kind() == gauge.ScenarioKind && reflect.DeepEqual(scenario, item.(*gauge.Scenario)) {
+				contains = true
+			}
+		}
+		if !contains {
+			return false
+		}
+	}
+	return true
+}
+
+func TestGetSpecsForDataTableRowsShouldHaveEqualNumberOfScenearioInSpecsScenariosAndItemCollectionForScenarioDataTable(t *testing.T) {
+	old := env.AllowScenarioDatatable
+	env.AllowScenarioDatatable = func() bool {
+		return true
+	}
+	specs := []*gauge.Specification{
+		{
+			Heading: &gauge.Heading{},
+			Scenarios: []*gauge.Scenario{
+				{
+					Steps: []*gauge.Step{{Args: []*gauge.StepArg{{Value: "header", ArgType: gauge.Dynamic, Name: "header"}}}},
+					DataTable: gauge.DataTable{Table: *gauge.NewTable([]string{"header"}, [][]gauge.TableCell{
+						{{Value: "row1", CellType: gauge.Static}, {Value: "row2", CellType: gauge.Static}, {Value: "row3", CellType: gauge.Static}},
+					}, 0)}},
+			},
+		},
+	}
+	actualSpecs := GetSpecsForDataTableRows(specs, gauge.NewBuildErrors())
+
+	if !containsScenario(actualSpecs[0].Scenarios, actualSpecs[0].Items) {
+		itemsJSON, _ := json.Marshal(actualSpecs[0].Items)
+		scnJSON, _ := json.Marshal(actualSpecs[0].Scenarios)
+		t.Errorf("Failed: Wanted items:\n\n%s\n\nto contain all scenarios: \n\n%s", itemsJSON, scnJSON)
+	}
+	env.AllowScenarioDatatable = old
+}
 func TestGetTableWithOneRow(t *testing.T) {
 	table := *gauge.NewTable([]string{"header"}, [][]gauge.TableCell{
 		{{Value: "row1", CellType: gauge.Static}, {Value: "row2", CellType: gauge.Static}},