Skip to content

Commit 7f7b81d

Browse files
Test Automation for Issue 783 (#2866)
1 parent f6b88ca commit 7f7b81d

3 files changed

Lines changed: 170 additions & 0 deletions

File tree

src/org/labkey/test/components/domain/DomainFormPanel.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ else if (fieldDefinition.getType().equals(FieldDefinition.ColumnType.DateAndTime
188188
fieldRow.setLookupValidatorEnabled(fieldDefinition.getLookupValidatorEnabled());
189189
if (fieldDefinition.getAliquotOption() != null)
190190
fieldRow.setAliquotOption(fieldDefinition.getAliquotOption());
191+
if (fieldDefinition.getValueExpression() != null)
192+
fieldRow.setValueExpression(fieldDefinition.getValueExpression());
191193
// ontology-specific
192194
if (fieldDefinition.getSourceOntology() != null)
193195
fieldRow.setSelectedOntology(fieldDefinition.getSourceOntology());

src/org/labkey/test/params/FieldDefinition.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,11 @@ public FieldDefinition setValueExpression(String valueExpression)
307307
return this;
308308
}
309309

310+
public String getValueExpression()
311+
{
312+
return (String) getFieldProperty("valueExpression");
313+
}
314+
310315
public Integer getScale()
311316
{
312317
return (Integer) getFieldProperty("scale");
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
package org.labkey.test.tests;
2+
3+
import org.junit.BeforeClass;
4+
import org.junit.Ignore;
5+
import org.junit.Test;
6+
import org.junit.experimental.categories.Category;
7+
import org.labkey.remoteapi.CommandException;
8+
import org.labkey.test.BaseWebDriverTest;
9+
import org.labkey.test.Locator;
10+
import org.labkey.test.categories.Daily;
11+
import org.labkey.test.pages.experiment.UpdateSampleTypePage;
12+
import org.labkey.test.params.FieldDefinition;
13+
import org.labkey.test.params.FieldInfo;
14+
import org.labkey.test.params.experiment.SampleTypeDefinition;
15+
import org.labkey.test.util.PortalHelper;
16+
import org.labkey.test.util.PostgresOnlyTest;
17+
import org.labkey.test.util.SampleTypeHelper;
18+
import org.labkey.test.util.exp.SampleTypeAPIHelper;
19+
import org.labkey.test.util.query.QueryApiHelper;
20+
import org.labkey.test.util.search.SearchAdminAPIHelper;
21+
22+
import java.io.IOException;
23+
import java.util.ArrayList;
24+
import java.util.Arrays;
25+
import java.util.HashMap;
26+
import java.util.List;
27+
import java.util.Map;
28+
import java.util.Random;
29+
30+
@Category({Daily.class})
31+
public class SampleTypeDesignerStressTest extends BaseWebDriverTest implements PostgresOnlyTest
32+
{
33+
34+
private static final String PROJECT_NAME = "SampleType Designer Stress Test";
35+
36+
@Override
37+
public List<String> getAssociatedModules()
38+
{
39+
return Arrays.asList("experiment");
40+
}
41+
42+
@Override
43+
protected String getProjectName()
44+
{
45+
return PROJECT_NAME;
46+
}
47+
48+
@Override
49+
public BrowserType bestBrowser()
50+
{
51+
return BrowserType.CHROME;
52+
}
53+
54+
@BeforeClass
55+
public static void setupProject()
56+
{
57+
SampleTypeDesignerStressTest init = getCurrentTest();
58+
init.doSetup();
59+
}
60+
61+
private void doSetup()
62+
{
63+
PortalHelper portalHelper = new PortalHelper(this);
64+
_containerHelper.createProject(PROJECT_NAME, null);
65+
portalHelper.enterAdminMode();
66+
portalHelper.addWebPart("Sample Types");
67+
portalHelper.exitAdminMode();
68+
}
69+
70+
/**
71+
*
72+
* <p>
73+
* Testing <a href="https://github.com/LabKey/internal-issues/issues/783">Issue 783: Server lockup when updating data class domain design</a>
74+
* </p>
75+
* <p>
76+
* Description from the issue:
77+
* </p>
78+
* <p>
79+
* Lock provisioned table on domain update
80+
* </p>
81+
* <p>
82+
* Operations such as add/drop column requires ACCESS EXCLUSIVE lock on the table. If another transaction performed
83+
* a SELECT on a provisioned table, adding/dropping columns from the provisioned table would have to wait until the
84+
* other transaction to complete. If the other transaction happened to be waiting for the add/drop column transaction
85+
* (in this case, updating exp.dataclass table), the two would deadlock.
86+
* </p>
87+
*
88+
*/
89+
@Test @Ignore // Ignoring the test because it still fails with search service errors on TC.
90+
public void testDomainDesignerDeadlock() throws IOException, CommandException
91+
{
92+
goToProjectHome();
93+
94+
// Intentionally not using fuzz values for this test. Want to keep it focused on stress.
95+
final String sampleTypeName = "DomainDesignerStress";
96+
97+
List<FieldDefinition> fields = new ArrayList<>();
98+
99+
int numOfFields = 10;
100+
log(String.format("Create a sample type with %d Int fields.", numOfFields));
101+
for (int i = 1; i <= numOfFields; i++)
102+
{
103+
fields.add(new FieldInfo(String.format("Int%02d", i), FieldDefinition.ColumnType.Integer).getFieldDefinition());
104+
}
105+
106+
SampleTypeDefinition sampleTypeDefinition = new SampleTypeDefinition(sampleTypeName).setFields(fields);
107+
sampleTypeDefinition.setNameExpression("DDStress ${genId}");
108+
109+
SampleTypeAPIHelper.createEmptySampleType(getProjectName(), sampleTypeDefinition);
110+
111+
Random randomInt = new Random();
112+
113+
List<Map<String, Object>> sampleRows = new ArrayList<>();
114+
115+
int numOfRows = 2_000;
116+
log(String.format("Add %,d rows with data to the sample type.", numOfRows));
117+
for (int i = 0; i < numOfRows; i++)
118+
{
119+
Map<String, Object> rowMap = new HashMap<>();
120+
for (FieldDefinition fd : fields)
121+
{
122+
rowMap.put(fd.getName(), randomInt.nextInt());
123+
}
124+
sampleRows.add(rowMap);
125+
}
126+
127+
QueryApiHelper queryApiHelper = new QueryApiHelper(createDefaultConnection(), getProjectName(), "exp.materials", sampleTypeName);
128+
queryApiHelper.insertRows(sampleRows);
129+
130+
refresh();
131+
132+
log("Wait for the indexer to complete after creating the sample type and populating it.");
133+
SearchAdminAPIHelper.waitForIndexer();
134+
135+
SampleTypeHelper sampleTypeHelper = new SampleTypeHelper(getDriver());
136+
137+
sampleTypeHelper.goToSampleType(sampleTypeName);
138+
139+
// Add as many new fields as there were originally in the sample type design.
140+
log(String.format("Add %d new fields, one at a time, to the sample type.", numOfFields));
141+
for (int i = 1; i <= numOfFields; i++)
142+
{
143+
144+
FieldDefinition fd = new FieldDefinition(String.format("New Text %02d", i), FieldDefinition.ColumnType.String);
145+
waitAndClickAndWait(Locator.lkButton("Edit Type"));
146+
UpdateSampleTypePage domainDesignerPage = new UpdateSampleTypePage(getDriver());
147+
domainDesignerPage.addField(fd);
148+
domainDesignerPage.clickSave();
149+
150+
// When running locally if the search indexer isn't allowed to run for every 5th field added the test will
151+
// fail with a server error because of the indexer. These errors might be valid to investigate, but they are
152+
// not the kind of errors this test is trying to catch.
153+
if (i%5 == 0)
154+
{
155+
log("Wait for the indexer to complete after adding 5 new fields.");
156+
SearchAdminAPIHelper.waitForIndexer();
157+
}
158+
159+
}
160+
161+
}
162+
163+
}

0 commit comments

Comments
 (0)