/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.pulsar.broker.service;

import java.util.concurrent.TimeUnit;
import lombok.Cleanup;
import org.apache.bookkeeper.mledger.ManagedLedgerConfig;
import org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl;
import org.apache.pulsar.broker.service.persistent.PersistentTopic;
import org.apache.pulsar.client.api.Consumer;
import org.apache.pulsar.client.api.Message;
import org.apache.pulsar.client.api.Producer;
import org.testng.Assert;
import org.testng.annotations.Test;

@Test(groups = "broker")
public class CurrentLedgerRolloverIfFullTest extends BrokerTestBase {

    @Override
    protected void setup() throws Exception {

    }

    @Override
    protected void cleanup() throws Exception {

    }

    @Test
    public void testCurrentLedgerRolloverIfFull() throws Exception {
        super.baseSetup();
        final String topicName = "persistent://prop/ns-abc/CurrentLedgerRolloverIfFullTest";

        @Cleanup
        Producer<byte[]> producer = pulsarClient.newProducer()
                .topic(topicName)
                .producerName("CurrentLedgerRolloverIfFullTest-producer-name")
                .create();

        @Cleanup
        Consumer<byte[]> consumer = pulsarClient.newConsumer()
                .topic(topicName)
                .subscriptionName("CurrentLedgerRolloverIfFullTest-subscriber-name")
                .subscribe();

        Topic topicRef = pulsar.getBrokerService().getTopicReference(topicName).get();
        Assert.assertNotNull(topicRef);
        PersistentTopic persistentTopic = (PersistentTopic) pulsar.getBrokerService().getOrCreateTopic(topicName).get();

        ManagedLedgerConfig managedLedgerConfig = persistentTopic.getManagedLedger().getConfig();
        managedLedgerConfig.setRetentionTime(1, TimeUnit.SECONDS);
        managedLedgerConfig.setMaxEntriesPerLedger(2);
        managedLedgerConfig.setMinimumRolloverTime(1, TimeUnit.MILLISECONDS);
        managedLedgerConfig.setMaximumRolloverTime(5, TimeUnit.MILLISECONDS);

        int msgNum = 10;
        for (int i = 0; i < msgNum; i++) {
            producer.send(new byte[1024 * 1024]);
        }

        ManagedLedgerImpl managedLedger = (ManagedLedgerImpl) persistentTopic.getManagedLedger();
        Assert.assertEquals(managedLedger.getLedgersInfoAsList().size(), msgNum / 2);

        for (int i = 0; i < msgNum; i++) {
            Message<byte[]> msg = consumer.receive(2, TimeUnit.SECONDS);
            Assert.assertNotNull(msg);
            consumer.acknowledge(msg);
        }

        // all the messages have been acknowledged
        // and all the ledgers have been removed except the the last ledger
        Thread.sleep(500);
        Assert.assertEquals(managedLedger.getLedgersInfoAsList().size(), 1);
        Assert.assertNotEquals(managedLedger.getCurrentLedgerSize(), 0);

        // trigger a ledger rollover
        // the last ledger will be closed and removed and we have one ledger for empty
        managedLedger.rollCurrentLedgerIfFull();
        Thread.sleep(1000);
        Assert.assertEquals(managedLedger.getLedgersInfoAsList().size(), 1);
        Assert.assertEquals(managedLedger.getTotalSize(), 0);
    }
}

@@ -845,16 +845,43 @@
 rvice;%0A%0A
+import java.time.Duration;%0A
 import j
@@ -1272,21 +1272,140 @@
 org.
-testng.Assert
+awaitility.Awaitility;%0Aimport org.testng.Assert;%0Aimport org.testng.annotations.AfterClass;%0Aimport org.testng.annotations.BeforeClass
 ;%0Aim
@@ -1531,24 +1531,41 @@
 TestBase %7B%0A%0A
+    @BeforeClass%0A
     @Overrid
@@ -1608,31 +1608,85 @@
 Exception %7B%0A
-%0A    %7D%0A
+        baseSetup();%0A    %7D%0A%0A    @AfterClass(alwaysRun = true)
 %0A    @Overri
@@ -1736,16 +1736,42 @@
 ption %7B%0A
+        internalCleanup();
 %0A    %7D%0A%0A
@@ -1853,35 +1853,8 @@
 n %7B%0A
-        super.baseSetup();%0A
     
@@ -3678,27 +3678,141 @@
     
-Thread.sleep(500);%0A
+Awaitility.await()%0A                .pollInterval(Duration.ofMillis(500L))%0A                .untilAsserted(() -%3E %7B%0A                    
     
@@ -3876,32 +3876,52 @@
 t().size(), 1);%0A
+                    
         Assert.a
@@ -3976,16 +3976,44 @@
 e(), 0);
+%0A                        %7D);
 %0A%0A      
@@ -4043,16 +4043,66 @@
 ollover%0A
+        managedLedger.rollCurrentLedgerIfFull();%0A%0A
         
@@ -4192,77 +4192,134 @@
     
-managedLedger.rollCurrentLedgerIfFull();%0A        Thread.sleep(1000);%0A
+Awaitility.await()%0A                .pollInterval(Duration.ofMillis(1000L))%0A                .untilAsserted(() -%3E %7B%0A            
     
@@ -4383,32 +4383,44 @@
 t().size(), 1);%0A
+            
         Assert.a
@@ -4461,20 +4461,40 @@
 Size(), 0);%0A
+                %7D);%0A
     %7D%0A%7D%0A

Fix flaky test CurrentLedgerRolloverIfFullTest (#10004)