Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package ghc-network-control for 
openSUSE:Factory checked in at 2024-11-12 19:20:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-network-control (Old)
 and      /work/SRC/openSUSE:Factory/.ghc-network-control.new.2017 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ghc-network-control"

Tue Nov 12 19:20:14 2024 rev:2 rq:1222959 version:0.1.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-network-control/ghc-network-control.changes  
2023-12-05 17:03:57.634793848 +0100
+++ 
/work/SRC/openSUSE:Factory/.ghc-network-control.new.2017/ghc-network-control.changes
        2024-11-12 19:20:41.193620558 +0100
@@ -1,0 +2,24 @@
+Thu Jul 18 22:56:21 UTC 2024 - Peter Simons <psim...@suse.com>
+
+- Update network-control to version 0.1.3.
+  ## 0.1.3
+
+  * Simplify `maybeOpenRxWindow` and improve docs
+    [#7](https://github.com/kazu-yamamoto/network-control/pull/7)
+
+  ## 0.1.2
+
+  * introducing a minimum size for window update
+    [#5](https://github.com/kazu-yamamoto/network-control/pull/5)
+
+  ## 0.1.1
+
+  * Change defaultMaxData
+    [#4](https://github.com/kazu-yamamoto/network-control/pull/4)
+
+  ## 0.1.0
+
+  * Breaking change: Renaming rxfWindow to rxfBufSize.
+  * Updating the document about flow control.
+
+-------------------------------------------------------------------

Old:
----
  network-control-0.0.2.tar.gz

New:
----
  network-control-0.1.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ghc-network-control.spec ++++++
--- /var/tmp/diff_new_pack.LJih3E/_old  2024-11-12 19:20:42.977695362 +0100
+++ /var/tmp/diff_new_pack.LJih3E/_new  2024-11-12 19:20:42.989695865 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package ghc-network-control
 #
-# Copyright (c) 2023 SUSE LLC
+# Copyright (c) 2024 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,8 +18,9 @@
 
 %global pkg_name network-control
 %global pkgver %{pkg_name}-%{version}
+%bcond_with tests
 Name:           ghc-%{pkg_name}
-Version:        0.0.2
+Version:        0.1.3
 Release:        0
 Summary:        Library to control network protocols
 License:        BSD-3-Clause
@@ -34,6 +35,16 @@
 BuildRequires:  ghc-unix-time-devel
 BuildRequires:  ghc-unix-time-prof
 ExcludeArch:    %{ix86}
+%if %{with tests}
+BuildRequires:  ghc-QuickCheck-devel
+BuildRequires:  ghc-QuickCheck-prof
+BuildRequires:  ghc-hspec-devel
+BuildRequires:  ghc-hspec-prof
+BuildRequires:  ghc-pretty-simple-devel
+BuildRequires:  ghc-pretty-simple-prof
+BuildRequires:  ghc-text-devel
+BuildRequires:  ghc-text-prof
+%endif
 
 %description
 Common parts to control network protocols.
@@ -74,6 +85,9 @@
 %install
 %ghc_lib_install
 
+%check
+%cabal_test
+
 %post devel
 %ghc_pkg_recache
 

++++++ network-control-0.0.2.tar.gz -> network-control-0.1.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/network-control-0.0.2/Changelog.md 
new/network-control-0.1.3/Changelog.md
--- old/network-control-0.0.2/Changelog.md      2001-09-09 03:46:40.000000000 
+0200
+++ new/network-control-0.1.3/Changelog.md      2001-09-09 03:46:40.000000000 
+0200
@@ -1,5 +1,25 @@
 # Revision history for network-control
 
+## 0.1.3
+
+* Simplify `maybeOpenRxWindow` and improve docs
+  [#7](https://github.com/kazu-yamamoto/network-control/pull/7)
+
+## 0.1.2
+
+* introducing a minimum size for window update
+  [#5](https://github.com/kazu-yamamoto/network-control/pull/5)
+
+## 0.1.1
+
+* Change defaultMaxData
+  [#4](https://github.com/kazu-yamamoto/network-control/pull/4)
+
+## 0.1.0
+
+* Breaking change: Renaming rxfWindow to rxfBufSize.
+* Updating the document about flow control.
+
 ## 0.0.2
 
 * Adding constants.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/network-control-0.0.2/Network/Control/Flow.hs 
new/network-control-0.1.3/Network/Control/Flow.hs
--- old/network-control-0.0.2/Network/Control/Flow.hs   2001-09-09 
03:46:40.000000000 +0200
+++ new/network-control-0.1.3/Network/Control/Flow.hs   2001-09-09 
03:46:40.000000000 +0200
@@ -1,20 +1,27 @@
 {-# LANGUAGE RecordWildCards #-}
 
 module Network.Control.Flow (
-    -- * Constants for flow control.
+    -- * Flow control
+
+    -- | This is based on the total approach of QUIC rather than
+    --   the difference approach of HTTP\/2 because QUIC'one is
+    --   considered safer. Please refer to [Using HTTP\/3 Stream Limits in 
HTTP\/2](https://datatracker.ietf.org/doc/draft-thomson-httpbis-h2-stream-limits/)
 to understand that QUIC's approaches are better though its topic is about 
stream concurrency.
+
+    -- ** Constants for flow control.
     defaultMaxStreams,
     defaultMaxStreamData,
     defaultMaxData,
 
-    -- * Flow control for sending
+    -- ** Flow control for sending
     TxFlow (..),
     newTxFlow,
     txWindowSize,
     WindowSize,
 
-    -- * Flow control for receiving
+    -- ** Flow control for receiving
     RxFlow (..),
     newRxFlow,
+    rxWindowSize,
     FlowControlType (..),
     maybeOpenRxWindow,
     checkRxLimit,
@@ -30,21 +37,41 @@
 defaultMaxStreamData :: Int
 defaultMaxStreamData = 262144
 
--- | Default max data of a connection. (1M bytes)
+-- | Default max data of a connection.
+--
+-- By default, this is set to @defaultMaxStreams * defaultMaxStreamData@. This
+-- ensures that streams that are not currently handled cannot exhaust the
+-- connection window.
+--
+-- If you use a smaller connection window size, you __must__ ensure that if you
+-- are handling fewer concurrent streams than allowed by 'defaultMaxStreams',
+-- that the unhandled streams cannot exhaust the connection window, or risk the
+-- entire system deadlocking.
 defaultMaxData :: Int
-defaultMaxData = 1048576
+defaultMaxData = defaultMaxStreamData * defaultMaxStreams
 
 -- | Window size.
 type WindowSize = Int
 
 -- | Flow for sending
+--
+-- @
+-- -------------------------------------->
+--        ^           ^
+--     txfSent    txfLimit
+--
+--        |-----------| The size which this node can send
+--        txWindowSize
+-- @
 data TxFlow = TxFlow
     { txfSent :: Int
+    -- ^ The total size of sent data.
     , txfLimit :: Int
+    -- ^ The total size of data which can be sent.
     }
-    deriving (Show)
+    deriving (Eq, Show)
 
--- | Creating TX flow with an initial window size.
+-- | Creating TX flow with a receive buffer size.
 newTxFlow :: WindowSize -> TxFlow
 newTxFlow win = TxFlow 0 win
 
@@ -52,19 +79,71 @@
 txWindowSize :: TxFlow -> WindowSize
 txWindowSize TxFlow{..} = txfLimit - txfSent
 
--- | Flow for receiving
+-- | Flow for receiving.
+--
+-- The goal of 'RxFlow' is to ensure that our network peer does not send us 
data
+-- faster than we can consume it. We therefore impose a maximum number of
+-- unconsumed bytes that we are willing to receive from the peer, which we 
refer
+-- to as the buffer size:
+--
+-- @
+--                    rxfBufSize
+--           |---------------------------|
+-- -------------------------------------------->
+--           ^              ^
+--      rxfConsumed    rxvReceived
+-- @
+--
+-- The peer does not know of course how many bytes we have consumed of the data
+-- that they sent us, so they keep track of their own limit of how much data
+-- they are allowed to send. We keep track of this limit also:
+--
+-- @
+--                    rxfBufSize
+--           |---------------------------|
+-- -------------------------------------------->
+--           ^              ^       ^
+--      rxfConsumed    rxvReceived  |
+--                               rxfLimit
+-- @
+--
+-- Each time we receive data from the peer, we check that they do not exceed 
the
+-- limit ('checkRxLimit'). When we consume data, we periodically send the peer
+-- an update (known as a _window update_) of what their new limit is
+-- ('maybeOpenRxWindow'). To decrease overhead, we only this if the window
+-- update is at least half the window size.
 data RxFlow = RxFlow
-    { rxfWindow :: WindowSize
+    { rxfBufSize :: Int
+    -- ^ Maxinum number of unconsumed bytes the peer can send us
+    --
+    -- See discussion above for details.
     , rxfConsumed :: Int
+    -- ^ How much of the data that the peer has sent us have we consumed?
+    --
+    -- This is an absolute number: the total about of bytes consumed over the
+    -- lifetime of the connection or stream (i.e., not relative to the window).
     , rxfReceived :: Int
+    -- ^ How much data have we received from the peer?
+    --
+    -- Like 'rxfConsumed', this is an absolute number.
     , rxfLimit :: Int
+    -- ^ Current limit on how many bytes the peer is allowed to send us.
+    --
+    -- Like 'rxfConsumed, this is an absolute number.
     }
-    deriving (Show)
+    deriving (Eq, Show)
 
 -- | Creating RX flow with an initial window size.
 newRxFlow :: WindowSize -> RxFlow
 newRxFlow win = RxFlow win 0 0 win
 
+-- | 'rxfLimit' - 'rxfReceived'.
+--
+-- This is the number of bytes the peer is still allowed to send before they
+-- must wait for a window update; see 'RxFlow' for details.
+rxWindowSize :: RxFlow -> WindowSize
+rxWindowSize RxFlow{..} = rxfLimit - rxfReceived
+
 -- | The representation of window size update.
 data FlowControlType
     = -- | HTTP\/2 style
@@ -72,10 +151,9 @@
     | -- | QUIC style
       FCTMaxData
 
--- | When an application consumed received data,
---   this function should be called to update 'rxfConsumed'.
---   If the window size is less than the half of the initial window.
---   the representation of window size update is returned.
+-- | Record that we have consumed some received data
+--
+-- May return a window update; see 'RxFlow' for details.
 maybeOpenRxWindow
     :: Int
     -- ^ The consumed size.
@@ -84,24 +162,28 @@
     -> (RxFlow, Maybe Int)
     -- ^ 'Just' if the size should be informed to the peer.
 maybeOpenRxWindow consumed fct flow@RxFlow{..}
-    | available < threshold =
-        let limit = consumed' + rxfWindow
-            flow' =
+    | winUpdate >= threshold =
+        let flow' =
                 flow
-                    { rxfConsumed = consumed'
-                    , rxfLimit = limit
+                    { rxfConsumed = rxfConsumed'
+                    , rxfLimit = rxfLimit'
                     }
             update = case fct of
-                FCTWindowUpdate -> limit - rxfLimit
-                FCTMaxData -> limit
+                FCTWindowUpdate -> winUpdate
+                FCTMaxData -> rxfLimit'
          in (flow', Just update)
     | otherwise =
-        let flow' = flow{rxfConsumed = consumed'}
+        let flow' = flow{rxfConsumed = rxfConsumed'}
          in (flow', Nothing)
   where
-    available = rxfLimit - rxfReceived
-    threshold = rxfWindow `unsafeShiftR` 1
-    consumed' = rxfConsumed + consumed
+    rxfConsumed' = rxfConsumed + consumed
+
+    -- Minimum window update size
+    threshold = rxfBufSize `unsafeShiftR` 1
+
+    -- The window update, /if/ we choose to send it
+    rxfLimit' = rxfConsumed' + rxfBufSize
+    winUpdate = rxfLimit' - rxfLimit
 
 -- | Checking if received data is acceptable against the
 --   current window.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/network-control-0.0.2/Network/Control.hs 
new/network-control-0.1.3/Network/Control.hs
--- old/network-control-0.0.2/Network/Control.hs        2001-09-09 
03:46:40.000000000 +0200
+++ new/network-control-0.1.3/Network/Control.hs        2001-09-09 
03:46:40.000000000 +0200
@@ -1,4 +1,5 @@
 -- | Common parts to control network protocols.
+--   This library assumes that 'Int' is 64bit.
 module Network.Control (
     module Network.Control.Flow,
     module Network.Control.LRUCache,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/network-control-0.0.2/network-control.cabal 
new/network-control-0.1.3/network-control.cabal
--- old/network-control-0.0.2/network-control.cabal     2001-09-09 
03:46:40.000000000 +0200
+++ new/network-control-0.1.3/network-control.cabal     2001-09-09 
03:46:40.000000000 +0200
@@ -1,6 +1,6 @@
 cabal-version:   3.0
 name:            network-control
-version:         0.0.2
+version:         0.1.3
 license:         BSD-3-Clause
 license-file:    LICENSE
 maintainer:      k...@iij.ad.jp
@@ -25,3 +25,22 @@
         base >=4.14 && <5,
         psqueues,
         unix-time
+
+test-suite spec
+    type:               exitcode-stdio-1.0
+    main-is:            Spec.hs
+    build-tool-depends: hspec-discover:hspec-discover
+    hs-source-dirs:     test
+    other-modules:
+        Network.Control.FlowSpec
+
+    default-language:   Haskell2010
+    default-extensions: Strict StrictData
+    ghc-options:        -Wall -threaded
+    build-depends:
+        base,
+        hspec >=1.3,
+        network-control,
+        QuickCheck,
+        pretty-simple,
+        text
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/network-control-0.0.2/test/Network/Control/FlowSpec.hs 
new/network-control-0.1.3/test/Network/Control/FlowSpec.hs
--- old/network-control-0.0.2/test/Network/Control/FlowSpec.hs  1970-01-01 
01:00:00.000000000 +0100
+++ new/network-control-0.1.3/test/Network/Control/FlowSpec.hs  2001-09-09 
03:46:40.000000000 +0200
@@ -0,0 +1,163 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE NumericUnderscores #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE ViewPatterns #-}
+{-# OPTIONS_GHC -Wno-orphans -Wno-incomplete-patterns #-}
+
+module Network.Control.FlowSpec where
+
+import Data.List
+import Data.Text.Lazy (unpack)
+import Network.Control
+import Test.Hspec
+import Test.Hspec.QuickCheck
+import Test.QuickCheck
+import Text.Pretty.Simple
+
+-- types
+
+data Op = Consume | Receive
+    deriving (Eq, Show, Bounded, Enum)
+
+data OpWithResult = ConsumeWithResult (Maybe Int) | ReceiveWithResult Bool
+    deriving (Eq, Show)
+
+data Step op = Step {stepOp :: op, stepArg :: Int}
+    deriving (Eq, Show)
+
+data Trace = Trace
+    { traceStart :: RxFlow
+    , traceSteps :: [(Int, Step OpWithResult, RxFlow)]
+    }
+    deriving (Eq, Show)
+
+-- arbitrary instances
+
+maxWindowSize :: Int
+maxWindowSize = 200 -- (more realistic: 2_000_000)
+
+instance Arbitrary RxFlow where
+    -- Prefer to generate a simple window size
+    arbitrary =
+        newRxFlow
+            <$> oneof
+                [ elements [1, 10, 50, 100]
+                , chooseInt (1, maxWindowSize)
+                ]
+
+instance Arbitrary Op where
+    arbitrary = elements [minBound ..]
+
+instance Arbitrary Trace where
+    arbitrary = do
+        initialFlow <- arbitrary
+        len <- chooseInt (0, 500)
+        Trace initialFlow <$> runManySteps len 0 initialFlow
+      where
+        runManySteps :: Int -> Int -> RxFlow -> Gen [(Int, Step OpWithResult, 
RxFlow)]
+        runManySteps 0 _ _ = pure []
+        runManySteps len ix oldFlow = do
+            (newStep, newFlow) <- runStep oldFlow <$> genStep oldFlow
+            ((ix, newStep, newFlow) :) <$> runManySteps (len - 1) (ix + 1) 
newFlow
+
+        genStep :: RxFlow -> Gen (Step Op)
+        genStep oldFlow = oneof [mkConsume, mkReceive]
+          where
+            -- Negative frames are non-sensical; frames larger than the window
+            -- size are theoretically possible (but will trivially be rejected
+            -- as exceeding the window).
+            mkReceive =
+                Step Receive <$> chooseInt (0, rxfBufSize oldFlow * 2)
+
+            -- We can only consume as much as we have received
+            -- (but it is in principle not a problem to consume 0 bytes)
+            mkConsume =
+                Step Consume <$> chooseInt (0, rxfReceived oldFlow - 
rxfConsumed oldFlow)
+
+        runStep :: RxFlow -> Step Op -> (Step OpWithResult, RxFlow)
+        runStep oldFlow = \case
+            Step Consume arg ->
+                let (newFlow, limitDelta) = maybeOpenRxWindow arg 
FCTWindowUpdate oldFlow
+                 in (Step (ConsumeWithResult limitDelta) arg, newFlow)
+            Step Receive arg ->
+                let (newFlow, isAcceptable) = checkRxLimit arg oldFlow
+                 in (Step (ReceiveWithResult isAcceptable) arg, newFlow)
+
+    shrink (Trace initialFlow steps) =
+        concat
+            [ -- Take a prefix (starting with the same initialFlow)
+              Trace initialFlow <$> init (inits steps)
+            , -- Take a suffix (starting with a later initialFlow)
+              map shiftInitialFlow $ tail (tails steps)
+            ]
+      where
+        shiftInitialFlow :: [(Int, Step OpWithResult, RxFlow)] -> Trace
+        shiftInitialFlow [] = Trace initialFlow []
+        shiftInitialFlow ((_, _, initialFlow') : rest) = Trace initialFlow' 
rest
+
+-- invariants
+
+assertTrace :: Trace -> Property
+assertTrace (Trace initialFlow steps) = assertStep initialFlow steps
+
+assertStep :: RxFlow -> [(Int, Step OpWithResult, RxFlow)] -> Property
+assertStep _ [] = property True
+assertStep oldFlow ((ix, step, newFlow) : steps) =
+    (counterexample ("step #" <> show ix) check) .&. assertStep newFlow steps
+  where
+    check :: Expectation
+    check = case step of
+        Step (ConsumeWithResult limitDelta) arg -> do
+            -- There is no point duplicating precisely the same logic here as 
in
+            -- 'maybeOpenRxWindow': that would result in circular reasoning.
+            -- Instead, we leave 'maybeOpenRxWindow' some implementation
+            -- freedom, and only verify that the window update makes sense:
+            --
+            -- (a) It can't be too large: the new window after the update 
should
+            --     never exceed the specified buffer size.
+            -- (b) It can't be too late: if we consume /all/ received data, and
+            --     do not allow the peer to send any further data, then the
+            --     system deadlocks.
+            -- (c) It shouldn't be too small: very small window updates are
+            --     wasteful.
+            --
+            -- Within these parameters 'maybeOpenRxWindow' can decide when to
+            -- send window updates and how large they should be. We also don't
+            -- set the bound on (c) too strict.
+            newFlow
+                `shouldBe` RxFlow
+                    { rxfBufSize = rxfBufSize oldFlow
+                    , rxfConsumed = rxfConsumed oldFlow + arg
+                    , rxfReceived = rxfReceived oldFlow
+                    , rxfLimit = case limitDelta of
+                        Nothing -> rxfLimit oldFlow
+                        Just upd -> rxfLimit oldFlow + upd
+                    }
+            -- Condition (a)
+            newFlow `shouldSatisfy` \flow ->
+                rxfLimit flow - rxfConsumed flow <= rxfBufSize flow
+            -- Condition (b)
+            newFlow `shouldSatisfy` \flow ->
+                rxfLimit flow > rxfConsumed flow
+            -- Condition (c)
+            limitDelta `shouldSatisfy` \mUpd ->
+                case mUpd of
+                    Nothing -> True
+                    Just upd -> upd >= rxfBufSize newFlow `div` 8
+        Step (ReceiveWithResult isAcceptable) arg -> do
+            newFlow
+                `shouldBe` if isAcceptable
+                    then
+                        RxFlow
+                            { rxfBufSize = rxfBufSize newFlow
+                            , rxfConsumed = rxfConsumed oldFlow
+                            , rxfReceived = rxfReceived oldFlow + arg
+                            , rxfLimit = rxfLimit oldFlow
+                            }
+                    else oldFlow
+
+spec :: Spec
+spec = do
+    focus . prop "state transition graph checks out" $
+        \trace -> counterexample (unpack $ pShowNoColor trace) (assertTrace 
trace)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/network-control-0.0.2/test/Spec.hs 
new/network-control-0.1.3/test/Spec.hs
--- old/network-control-0.0.2/test/Spec.hs      1970-01-01 01:00:00.000000000 
+0100
+++ new/network-control-0.1.3/test/Spec.hs      2001-09-09 03:46:40.000000000 
+0200
@@ -0,0 +1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}

Reply via email to