From f47257bdf1cb87afa3389866b76037c4f5d89002 Mon Sep 17 00:00:00 2001 From: Robert Sandell Date: Fri, 12 Feb 2021 19:51:53 +0100 Subject: [PATCH] [JENKINS-64840] Fix searching multiple update sites (#5281) --- core/src/main/java/hudson/PluginManager.java | 5 +- .../test/java/hudson/PluginManagerTest.java | 40 +++++++++ .../plugins/search-test-update-center1.json | 89 +++++++++++++++++++ .../plugins/search-test-update-center2.json | 38 ++++++++ 4 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 test/src/test/resources/plugins/search-test-update-center1.json create mode 100644 test/src/test/resources/plugins/search-test-update-center2.json diff --git a/core/src/main/java/hudson/PluginManager.java b/core/src/main/java/hudson/PluginManager.java index 61f222915d6e..51b87fc270c1 100644 --- a/core/src/main/java/hudson/PluginManager.java +++ b/core/src/main/java/hudson/PluginManager.java @@ -1355,7 +1355,7 @@ public static boolean isNonMetaLabel(String label) { public HttpResponse doPluginsSearch(@QueryParameter String query, @QueryParameter Integer limit) { List plugins = new ArrayList<>(); for (UpdateSite site : Jenkins.get().getUpdateCenter().getSiteList()) { - plugins = site.getAvailables().stream() + List sitePlugins = site.getAvailables().stream() .filter(plugin -> { if (StringUtils.isBlank(query)) { return true; @@ -1369,7 +1369,7 @@ public HttpResponse doPluginsSearch(@QueryParameter String query, @QueryParamete .anyMatch(category -> StringUtils.containsIgnoreCase(category, query)) || plugin.hasWarnings() && query.equalsIgnoreCase("warning:"); }) - .limit(limit) + .limit(Math.max(limit - plugins.size(), 1)) .sorted((o1, o2) -> { String o1DisplayName = o1.getDisplayName(); if (o1.name.equalsIgnoreCase(query) || @@ -1453,6 +1453,7 @@ public HttpResponse doPluginsSearch(@QueryParameter String query, @QueryParamete return jsonObject; }) .collect(toList()); + plugins.addAll(sitePlugins); if (plugins.size() >= limit) { break; } diff --git a/test/src/test/java/hudson/PluginManagerTest.java b/test/src/test/java/hudson/PluginManagerTest.java index bea7ba957572..bf324710eb12 100644 --- a/test/src/test/java/hudson/PluginManagerTest.java +++ b/test/src/test/java/hudson/PluginManagerTest.java @@ -663,4 +663,44 @@ public void doNotThrowWithUnknownPlugins() throws Exception { // This would throw NPE uc.getPluginsWithUnavailableUpdates(); } + + @Test @Issue("JENKINS-64840") + public void searchMultipleUpdateSites() throws Exception { + PersistedList sites = r.jenkins.getUpdateCenter().getSites(); + sites.clear(); + URL url = PluginManagerTest.class.getResource("/plugins/search-test-update-center1.json"); + UpdateSite site = new UpdateSite(UpdateCenter.ID_DEFAULT, url.toString()); + sites.add(site); + assertEquals(FormValidation.ok(), site.updateDirectly(false).get()); + assertNotNull(site.getData()); + url = PluginManagerTest.class.getResource("/plugins/search-test-update-center2.json"); + site = new UpdateSite("secondary", url.toString()); + sites.add(site); + final Future future = site.updateDirectly(false); + if (future != null) { + assertEquals(FormValidation.ok(), future.get()); + } + assertNotNull(site.getData()); + + //Dummy plugin is found in the second site (should have worked before the fix) + JenkinsRule.JSONWebResponse response = r.getJSON("pluginManager/pluginsSearch?query=dummy&limit=5"); + JSONObject json = response.getJSONObject(); + assertTrue(json.has("data")); + JSONArray data = json.getJSONArray("data"); + assertEquals("Should be one search hit for dummy", 1, data.size()); + + //token-macro plugin is found in the first site (didn't work before the fix) + response = r.getJSON("pluginManager/pluginsSearch?query=token&limit=5"); + json = response.getJSONObject(); + assertTrue(json.has("data")); + data = json.getJSONArray("data"); + assertEquals("Should be one search hit for token", 1, data.size()); + + //hello-world plugin is found in the first site and hello-huston in the second (didn't work before the fix) + response = r.getJSON("pluginManager/pluginsSearch?query=hello&limit=5"); + json = response.getJSONObject(); + assertTrue(json.has("data")); + data = json.getJSONArray("data"); + assertEquals("Should be two search hits for hello", 2, data.size()); + } } diff --git a/test/src/test/resources/plugins/search-test-update-center1.json b/test/src/test/resources/plugins/search-test-update-center1.json new file mode 100644 index 000000000000..f3b653518b31 --- /dev/null +++ b/test/src/test/resources/plugins/search-test-update-center1.json @@ -0,0 +1,89 @@ +updateCenter.post( +{"connectionCheckUrl":"http://www.google.com/", + "core": { + "buildDate": "Dec 31, 1969", + "name": "core", + "url": "jenkins.war", + "version": "23" + }, + "id": "default", + "plugins": { + "credentials": { + "buildDate": "Apr 04, 2016", + "dependencies": [ + { + "name": "icon-shim", + "optional": false, + "version":"2.0.2" + } + ], + "developers": [], + "excerpt": "This plugin allows you to store credentials in Jenkins.", + "gav": "org.jenkins-ci.plugins:credentials:1.27", + "labels": [], + "name": "credentials", + "previousTimestamp": "2016-03-24T01:19:58.00Z", + "previousVersion": "1.26", + "releaseTimestamp": "2016-04-04T16:26:54.00Z", + "requiredCore": "1.565", + "scm": "github.com", + "sha1": "XWJpfL8B2x7qrISJg7IY2ZTPxFk=", + "title": "Credentials Plugin", + "url": "credentials.hpi", + "version": "1.27", + "wiki": "https://wiki.jenkins-ci.org/display/JENKINS/Credentials+Plugin" + }, + "icon-shim": { + "buildDate": "Feb 23, 2016", + "dependencies": [], + "developers": [], + "excerpt": "This plugin allows other Jenkins plugins to take advantage of the tag. ", + "gav": "org.jenkins-ci.plugins.icon-shim:icon-shim:2.0.3", + "labels": ["ui"], + "name": "icon-shim", + "previousTimestamp": "2016-01-09T20:01:12.00Z", + "previousVersion": "2.0.2", + "releaseTimestamp": "2016-02-23T23:08:18.00Z", + "requiredCore": "1.609", + "scm": "github.com", + "sha1": "umtSUbNwIuqU6JGEQcBxqFt1X24=", + "title": "Icon Shim Plugin", + "url": "icon-shim.hpi", + "version": "2.0.3", + "wiki": "https://wiki.jenkins-ci.org/display/JENKINS/Icon+Shim+Plugin" + }, + "token-macro": { + "buildDate": "Dec 14, 2015", + "dependencies": [], + "developers": [], + "excerpt": "This plugin adds reusable macro expansion capability for other plugins to use", + "gav": "org.jenkins-ci.plugins:token-macro:1.12.1", + "labels": [], + "name": "token-macro", + "previousTimestamp": "2015-12-11T08:27:18.00Z", + "previousVersion": "1.12", + "releaseTimestamp": "2015-12-14T18:07:56.00Z", + "requiredCore": "1.609.2", + "scm": "github.com", + "sha1": "TV61PGo+od75URp3maLGUFJ768k=", + "title": "Token Macro Plugin", + "url": "token-macro.hpi", + "version": "1.9", + "wiki": "https://wiki.jenkins-ci.org/display/JENKINS/Token+Macro+Plugin" + }, + "hello-world": { + "buildDate": "Dec 17, 2008", + "dependencies": [], + "developers": [], + "excerpt": "…", + "name": "hello-=world", + "requiredCore": "1.100", + "sha1": "wtzlcjUKiMcg90H5CTYkGX6+r8Y=", + "title": "Hello World", + "url": "http://nowhere.net/hello-world.hpi", + "version": "1.0" + } + }, + "updateCenterVersion": 1 +} +); diff --git a/test/src/test/resources/plugins/search-test-update-center2.json b/test/src/test/resources/plugins/search-test-update-center2.json new file mode 100644 index 000000000000..805113249ac5 --- /dev/null +++ b/test/src/test/resources/plugins/search-test-update-center2.json @@ -0,0 +1,38 @@ +updateCenter.post( +{"connectionCheckUrl":"http://www.google.com/", + "core": { + "buildDate": "Dec 31, 1969", + "name": "core", + "url": "jenkins.war", + "version": "23" + }, + "id": "secondary", + "plugins": { + "hello-huston": { + "buildDate": "Dec 17, 2008", + "dependencies": [], + "developers": [], + "excerpt": "…", + "name": "hello-huston", + "requiredCore": "1.100", + "sha1": "wtzlcjUKiMcg90H5CTYkGX6+r8Y=", + "title": "Hello Huston", + "url": "http://nowhere.net/hello-huston.hpi", + "version": "1.0" + }, + "dummy": { + "buildDate": "Dec 17, 2008", + "dependencies": [], + "developers": [], + "excerpt": "…", + "name": "dummy", + "requiredCore": "1.100", + "sha1": "wtzlcjUKiMcg90H5CTYkGX6+r8Y=", + "title": "Dummy", + "url": "http://nowhere.net/dummy.hpi", + "version": "1.0" + } + }, + "updateCenterVersion": 1 +} +);