Merge branch 'stable-3.1' into stable-3.2

* stable-3.1:
  PolyGerrit: Remove duplicate key from language map
  e2e-tests: add RestoreChange scenario
  Documentation: dev-bazel: Fix indent level
  PolyGerrit: Highlight tex files
  e2e-tests: add AbandonChange scenario
  Stop SPAMming Gerrit logs with 'Logging context is not empty'
  Update git submodules
  Update git submodules
  Update git submodules
  GitRepositoryManager should be responsible to enable/disable the GC
  e2e-tests: Fix regex to adapt to JSON_COMPACT

Change-Id: I20d16ee00010b96c60b7724ac46a303400dbc0fd
This commit is contained in:
Marco Miller 2021-03-10 17:04:17 -05:00
commit 17c4d8efa6
15 changed files with 540 additions and 302 deletions

View File

@ -258,7 +258,7 @@ refreshed and missing dependency JARs can be downloaded by running
with BUILD Files` button of link:https://ij.bazel.build[Bazel plugin,role=external,window=_blank].
[[documentation]]
=== Documentation
== Documentation
To build only the documentation for testing or static hosting:

View File

@ -0,0 +1,6 @@
[
{
"url": "HTTP_SCHEME://HOSTNAME:HTTP_PORT/a/changes/",
"number": "NUMBER"
}
]

View File

@ -0,0 +1,6 @@
[
{
"url": "HTTP_SCHEME://HOSTNAME:HTTP_PORT/a/changes/",
"number": "NUMBER"
}
]

View File

@ -0,0 +1,71 @@
// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.scenarios
import io.gatling.core.Predef.{atOnceUsers, _}
import io.gatling.core.feeder.FeederBuilder
import io.gatling.core.structure.ScenarioBuilder
import io.gatling.http.Predef.http
import scala.collection.mutable
import scala.concurrent.duration.DurationInt
class AbandonChange extends GerritSimulation {
private val data: FeederBuilder = jsonFile(resource).convert(keys).circular
private val projectName = className
private var numbersCopy: mutable.Queue[Int] = mutable.Queue[Int]()
private var createChange: Option[CreateChange] = Some(new CreateChange(projectName))
override def relativeRuntimeWeight = 10
def this(createChange: CreateChange) {
this()
this.createChange = Some(createChange)
}
val test: ScenarioBuilder = scenario(uniqueName)
.feed(data)
.exec(session => {
if (createChange.nonEmpty) {
if (numbersCopy.isEmpty) {
numbersCopy = createChange.get.numbers.clone()
}
}
session.set("number", numbersCopy.dequeue())
})
.exec(http(uniqueName).post("${url}${number}/abandon"))
private val createProject = new CreateProject(projectName)
private val deleteProject = new DeleteProject(projectName)
setUp(
createProject.test.inject(
nothingFor(stepWaitTime(createProject) seconds),
atOnceUsers(single)
),
createChange.get.test.inject(
nothingFor(stepWaitTime(createChange.get) seconds),
atOnceUsers(numberOfUsers)
),
test.inject(
nothingFor(stepWaitTime(this) seconds),
atOnceUsers(numberOfUsers)
),
deleteProject.test.inject(
nothingFor(stepWaitTime(deleteProject) seconds),
atOnceUsers(single)
),
).protocols(httpProtocol)
}

View File

@ -37,7 +37,7 @@ class CheckProjectsCacheFlushEntries extends CacheFlushSimulation {
}
})
.exec(http(uniqueName).get("${url}")
.check(regex("\"" + memKey + "\": (\\d+)")
.check(regex("\"" + memKey + "\":(\\d+)")
.is(session => session(entriesKey).as[String])))
setUp(

View File

@ -23,7 +23,7 @@ class GetMasterBranchRevision extends ProjectSimulation {
private val data: FeederBuilder = jsonFile(resource).convert(keys).queue
var revision: Option[String] = None
val revisionKey = "revision"
val revisionPattern: String = "\"" + revisionKey + "\": \"(.+)\""
val revisionPattern: String = "\"" + revisionKey + "\":\"(.+)\""
val test: ScenarioBuilder = scenario(uniqueName)
.feed(data)

View File

@ -30,7 +30,7 @@ class GetProjectsCacheEntries extends CacheFlushSimulation {
val test: ScenarioBuilder = scenario(uniqueName)
.feed(data)
.exec(http(uniqueName).get("${url}")
.check(regex("\"" + memKey + "\": (\\d+)").saveAs(entriesKey)))
.check(regex("\"" + memKey + "\":(\\d+)").saveAs(entriesKey)))
.exec(session => {
if (consumer.nonEmpty) {
consumer.get.entriesBeforeFlush(session(entriesKey).as[Int])

View File

@ -0,0 +1,74 @@
// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.scenarios
import io.gatling.core.Predef.{atOnceUsers, _}
import io.gatling.core.feeder.FeederBuilder
import io.gatling.core.structure.ScenarioBuilder
import io.gatling.http.Predef.http
import scala.collection.mutable
import scala.concurrent.duration.DurationInt
class RestoreChange extends GerritSimulation {
private val data: FeederBuilder = jsonFile(resource).convert(keys).circular
private val projectName = className
private var numbersCopy: mutable.Queue[Int] = mutable.Queue[Int]()
override def relativeRuntimeWeight = 10
private val test: ScenarioBuilder = scenario(uniqueName)
.feed(data)
.exec(session => {
if (numbersCopy.isEmpty) {
numbersCopy = createChange.numbers.clone()
}
session.set("number", numbersCopy.dequeue())
}
).exec(http(uniqueName).post("${url}${number}/restore"))
private val createProject = new CreateProject(projectName)
private val createChange = new CreateChange(projectName)
private val abandonChange = new AbandonChange(createChange)
private val deleteChange = new DeleteChange(createChange)
private val deleteProject = new DeleteProject(projectName)
setUp(
createProject.test.inject(
nothingFor(stepWaitTime(createProject) seconds),
atOnceUsers(single)
),
createChange.test.inject(
nothingFor(stepWaitTime(createChange) seconds),
atOnceUsers(numberOfUsers)
),
abandonChange.test.inject(
nothingFor(stepWaitTime(abandonChange) seconds),
atOnceUsers(numberOfUsers)
),
test.inject(
nothingFor(stepWaitTime(this) seconds),
atOnceUsers(numberOfUsers)
),
deleteChange.test.inject(
nothingFor(stepWaitTime(deleteChange) seconds),
atOnceUsers(numberOfUsers)
),
deleteProject.test.inject(
nothingFor(stepWaitTime(deleteProject) seconds),
atOnceUsers(single)
),
).protocols(httpProtocol)
}

View File

@ -57,4 +57,13 @@ public interface GitRepositoryManager {
/** @return set of all known projects, sorted by natural NameKey order. */
SortedSet<Project.NameKey> list();
/**
* Check if garbage collection can be performed by the repository manager.
*
* @return true if repository can perform garbage collection.
*/
default Boolean canPerformGC() {
return false;
}
}

View File

@ -199,6 +199,11 @@ public class LocalDiskRepositoryManager implements GitRepositoryManager {
}
}
@Override
public Boolean canPerformGC() {
return true;
}
private boolean isUnreasonableName(Project.NameKey nameKey) {
final String name = nameKey.get();

View File

@ -81,10 +81,7 @@ public class LoggingContext extends com.google.common.flogger.backend.system.Log
}
public boolean isEmpty() {
return tags.get() == null
&& forceLogging.get() == null
&& performanceLogging.get() == null
&& performanceLogRecords.get() == null;
return tags.get() == null && forceLogging.get() == null && performanceLogging.get() == null;
}
public void clear() {

View File

@ -29,7 +29,6 @@ import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.server.config.UrlFormatter;
import com.google.gerrit.server.git.GarbageCollection;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.ioutil.HexFormat;
import com.google.gerrit.server.project.ProjectResource;
@ -67,7 +66,7 @@ public class GarbageCollect
DynamicItem<UrlFormatter> urlFormatter) {
this.workQueue = workQueue;
this.urlFormatter = urlFormatter;
this.canGC = repoManager instanceof LocalDiskRepositoryManager;
this.canGC = repoManager.canPerformGC();
this.garbageCollectionFactory = garbageCollectionFactory;
}

View File

@ -0,0 +1,54 @@
// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.server.git;
import static com.google.common.truth.Truth.assertThat;
import com.google.gerrit.entities.Project.NameKey;
import java.util.SortedSet;
import org.eclipse.jgit.lib.Repository;
import org.junit.Before;
import org.junit.Test;
public class GitRepositoryManagerTest {
private GitRepositoryManager objectUnderTest;
@Before
public void setUp() throws Exception {
objectUnderTest = new TestGitRepositoryManager();
}
@Test
public void shouldReturnFalseWhenDefaultCanPerformGC() {
assertThat(objectUnderTest.canPerformGC()).isFalse();
}
private static class TestGitRepositoryManager implements GitRepositoryManager {
@Override
public Repository openRepository(NameKey name) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public Repository createRepository(NameKey name) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public SortedSet<NameKey> list() {
throw new UnsupportedOperationException("Not implemented");
}
}
}

View File

@ -252,6 +252,11 @@ public class LocalDiskRepositoryManagerTest {
() -> newRepoManager.createRepository(Project.nameKey("A")));
}
@Test
public void testRepositoryCanPerformGC() throws Exception {
assertThat(repoManager.canPerformGC()).isTrue();
}
private void createSymLink(Project.NameKey project, String link) throws IOException {
Path base = repoManager.getBasePath(project);
Path projectDir = base.resolve(project.get() + ".git");

File diff suppressed because one or more lines are too long