# Global Metrics

path: .metrics.nexits.sum
old: 7.0
new: 11.0
path: .metrics.nexits.average
old: 1.1666666666666667
new: 0.5789473684210527
path: .metrics.cyclomatic.sum
old: 25.0
new: 27.0
path: .metrics.cyclomatic.average
old: 3.125
new: 1.35
path: .metrics.loc.cloc
old: 48.0
new: 16.0
path: .metrics.loc.sloc
old: 143.0
new: 197.0
path: .metrics.loc.lloc
old: 37.0
new: 54.0
path: .metrics.loc.ploc
old: 76.0
new: 144.0
path: .metrics.loc.blank
old: 19.0
new: 37.0
path: .metrics.nargs.sum
old: 16.0
new: 31.0
path: .metrics.nargs.average
old: 2.6666666666666665
new: 1.631578947368421
path: .metrics.halstead.length
old: 360.0
new: 645.0
path: .metrics.halstead.volume
old: 2325.395382709427
new: 4650.0974208306725
path: .metrics.halstead.purity_ratio
old: 1.3583871487614556
new: 1.5004052524873497
path: .metrics.halstead.level
old: 0.02695417789757412
new: 0.034375880529726684
path: .metrics.halstead.N1
old: 201.0
new: 372.0
path: .metrics.halstead.N2
old: 159.0
new: 273.0
path: .metrics.halstead.n1
old: 28.0
new: 26.0
path: .metrics.halstead.difficulty
old: 37.1
new: 29.09016393442623
path: .metrics.halstead.vocabulary
old: 88.0
new: 148.0
path: .metrics.halstead.effort
old: 86272.16869851974
new: 135272.09628301684
path: .metrics.halstead.estimated_program_length
old: 489.01937355412406
new: 967.7613878543406
path: .metrics.halstead.n2
old: 60.0
new: 122.0
path: .metrics.halstead.bugs
old: 0.6508174999160733
new: 0.8783836138095413
path: .metrics.halstead.time
old: 4792.898261028875
new: 7515.116460167603
path: .metrics.mi.mi_visual_studio
old: 26.048749189735325
new: 20.637399800723916
path: .metrics.mi.mi_original
old: 44.54336111444741
new: 35.289953659237895
path: .metrics.mi.mi_sei
old: 30.19718373168821
new: -0.6741866918737145
path: .metrics.nom.closures
old: 0.0
new: 1.0
path: .metrics.nom.functions
old: 6.0
new: 18.0
path: .metrics.nom.total
old: 6.0
new: 19.0
path: .metrics.cognitive.average
old: 3.8333333333333335
new: 0.47368421052631576
path: .metrics.cognitive.sum
old: 23.0
new: 9.0

# Spaces Data

## Minimal test - lines (18, 197)

path: .spaces[0].metrics.nom.total
old: 1.0
new: 19.0
path: .spaces[0].metrics.nom.functions
old: 1.0
new: 18.0
path: .spaces[0].metrics.nom.closures
old: 0.0
new: 1.0
path: .spaces[0].metrics.mi.mi_sei
old: 111.46128769050485
new: -2.5911842655361355
path: .spaces[0].metrics.mi.mi_visual_studio
old: 75.78348370266743
new: 21.680582172096212
path: .spaces[0].metrics.mi.mi_original
old: 129.5897571315613
new: 37.07379551428453
path: .spaces[0].metrics.cyclomatic.sum
old: 2.0
new: 26.0
path: .spaces[0].metrics.cyclomatic.average
old: 2.0
new: 1.368421052631579
path: .spaces[0].metrics.nexits.average
old: 1.0
new: 0.5789473684210527
path: .spaces[0].metrics.nexits.sum
old: 1.0
new: 11.0
path: .spaces[0].metrics.halstead.estimated_program_length
old: 53.5635228093372
new: 917.7372281064668
path: .spaces[0].metrics.halstead.difficulty
old: 7.333333333333333
new: 29.92241379310345
path: .spaces[0].metrics.halstead.bugs
old: 0.024482838674456185
new: 0.8845808257116634
path: .spaces[0].metrics.halstead.length
old: 21.0
new: 639.0
path: .spaces[0].metrics.halstead.N1
old: 13.0
new: 372.0
path: .spaces[0].metrics.halstead.effort
old: 629.4692775525522
new: 136706.18507673
path: .spaces[0].metrics.halstead.vocabulary
old: 17.0
new: 142.0
path: .spaces[0].metrics.halstead.N2
old: 8.0
new: 267.0
path: .spaces[0].metrics.halstead.n1
old: 11.0
new: 26.0
path: .spaces[0].metrics.halstead.n2
old: 6.0
new: 116.0
path: .spaces[0].metrics.halstead.purity_ratio
old: 2.5506439433017714
new: 1.436208494689306
path: .spaces[0].metrics.halstead.volume
old: 85.83671966625712
new: 4568.688409363492
path: .spaces[0].metrics.halstead.time
old: 34.970515419586235
new: 7594.788059818334
path: .spaces[0].metrics.halstead.level
old: 0.13636363636363638
new: 0.033419763756842406
path: .spaces[0].metrics.nargs.average
old: 1.0
new: 1.631578947368421
path: .spaces[0].metrics.nargs.sum
old: 1.0
new: 31.0
path: .spaces[0].metrics.cognitive.sum
old: 1.0
new: 9.0
path: .spaces[0].metrics.cognitive.average
old: 1.0
new: 0.47368421052631576
path: .spaces[0].metrics.loc.cloc
old: 0.0
new: 9.0
path: .spaces[0].metrics.loc.lloc
old: 1.0
new: 54.0
path: .spaces[0].metrics.loc.sloc
old: 3.0
new: 180.0
path: .spaces[0].metrics.loc.ploc
old: 3.0
new: 137.0
path: .spaces[0].metrics.loc.blank
old: 0.0
new: 34.0

### Code

    namespace testing {

    // Populate an array with the given number of bytes.  Data is lorem ipsum
    // random text, but deterministic across multiple calls.
    void CreateData(uint32_t aNumBytes, nsTArray& aDataOut) {
      static const char data[] =
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec egestas "
          "purus eu condimentum iaculis. In accumsan leo eget odio porttitor, non "
          "rhoncus nulla vestibulum. Etiam lacinia consectetur nisl nec "
          "sollicitudin. Sed fringilla accumsan diam, pulvinar varius massa. Duis "
          "mollis dignissim felis, eget tempus nisi tristique ut. Fusce euismod, "
          "lectus non lacinia tempor, tellus diam suscipit quam, eget hendrerit "
          "lacus nunc fringilla ante. Sed ultrices massa vitae risus molestie, ut "
          "finibus quam laoreet nullam.";
      static const uint32_t dataLength = sizeof(data) - 1;

      aDataOut.SetCapacity(aNumBytes);

      while (aNumBytes > 0) {
        uint32_t amount = std::min(dataLength, aNumBytes);
        aDataOut.AppendElements(data, amount);
        aNumBytes -= amount;
      }
    }

    // Write the given number of bytes out to the stream.  Loop until expected
    // bytes count is reached or an error occurs.
    void Write(nsIOutputStream* aStream, const nsTArray& aData,
               uint32_t aOffset, uint32_t aNumBytes) {
      uint32_t remaining =
          std::min(aNumBytes, static_cast(aData.Length() - aOffset));

      while (remaining > 0) {
        uint32_t numWritten;
        nsresult rv =
            aStream->Write(aData.Elements() + aOffset, remaining, &numWritten);
        ASSERT_TRUE(NS_SUCCEEDED(rv));
        if (numWritten < 1) {
          break;
        }
        aOffset += numWritten;
        remaining -= numWritten;
      }
    }

    // Write the given number of bytes and then close the stream.
    void WriteAllAndClose(nsIOutputStream* aStream, const nsTArray& aData) {
      Write(aStream, aData, 0, aData.Length());
      aStream->Close();
    }

    // Synchronously consume the given input stream and validate the resulting data
    // against the given array of expected values.
    void ConsumeAndValidateStream(nsIInputStream* aStream,
                                  const nsTArray& aExpectedData) {
      nsDependentCSubstring data(aExpectedData.Elements(), aExpectedData.Length());
      ConsumeAndValidateStream(aStream, data);
    }

    // Synchronously consume the given input stream and validate the resulting data
    // against the given string of expected values.
    void ConsumeAndValidateStream(nsIInputStream* aStream,
                                  const nsACString& aExpectedData) {
      nsAutoCString outputData;
      nsresult rv = NS_ConsumeStream(aStream, UINT32_MAX, outputData);
      ASSERT_TRUE(NS_SUCCEEDED(rv));
      ASSERT_EQ(aExpectedData.Length(), outputData.Length());
      ASSERT_TRUE(aExpectedData.Equals(outputData));
    }

    NS_IMPL_ISUPPORTS(OutputStreamCallback, nsIOutputStreamCallback);

    OutputStreamCallback::OutputStreamCallback() : mCalled(false) {}

    OutputStreamCallback::~OutputStreamCallback() = default;

    NS_IMETHODIMP
    OutputStreamCallback::OnOutputStreamReady(nsIAsyncOutputStream* aStream) {
      mCalled = true;
      return NS_OK;
    }

    NS_IMPL_ISUPPORTS(InputStreamCallback, nsIInputStreamCallback);

    InputStreamCallback::InputStreamCallback() : mCalled(false) {}

    InputStreamCallback::~InputStreamCallback() = default;

    NS_IMETHODIMP
    InputStreamCallback::OnInputStreamReady(nsIAsyncInputStream* aStream) {
      mCalled = true;
      return NS_OK;
    }

    AsyncStringStream::AsyncStringStream(const nsACString& aBuffer) {
      NS_NewCStringInputStream(getter_AddRefs(mStream), aBuffer);
    }

    NS_IMETHODIMP
    AsyncStringStream::Available(uint64_t* aLength) {
      return mStream->Available(aLength);
    }

    NS_IMETHODIMP
    AsyncStringStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) {
      return mStream->Read(aBuffer, aCount, aReadCount);
    }

    NS_IMETHODIMP
    AsyncStringStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
                                    uint32_t aCount, uint32_t* aResult) {
      return NS_ERROR_NOT_IMPLEMENTED;
    }

    NS_IMETHODIMP
    AsyncStringStream::Close() {
      nsresult rv = mStream->Close();
      if (NS_SUCCEEDED(rv)) {
        MaybeExecCallback(mCallback, mCallbackEventTarget);
      }
      return rv;
    }

    NS_IMETHODIMP
    AsyncStringStream::IsNonBlocking(bool* aNonBlocking) {
      return mStream->IsNonBlocking(aNonBlocking);
    }

    NS_IMETHODIMP
    AsyncStringStream::CloseWithStatus(nsresult aStatus) { return Close(); }

    NS_IMETHODIMP
    AsyncStringStream::AsyncWait(nsIInputStreamCallback* aCallback, uint32_t aFlags,
                                 uint32_t aRequestedCount,
                                 nsIEventTarget* aEventTarget) {
      if (aFlags & nsIAsyncInputStream::WAIT_CLOSURE_ONLY) {
        mCallback = aCallback;
        mCallbackEventTarget = aEventTarget;
        return NS_OK;
      }

      MaybeExecCallback(aCallback, aEventTarget);
      return NS_OK;
    }

    void AsyncStringStream::MaybeExecCallback(nsIInputStreamCallback* aCallback,
                                              nsIEventTarget* aEventTarget) {
      if (!aCallback) {
        return;
      }

      nsCOMPtr callback = aCallback;
      nsCOMPtr self = this;

      nsCOMPtr r = NS_NewRunnableFunction(
          "AsyncWait", [callback, self]() { callback->OnInputStreamReady(self); });

      if (aEventTarget) {
        aEventTarget->Dispatch(r.forget());
      } else {
        r->Run();
      }
    }

    NS_IMPL_ISUPPORTS(AsyncStringStream, nsIAsyncInputStream, nsIInputStream)

    NS_IMPL_ADDREF(LengthInputStream);
    NS_IMPL_RELEASE(LengthInputStream);

    NS_INTERFACE_MAP_BEGIN(LengthInputStream)
      NS_INTERFACE_MAP_ENTRY(nsIInputStream)
      NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamLength, mIsInputStreamLength)
      NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStreamLength,
                                         mIsAsyncInputStreamLength)
      NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
    NS_INTERFACE_MAP_END

    NS_IMPL_ISUPPORTS(LengthCallback, nsIInputStreamLengthCallback)

    }  // namespace testing