-
Notifications
You must be signed in to change notification settings - Fork 792
[EXPERIMENT!] Use AI to migrate Solr tests from SolrJettyTestBase to using SolrJettyTestRule #3947
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…rTestCaseJ4 I used the prompt that I previously checked in, and pretty much just let it go to town. I had to help it a bit on the BasicHttpSolrClientTest. tests_not_migrated.md represents the ones that didn't go on the first pass.
…ious batch They all look pretty straightforward however.
|
Some lessons learned:
|
|
Big changes like this should be a multi-step journey. Anticipate that and ask the AI where to start and just stay focused there. For example look at SolrJettyTestBase and focus on removing that. Perhaps even that might be too much for one PR, so narrow further on RestTestBae, for example. |
|
Note for later: This pattern if often NOT needed. Remove it and the test passes... Also, look for Also, make sure |
|
I think I am there for this effort. I didn't manage to move ALL clasess from SolrJettyTestBase, we still have classes that extend it... I thought I would come up with a prompt, run it, review the results and edit the prompt and re-run it. That didn't really happen... And I ended up going through each class and putting a lot of manual review in and tweaking from what Claude first did! |
|
Please ignore the documentation related files, I will remove them as part of my final review.. I'm keeping them mostly as "working file".... |
|
Actually, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This entire package is going away soon.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I very much look forward to that!
| public abstract class SolrExampleTestsBase extends SolrJettyTestBase { | ||
| public abstract class SolrExampleTestsBase extends SolrTestCaseJ4 { | ||
|
|
||
| @ClassRule public static SolrJettyTestRule solrJettyTestRule = new SolrJettyTestRule(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps we should standardize on a field name for the rule. Like "solrRule" is fairly short & sweet. We needn't put it's "Jetty"-ness in the name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure! Would you want to rename the class SolrJettyTestRule to SolrTestRule too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure! Would you want to rename the class SolrJettyTestRule to SolrTestRule too?
No of course not; Jetty is what differentiates that class from EmbeddedSolrServerTestRule, and eventually from a forthcoming SolrCloudTestRule. An analogy would be using ArrayList but declaring a field/param/var as list.
| return getHttpSolrClient(solrJettyTestRule.getBaseUrl(), DEFAULT_TEST_CORENAME); | ||
| } | ||
|
|
||
| public static HttpSolrClient getHttpSolrClient(String baseUrl, String coreName) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
protected
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's apparently public in the parent class SolrTestCaseJ4 so I can't...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i amc hecking if we duplicate methods from parent classes..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now I see that this method was copied from STCJ4. Why copy it?
| // create second core | ||
| try (SolrClient nodeClient = getHttpSolrClient(url)) { | ||
| CoreAdminRequest.Create req = new CoreAdminRequest.Create(); | ||
| req.setCoreName("collection2"); | ||
| req.setConfigSet("collection1"); | ||
| nodeClient.request(req); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what happened to the 2nd core?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We now do set up directly:
- **Old approach **: Start Solr with one core, then use
CoreAdminRequest.Createto add the second core dynamically - New approach: Pre-create both core directories and configs, so Solr discovers and loads both cores during startup
Claude says this is fine and doesn't defeat the purpose of the test. Follows our more common patterns as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good qeustion to ask!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this test not amenable to SolrJettyTestRule.create or maybe Claude/you didn't know it exists because of too few callers? Some tests may not be but I haven't examined this one closely to know. When I created the Solr rule APIs, I wanted to ensure it has a generalized API for core/collection creation so that we could have some tests minimally change between an (eventual) SolrCloud vs Jetty vs simply embedded. I also wanted tests to look more "normal" with respect to SolrClient API. Pre-creation is kind of low level and also questionable with SolrCloud. If we were to lean in the other direction (pre-creation), I'd want to see more/better solr-home dir setup methods. That wouldn't be a bad thing anyway.
@hossman maybe you might have an opinion as an old-timer on test infra here, if I can be so lucky to get your attention on the GitHub platform ;-).
So the approach you are doing is not wrong. But I was trying to get away from, not attract to. It's a "preference" matter, definitely not a strong deprecate/going-away.
| } | ||
| } | ||
| assertTrue("Expected header not found", containsWarningHeader); | ||
| HttpClientUtil.close(httpClient); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the try-with-resources means you don't need this explicit close
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR is an experimental effort to use AI to migrate Solr tests from the deprecated SolrJettyTestBase to using SolrJettyTestRule. The primary goal is to reduce technical debt by modernizing test infrastructure, with the focus on refining the AI prompt (prompt_to_use.md) rather than reviewing individual test file changes.
Key changes:
- Migration of numerous test classes from extending
SolrJettyTestBasetoSolrTestCaseJ4with@ClassRule SolrJettyTestRule - Updates to base test classes (
SolrExampleTestsBase,HttpSolrClientTestBase) to support the new pattern - Replacement of legacy methods (
getBaseUrl(),getSolrClient(), etc.) with rule-based equivalents - Documentation of migration progress and patterns in markdown files
Reviewed changes
Copilot reviewed 40 out of 40 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| prompt_to_use.md | AI prompt defining migration requirements and patterns |
| tests_not_migrated.md | Documentation of migration status and remaining work |
| MIGRATION_*.md | AI-generated status and progress tracking files |
| solr/test-framework/.../BasicHttpSolrClientTest.java | Migrated to use SolrJettyTestRule with extensive method call replacements |
| solr/test-framework/.../ConcurrentUpdate*.java | Multiple test classes migrated to new pattern |
| solr/solrj/.../HttpSolrClientTestBase.java | Base class updated with DEFAULT_COLLECTION constant and rule support |
| solr/solrj/.../SolrExampleTestsBase.java | Base class refactored with deprecated backward-compatibility methods |
| solr/solrj/.../*Test.java | Various test classes migrated following standard pattern |
| solr/core/.../ResponseHeaderTest.java | Migrated with improved resource management using try-with-resources |
| solr/core/.../TestTolerantSearch.java | Complex multi-collection test migrated with custom setup |
| solr/core/.../DistributedDebugComponentTest.java | Multi-collection test migrated |
| solr/modules/sql/.../TestSQLHandlerNonCloud.java | Migrated with minimal config setup |
| solr/test-framework/.../SolrTestCaseJ4.java | Added documentation to copyMinConf method |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| protected HttpClient getHttpClient() { | ||
| HttpSolrClient client = (HttpSolrClient) getSolrClient(); | ||
| return client.getHttpClient(); | ||
| } |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method getHttpClient() is added but is never called within this file. If this is an override of a parent class method or an interface method, it should be annotated with @Override. Otherwise, consider removing this unused method or documenting its purpose.
| collection1 = null; | ||
| collection2 = null; |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the migration to SolrJettyTestRule, the clients collection1 and collection2 are no longer explicitly closed in the AfterClass method. While the comment suggests relying on the rule for cleanup, verify that the SolrJettyTestRule properly closes all SolrClient instances obtained via getSolrClient() to prevent resource leaks.
| collection1 = null; | |
| collection2 = null; | |
| if (collection1 != null) { | |
| collection1.close(); | |
| collection1 = null; | |
| } | |
| if (collection2 != null) { | |
| collection2.close(); | |
| collection2 = null; | |
| } |
| Path workDir = createTempDir().toRealPath(); | ||
| Path collectionDirectory = workDir.resolve(DEFAULT_TEST_COLLECTION_NAME); | ||
|
|
||
| copyMinConf(collectionDirectory, "name=" + DEFAULT_TEST_COLLECTION_NAME + "\n"); | ||
|
|
||
| return workDir; |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The migration removes the setupJettyTestHome call and replaces it with copyMinConf. However, setupJettyTestHome may have been copying additional configuration files beyond what copyMinConf provides. Verify that all necessary configuration files (such as schema.xml, managed-schema, etc.) are still properly copied for the test to function correctly.
| // Backward compatibility methods for existing subclasses | ||
| @Deprecated | ||
| protected static void createAndStartJetty(Path solrHome) throws Exception { | ||
| solrJettyTestRule.startSolr(solrHome, new Properties(), JettyConfig.builder().build()); | ||
| } |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The deprecated method createAndStartJetty is being added to SolrExampleTestsBase but marked as deprecated. This suggests subclasses may still be calling it. Consider removing this method entirely and updating all subclasses to use the new pattern with solrJettyTestRule.startSolr() instead of maintaining backward compatibility with a deprecated API.
| // Backward compatibility methods for existing subclasses | |
| @Deprecated | |
| protected static void createAndStartJetty(Path solrHome) throws Exception { | |
| solrJettyTestRule.startSolr(solrHome, new Properties(), JettyConfig.builder().build()); | |
| } |
solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTestsBase.java
Show resolved
Hide resolved
| collection1 = null; | ||
| collection2 = null; |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The clients collection1 and collection2 in TestTolerantSearch are set to null in AfterClass without being closed. This creates a potential resource leak. Either close these clients before nulling them, or verify that the SolrJettyTestRule handles cleanup of all client instances.
| collection1 = null; | |
| collection2 = null; | |
| if (collection1 != null) { | |
| collection1.close(); | |
| collection1 = null; | |
| } | |
| if (collection2 != null) { | |
| collection2.close(); | |
| collection2 = null; | |
| } |
| protected static final String DEFAULT_CORE = "foo"; | ||
| @ClassRule public static SolrJettyTestRule solrClientTestRule = new SolrJettyTestRule(); | ||
|
|
||
| protected static final String DEFAULT_COLLECTION = "collection1"; |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The constant DEFAULT_CORE has been renamed to DEFAULT_COLLECTION. However, this constant is being used throughout the test methods which may indicate an incomplete migration. Consider verifying that all references to the old constant name have been updated consistently. Additionally, DEFAULT_COLLECTION should likely use the same value as DEFAULT_TEST_CORENAME for consistency across the codebase.
| protected static final String DEFAULT_COLLECTION = "collection1"; | |
| protected static final String DEFAULT_COLLECTION = DEFAULT_TEST_CORENAME; |
| @SuppressSSL | ||
| public abstract class SolrExampleTests extends SolrExampleTestsBase { | ||
| private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); | ||
|
|
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The static block that calls ignoreException("uniqueKey") has been removed. If this exception ignore was serving a purpose in handling expected exceptions during tests, its removal could cause test failures or unexpected error logging. Verify that this removal is intentional and doesn't affect test behavior.
| static { | |
| ignoreException("uniqueKey"); | |
| } |
| protected SolrClient getSolrClient() { | ||
| if (client == null) { | ||
| client = createNewSolrClient(); | ||
| } | ||
| return client; | ||
| } |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getSolrClient method visibility has changed from public (with @Override) to protected (without @Override). This is a breaking change for any code that was relying on this being a public method. If this method is part of a base class contract, verify that all subclasses and callers can still access it appropriately.
This is a bit of an experiment. I wanted to see if I could reduce the amount of effort to get our tests updated. Over time we've been accumulating tech debt in our tests, and addressing that manually appears pretty difficult!
In this PR I've checked in my prompt
prompt_to_use.mdthat I used in VS Code. My thought is that the most important aspect of this PR is crafting a really great prompt. Instead of reviewing and commenting on the changes made per individual test file, what I really want is review of the overall change, and feed that review BACK into my prompt. Then I will re-run the improved prompt and that hopefully will output the final set of changes. Maybe in this PR, maybe in another fresh PR with improved prompt.As an example of feeding back input, after running everything I noticed in one test it hardcoded a
127.0.0.1url, and so I addedPlease do not create hard coded urls like 127.0.0.1 in the tests.to prevent that in the future.There are three files that start with
MIGRATION_*.mdand they are somewhat messy AI generated status files. I wanted it to maintaintests_not_migrated.mdas the but it kind of forgot that file....