Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0964a675 authored by Kweku Adams's avatar Kweku Adams
Browse files

Track basic TARE statistics.

Track some basic statistics to see how TARE performs over time. They'll
only be kept and viewable locally. We can continue to refine them to
determine what's useful and necessary.

Bug: 158300259
Test: atest frameworks/base/services/tests/servicestests/src/com/android/server/tare
Test: atest frameworks/base/services/tests/mockingservicestests/src/com/android/server/tare
Change-Id: Ia408b9fc2b688a850fe8974ac473613711711a15
parent 96ad5cca
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ class Agent {

    private final Object mLock;
    private final Handler mHandler;
    private final Analyst mAnalyst;
    private final InternalResourceService mIrs;
    private final Scribe mScribe;

@@ -110,10 +111,11 @@ class Agent {
     */
    private static final int MSG_CHECK_INDIVIDUAL_AFFORDABILITY = 1;

    Agent(@NonNull InternalResourceService irs, @NonNull Scribe scribe) {
    Agent(@NonNull InternalResourceService irs, @NonNull Scribe scribe, @NonNull Analyst analyst) {
        mLock = irs.getLock();
        mIrs = irs;
        mScribe = scribe;
        mAnalyst = analyst;
        mHandler = new AgentHandler(TareHandlerThread.get().getLooper());
        mAppStandbyInternal = LocalServices.getService(AppStandbyInternal.class);
        mBalanceThresholdAlarmQueue = new BalanceThresholdAlarmQueue(
@@ -443,7 +445,7 @@ class Agent {
    void recordTransactionLocked(final int userId, @NonNull final String pkgName,
            @NonNull Ledger ledger, @NonNull Ledger.Transaction transaction,
            final boolean notifyOnAffordabilityChange) {
        if (transaction.delta == 0) {
        if (!DEBUG && transaction.delta == 0) {
            // Skip recording transactions with a delta of 0 to save on space.
            return;
        }
@@ -471,6 +473,7 @@ class Agent {
        }
        ledger.recordTransaction(transaction);
        mScribe.adjustRemainingConsumableCakesLocked(-transaction.ctp);
        mAnalyst.noteTransaction(transaction);
        if (transaction.delta != 0 && notifyOnAffordabilityChange) {
            final ArraySet<ActionAffordabilityNote> actionAffordabilityNotes =
                    mActionAffordabilityNotes.get(userId, pkgName);
+290 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.android.server.tare;

import static com.android.server.tare.EconomicPolicy.TYPE_ACTION;
import static com.android.server.tare.EconomicPolicy.TYPE_REGULATION;
import static com.android.server.tare.EconomicPolicy.TYPE_REWARD;
import static com.android.server.tare.EconomicPolicy.getEventType;
import static com.android.server.tare.TareUtils.cakeToString;

import android.annotation.NonNull;
import android.util.IndentingPrintWriter;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

/**
 * Responsible for maintaining statistics and analysis of TARE's performance.
 */
public class Analyst {
    private static final String TAG = "TARE-" + Analyst.class.getSimpleName();
    private static final boolean DEBUG = InternalResourceService.DEBUG
            || Log.isLoggable(TAG, Log.DEBUG);

    private static final int NUM_PERIODS_TO_RETAIN = 8;

    static final class Report {
        /** How much the battery was discharged over the tracked period. */
        public int cumulativeBatteryDischarge = 0;
        public int currentBatteryLevel = 0;
        /**
         * Profit from performing actions. This excludes special circumstances where we charge the
         * app
         * less than the action's CTP.
         */
        public long cumulativeProfit = 0;
        public int numProfitableActions = 0;
        /**
         * Losses from performing actions for special circumstances (eg. for a TOP app) where we
         * charge
         * the app less than the action's CTP.
         */
        public long cumulativeLoss = 0;
        public int numUnprofitableActions = 0;
        /**
         * The total number of rewards given to apps over this period.
         */
        public long cumulativeRewards = 0;
        public int numRewards = 0;
        /**
         * Regulations that increased an app's balance.
         */
        public long cumulativePositiveRegulations = 0;
        public int numPositiveRegulations = 0;
        /**
         * Regulations that decreased an app's balance.
         */
        public long cumulativeNegativeRegulations = 0;
        public int numNegativeRegulations = 0;

        private void clear() {
            cumulativeBatteryDischarge = 0;
            currentBatteryLevel = 0;
            cumulativeProfit = 0;
            numProfitableActions = 0;
            cumulativeLoss = 0;
            numUnprofitableActions = 0;
            cumulativeRewards = 0;
            numRewards = 0;
            cumulativePositiveRegulations = 0;
            numPositiveRegulations = 0;
            cumulativeNegativeRegulations = 0;
            numNegativeRegulations = 0;
        }
    }

    private int mPeriodIndex = 0;
    /** How much the battery was discharged over the tracked period. */
    private final Report[] mReports = new Report[NUM_PERIODS_TO_RETAIN];

    /** Returns the list of most recent reports, with the oldest report first. */
    @NonNull
    List<Report> getReports() {
        final List<Report> list = new ArrayList<>(NUM_PERIODS_TO_RETAIN);
        for (int i = 1; i <= NUM_PERIODS_TO_RETAIN; ++i) {
            final int idx = (mPeriodIndex + i) % NUM_PERIODS_TO_RETAIN;
            final Report report = mReports[idx];
            if (report != null) {
                list.add(report);
            }
        }
        return list;
    }

    /**
     * Tracks the given reports instead of whatever is currently saved. Reports should be ordered
     * oldest to most recent.
     */
    void loadReports(@NonNull List<Report> reports) {
        final int numReports = reports.size();
        mPeriodIndex = Math.max(0, numReports - 1);
        for (int i = 0; i < NUM_PERIODS_TO_RETAIN; ++i) {
            if (i < numReports) {
                mReports[i] = reports.get(i);
            } else {
                mReports[i] = null;
            }
        }
    }

    void noteBatteryLevelChange(int newBatteryLevel) {
        if (newBatteryLevel == 100 && mReports[mPeriodIndex] != null
                && mReports[mPeriodIndex].currentBatteryLevel < newBatteryLevel) {
            mPeriodIndex = (mPeriodIndex + 1) % NUM_PERIODS_TO_RETAIN;
            if (mReports[mPeriodIndex] != null) {
                final Report report = mReports[mPeriodIndex];
                report.clear();
                report.currentBatteryLevel = newBatteryLevel;
                return;
            }
        }

        if (mReports[mPeriodIndex] == null) {
            Report report = new Report();
            mReports[mPeriodIndex] = report;
            report.currentBatteryLevel = newBatteryLevel;
            return;
        }

        final Report report = mReports[mPeriodIndex];
        if (newBatteryLevel < report.currentBatteryLevel) {
            report.cumulativeBatteryDischarge += (report.currentBatteryLevel - newBatteryLevel);
        }
        report.currentBatteryLevel = newBatteryLevel;
    }

    void noteTransaction(@NonNull Ledger.Transaction transaction) {
        if (mReports[mPeriodIndex] == null) {
            mReports[mPeriodIndex] = new Report();
        }
        final Report report = mReports[mPeriodIndex];
        switch (getEventType(transaction.eventId)) {
            case TYPE_ACTION:
                // For now, assume all instances where price < CTP is a special instance.
                // TODO: add an explicit signal for special circumstances
                if (-transaction.delta > transaction.ctp) {
                    report.cumulativeProfit += (-transaction.delta - transaction.ctp);
                    report.numProfitableActions++;
                } else if (-transaction.delta < transaction.ctp) {
                    report.cumulativeLoss += (transaction.ctp + transaction.delta);
                    report.numUnprofitableActions++;
                }
                break;
            case TYPE_REGULATION:
                if (transaction.delta > 0) {
                    report.cumulativePositiveRegulations += transaction.delta;
                    report.numPositiveRegulations++;
                } else if (transaction.delta < 0) {
                    report.cumulativeNegativeRegulations -= transaction.delta;
                    report.numNegativeRegulations++;
                }
                break;
            case TYPE_REWARD:
                if (transaction.delta != 0) {
                    report.cumulativeRewards += transaction.delta;
                    report.numRewards++;
                }
                break;
        }
    }

    void tearDown() {
        for (int i = 0; i < mReports.length; ++i) {
            mReports[i] = null;
        }
        mPeriodIndex = 0;
    }

    @NonNull
    private String padStringWithSpaces(@NonNull String text, int targetLength) {
        // Make sure to have at least one space on either side.
        final int padding = Math.max(2, targetLength - text.length()) >>> 1;
        return " ".repeat(padding) + text + " ".repeat(padding);
    }

    void dump(IndentingPrintWriter pw) {
        pw.println("Reports:");
        pw.increaseIndent();
        pw.print("      Total Discharge");
        final int statColsLength = 47;
        pw.print(padStringWithSpaces("Profit (avg/action : avg/discharge)", statColsLength));
        pw.print(padStringWithSpaces("Loss (avg/action : avg/discharge)", statColsLength));
        pw.print(padStringWithSpaces("Rewards (avg/reward : avg/discharge)", statColsLength));
        pw.print(padStringWithSpaces("+Regs (avg/reg : avg/discharge)", statColsLength));
        pw.print(padStringWithSpaces("-Regs (avg/reg : avg/discharge)", statColsLength));
        pw.println();
        for (int r = 0; r < NUM_PERIODS_TO_RETAIN; ++r) {
            final int idx = (mPeriodIndex - r + NUM_PERIODS_TO_RETAIN) % NUM_PERIODS_TO_RETAIN;
            final Report report = mReports[idx];
            if (report == null) {
                continue;
            }
            pw.print("t-");
            pw.print(r);
            pw.print(":  ");
            pw.print(padStringWithSpaces(Integer.toString(report.cumulativeBatteryDischarge), 15));
            if (report.numProfitableActions > 0) {
                final String perDischarge = report.cumulativeBatteryDischarge > 0
                        ? cakeToString(report.cumulativeProfit / report.cumulativeBatteryDischarge)
                        : "N/A";
                pw.print(padStringWithSpaces(String.format("%s (%s : %s)",
                                cakeToString(report.cumulativeProfit),
                                cakeToString(report.cumulativeProfit / report.numProfitableActions),
                                perDischarge),
                        statColsLength));
            } else {
                pw.print(padStringWithSpaces("N/A", statColsLength));
            }
            if (report.numUnprofitableActions > 0) {
                final String perDischarge = report.cumulativeBatteryDischarge > 0
                        ? cakeToString(report.cumulativeLoss / report.cumulativeBatteryDischarge)
                        : "N/A";
                pw.print(padStringWithSpaces(String.format("%s (%s : %s)",
                                cakeToString(report.cumulativeLoss),
                                cakeToString(report.cumulativeLoss / report.numUnprofitableActions),
                                perDischarge),
                        statColsLength));
            } else {
                pw.print(padStringWithSpaces("N/A", statColsLength));
            }
            if (report.numRewards > 0) {
                final String perDischarge = report.cumulativeBatteryDischarge > 0
                        ? cakeToString(report.cumulativeRewards / report.cumulativeBatteryDischarge)
                        : "N/A";
                pw.print(padStringWithSpaces(String.format("%s (%s : %s)",
                                cakeToString(report.cumulativeRewards),
                                cakeToString(report.cumulativeRewards / report.numRewards),
                                perDischarge),
                        statColsLength));
            } else {
                pw.print(padStringWithSpaces("N/A", statColsLength));
            }
            if (report.numPositiveRegulations > 0) {
                final String perDischarge = report.cumulativeBatteryDischarge > 0
                        ? cakeToString(
                        report.cumulativePositiveRegulations / report.cumulativeBatteryDischarge)
                        : "N/A";
                pw.print(padStringWithSpaces(String.format("%s (%s : %s)",
                                cakeToString(report.cumulativePositiveRegulations),
                                cakeToString(report.cumulativePositiveRegulations
                                        / report.numPositiveRegulations),
                                perDischarge),
                        statColsLength));
            } else {
                pw.print(padStringWithSpaces("N/A", statColsLength));
            }
            if (report.numNegativeRegulations > 0) {
                final String perDischarge = report.cumulativeBatteryDischarge > 0
                        ? cakeToString(
                        report.cumulativeNegativeRegulations / report.cumulativeBatteryDischarge)
                        : "N/A";
                pw.print(padStringWithSpaces(String.format("%s (%s : %s)",
                                cakeToString(report.cumulativeNegativeRegulations),
                                cakeToString(report.cumulativeNegativeRegulations
                                        / report.numNegativeRegulations),
                                perDischarge),
                        statColsLength));
            } else {
                pw.print(padStringWithSpaces("N/A", statColsLength));
            }
            pw.println();
        }
        pw.decreaseIndent();
    }
}
+9 −2
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ public class InternalResourceService extends SystemService {
    private IDeviceIdleController mDeviceIdleController;

    private final Agent mAgent;
    private final Analyst mAnalyst;
    private final ConfigObserver mConfigObserver;
    private final EconomyManagerStub mEconomyManagerStub;
    private final Scribe mScribe;
@@ -254,9 +255,10 @@ public class InternalResourceService extends SystemService {
        mPackageManager = context.getPackageManager();
        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
        mEconomyManagerStub = new EconomyManagerStub();
        mScribe = new Scribe(this);
        mAnalyst = new Analyst();
        mScribe = new Scribe(this, mAnalyst);
        mCompleteEconomicPolicy = new CompleteEconomicPolicy(this);
        mAgent = new Agent(this, mScribe);
        mAgent = new Agent(this, mScribe, mAnalyst);

        mConfigObserver = new ConfigObserver(mHandler, context);

@@ -375,6 +377,7 @@ public class InternalResourceService extends SystemService {
    void onBatteryLevelChanged() {
        synchronized (mLock) {
            final int newBatteryLevel = getCurrentBatteryLevel();
            mAnalyst.noteBatteryLevelChange(newBatteryLevel);
            final boolean increased = newBatteryLevel > mCurrentBatteryLevel;
            if (increased) {
                mAgent.distributeBasicIncomeLocked(newBatteryLevel);
@@ -741,6 +744,7 @@ public class InternalResourceService extends SystemService {
        }
        synchronized (mLock) {
            mAgent.tearDownLocked();
            mAnalyst.tearDown();
            mCompleteEconomicPolicy.tearDown();
            mExemptedApps.clear();
            mExemptListLoaded = false;
@@ -1145,6 +1149,9 @@ public class InternalResourceService extends SystemService {

            pw.println();
            mAgent.dumpLocked(pw);

            pw.println();
            mAnalyst.dump(pw);
        }
    }
}
+77 −3
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ public class Scribe {
    private static final String XML_TAG_TARE = "tare";
    private static final String XML_TAG_TRANSACTION = "transaction";
    private static final String XML_TAG_USER = "user";
    private static final String XML_TAG_PERIOD_REPORT = "report";

    private static final String XML_ATTR_CTP = "ctp";
    private static final String XML_ATTR_DELTA = "delta";
@@ -86,6 +87,18 @@ public class Scribe {
    private static final String XML_ATTR_LAST_RECLAMATION_TIME = "lastReclamationTime";
    private static final String XML_ATTR_REMAINING_CONSUMABLE_CAKES = "remainingConsumableCakes";
    private static final String XML_ATTR_CONSUMPTION_LIMIT = "consumptionLimit";
    private static final String XML_ATTR_PR_DISCHARGE = "discharge";
    private static final String XML_ATTR_PR_BATTERY_LEVEL = "batteryLevel";
    private static final String XML_ATTR_PR_PROFIT = "profit";
    private static final String XML_ATTR_PR_NUM_PROFIT = "numProfits";
    private static final String XML_ATTR_PR_LOSS = "loss";
    private static final String XML_ATTR_PR_NUM_LOSS = "numLoss";
    private static final String XML_ATTR_PR_REWARDS = "rewards";
    private static final String XML_ATTR_PR_NUM_REWARDS = "numRewards";
    private static final String XML_ATTR_PR_POS_REGULATIONS = "posRegulations";
    private static final String XML_ATTR_PR_NUM_POS_REGULATIONS = "numPosRegulations";
    private static final String XML_ATTR_PR_NEG_REGULATIONS = "negRegulations";
    private static final String XML_ATTR_PR_NUM_NEG_REGULATIONS = "numNegRegulations";

    /** Version of the file schema. */
    private static final int STATE_FILE_VERSION = 0;
@@ -94,6 +107,7 @@ public class Scribe {

    private final AtomicFile mStateFile;
    private final InternalResourceService mIrs;
    private final Analyst mAnalyst;

    @GuardedBy("mIrs.getLock()")
    private long mLastReclamationTime;
@@ -107,13 +121,14 @@ public class Scribe {
    private final Runnable mCleanRunnable = this::cleanupLedgers;
    private final Runnable mWriteRunnable = this::writeState;

    Scribe(InternalResourceService irs) {
        this(irs, Environment.getDataSystemDirectory());
    Scribe(InternalResourceService irs, Analyst analyst) {
        this(irs, analyst, Environment.getDataSystemDirectory());
    }

    @VisibleForTesting
    Scribe(InternalResourceService irs, File dataDir) {
    Scribe(InternalResourceService irs, Analyst analyst, File dataDir) {
        mIrs = irs;
        mAnalyst = analyst;

        final File tareDir = new File(dataDir, "tare");
        //noinspection ResultOfMethodCallIgnored
@@ -210,6 +225,7 @@ public class Scribe {
            }
        }

        final List<Analyst.Report> reports = new ArrayList<>();
        try (FileInputStream fis = mStateFile.openRead()) {
            TypedXmlPullParser parser = Xml.resolvePullParser(fis);

@@ -263,11 +279,15 @@ public class Scribe {
                                readUserFromXmlLocked(
                                        parser, installedPackagesPerUser, endTimeCutoff));
                        break;
                    case XML_TAG_PERIOD_REPORT:
                        reports.add(readReportFromXml(parser));
                        break;
                    default:
                        Slog.e(TAG, "Unexpected tag: " + tagName);
                        break;
                }
            }
            mAnalyst.loadReports(reports);
            scheduleCleanup(earliestEndTime);
        } catch (IOException | XmlPullParserException e) {
            Slog.wtf(TAG, "Error reading state from disk", e);
@@ -457,6 +477,37 @@ public class Scribe {
        return earliestEndTime;
    }


    /**
     * @param parser Xml parser at the beginning of a {@link #XML_TAG_PERIOD_REPORT} tag. The next
     *               "parser.next()" call will take the parser into the body of the report tag.
     * @return Newly instantiated Report holding all the information we just read out of the xml tag
     */
    @NonNull
    private static Analyst.Report readReportFromXml(TypedXmlPullParser parser)
            throws XmlPullParserException, IOException {
        final Analyst.Report report = new Analyst.Report();

        report.cumulativeBatteryDischarge = parser.getAttributeInt(null, XML_ATTR_PR_DISCHARGE);
        report.currentBatteryLevel = parser.getAttributeInt(null, XML_ATTR_PR_BATTERY_LEVEL);
        report.cumulativeProfit = parser.getAttributeLong(null, XML_ATTR_PR_PROFIT);
        report.numProfitableActions = parser.getAttributeInt(null, XML_ATTR_PR_NUM_PROFIT);
        report.cumulativeLoss = parser.getAttributeLong(null, XML_ATTR_PR_LOSS);
        report.numUnprofitableActions = parser.getAttributeInt(null, XML_ATTR_PR_NUM_LOSS);
        report.cumulativeRewards = parser.getAttributeLong(null, XML_ATTR_PR_REWARDS);
        report.numRewards = parser.getAttributeInt(null, XML_ATTR_PR_NUM_REWARDS);
        report.cumulativePositiveRegulations =
                parser.getAttributeLong(null, XML_ATTR_PR_POS_REGULATIONS);
        report.numPositiveRegulations =
                parser.getAttributeInt(null, XML_ATTR_PR_NUM_POS_REGULATIONS);
        report.cumulativeNegativeRegulations =
                parser.getAttributeLong(null, XML_ATTR_PR_NEG_REGULATIONS);
        report.numNegativeRegulations =
                parser.getAttributeInt(null, XML_ATTR_PR_NUM_NEG_REGULATIONS);

        return report;
    }

    private void scheduleCleanup(long earliestEndTime) {
        if (earliestEndTime == Long.MAX_VALUE) {
            return;
@@ -501,6 +552,11 @@ public class Scribe {
                            writeUserLocked(out, userId));
                }

                List<Analyst.Report> reports = mAnalyst.getReports();
                for (int i = 0, size = reports.size(); i < size; ++i) {
                    writeReport(out, reports.get(i));
                }

                out.endTag(null, XML_TAG_TARE);

                out.endDocument();
@@ -560,6 +616,24 @@ public class Scribe {
        out.endTag(null, XML_TAG_TRANSACTION);
    }

    private static void writeReport(@NonNull TypedXmlSerializer out,
            @NonNull Analyst.Report report) throws IOException {
        out.startTag(null, XML_TAG_PERIOD_REPORT);
        out.attributeInt(null, XML_ATTR_PR_DISCHARGE, report.cumulativeBatteryDischarge);
        out.attributeInt(null, XML_ATTR_PR_BATTERY_LEVEL, report.currentBatteryLevel);
        out.attributeLong(null, XML_ATTR_PR_PROFIT, report.cumulativeProfit);
        out.attributeInt(null, XML_ATTR_PR_NUM_PROFIT, report.numProfitableActions);
        out.attributeLong(null, XML_ATTR_PR_LOSS, report.cumulativeLoss);
        out.attributeInt(null, XML_ATTR_PR_NUM_LOSS, report.numUnprofitableActions);
        out.attributeLong(null, XML_ATTR_PR_REWARDS, report.cumulativeRewards);
        out.attributeInt(null, XML_ATTR_PR_NUM_REWARDS, report.numRewards);
        out.attributeLong(null, XML_ATTR_PR_POS_REGULATIONS, report.cumulativePositiveRegulations);
        out.attributeInt(null, XML_ATTR_PR_NUM_POS_REGULATIONS, report.numPositiveRegulations);
        out.attributeLong(null, XML_ATTR_PR_NEG_REGULATIONS, report.cumulativeNegativeRegulations);
        out.attributeInt(null, XML_ATTR_PR_NUM_NEG_REGULATIONS, report.numNegativeRegulations);
        out.endTag(null, XML_TAG_PERIOD_REPORT);
    }

    @GuardedBy("mIrs.getLock()")
    void dumpLocked(IndentingPrintWriter pw, boolean dumpAll) {
        pw.println("Ledgers:");
+8 −6
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ public class AgentTest {
    @Mock
    private CompleteEconomicPolicy mEconomicPolicy;
    @Mock
    private Analyst mAnalyst;
    @Mock
    private Context mContext;
    @Mock
    private InternalResourceService mIrs;
@@ -53,8 +55,8 @@ public class AgentTest {
    private Scribe mScribe;

    private static class MockScribe extends Scribe {
        MockScribe(InternalResourceService irs) {
            super(irs);
        MockScribe(InternalResourceService irs, Analyst analyst) {
            super(irs, analyst);
        }

        @Override
@@ -74,7 +76,7 @@ public class AgentTest {
        doReturn(mEconomicPolicy).when(mIrs).getCompleteEconomicPolicyLocked();
        doReturn(mIrs).when(mIrs).getLock();
        doReturn(mock(AlarmManager.class)).when(mContext).getSystemService(Context.ALARM_SERVICE);
        mScribe = new MockScribe(mIrs);
        mScribe = new MockScribe(mIrs, mAnalyst);
    }

    @After
@@ -86,7 +88,7 @@ public class AgentTest {

    @Test
    public void testRecordTransaction_UnderMax() {
        Agent agent = new Agent(mIrs, mScribe);
        Agent agent = new Agent(mIrs, mScribe, mAnalyst);
        Ledger ledger = new Ledger();

        doReturn(1_000_000L).when(mIrs).getConsumptionLimitLocked();
@@ -115,7 +117,7 @@ public class AgentTest {

    @Test
    public void testRecordTransaction_MaxConsumptionLimit() {
        Agent agent = new Agent(mIrs, mScribe);
        Agent agent = new Agent(mIrs, mScribe, mAnalyst);
        Ledger ledger = new Ledger();

        doReturn(1000L).when(mIrs).getConsumptionLimitLocked();
@@ -162,7 +164,7 @@ public class AgentTest {

    @Test
    public void testRecordTransaction_MaxSatiatedBalance() {
        Agent agent = new Agent(mIrs, mScribe);
        Agent agent = new Agent(mIrs, mScribe, mAnalyst);
        Ledger ledger = new Ledger();

        doReturn(1_000_000L).when(mIrs).getConsumptionLimitLocked();
Loading