>>> from blessed import Terminal
>>> from pgactivity.types import *
>>> from pgactivity.views import *

>>> term = Terminal(force_styling=None)
>>> term.width
80

Tests for help()
----------------

>>> help(term, "2.1", True)
pg_activity 2.1 - https://github.com/dalibo/pg_activity
Released under PostgreSQL License.
<BLANKLINE>
   Up/Down: scroll process list
     Space: pause/unpause
         c: sort by CPU% desc. (activities)
         m: sort by MEM% desc. (activities)
         r: sort by READ/s desc. (activities)
         w: sort by WRITE/s desc. (activities)
         t: sort by TIME+ desc. (activities)
         +: increase refresh time (max:5s)
         -: decrease refresh time (min:0.5s)
         v: change display mode
         T: change duration mode
         D: force refresh database size
         R: force refresh
         q: quit
Mode
      F1/1: running queries
      F2/2: waiting queries
      F3/3: blocking queries
<BLANKLINE>
Press any key to exit.

>>> help(term, "5.0", False)
pg_activity 5.0 - https://github.com/dalibo/pg_activity
Released under PostgreSQL License.
<BLANKLINE>
   Up/Down: scroll process list
     Space: pause/unpause
         +: increase refresh time (max:5s)
         -: decrease refresh time (min:0.5s)
         v: change display mode
         T: change duration mode
         D: force refresh database size
         R: force refresh
         q: quit
Mode
      F1/1: running queries
      F2/2: waiting queries
      F3/3: blocking queries
<BLANKLINE>
Press any key to exit.


Tests for header()
------------------


>>> ui = UI.make(refresh_time=10, duration_mode=DurationMode.backend)

Remote host:

>>> host = Host("PostgreSQL 9.6", "server", "pgadm", "server.prod.tld", 5433, "app")
>>> dbinfo = DBInfo(10203040506070809, 9999)

>>> header(term, ui, host=host, dbinfo=dbinfo, tps=12, active_connections=0,
...        width=200)
PostgreSQL 9.6 - server - pgadm@server.prod.tld:5433/app - Ref.: 10s
 Size:         9.06P - 9.76K/s        | TPS:              12      | Active connections:               0      | Duration mode:     backend
>>> header(term, ui, host=host, dbinfo=dbinfo, tps=12, active_connections=0)
PostgreSQL 9.6 - server - pgadm@server.prod.tld:5433/app - Ref.: 10s
 Size:         9.06P - 9.76K/s        | TPS:              12      | Active

Local host, with priviledged access:

>>> host = Host("PostgreSQL 13.1", "localhost", "tester", "host", 5432, "postgres")
>>> dbinfo = DBInfo(123456789, 12)
>>> vmem = MemoryInfo(total=6175825920, percent=42.5, used=2007146496)
>>> swap = MemoryInfo(total=6312423424, used=2340, percent=0.0)
>>> io_read = IOCounter(bytes=128, count=6)
>>> io_write = IOCounter(bytes=8, count=9)
>>> load = LoadAverage(25.0, 0.19, 0.39)
>>> sysinfo = SystemInfo(vmem, swap, load, io_read, io_write, 12)

>>> ui = UI.make(refresh_time=2, min_duration=1.2)
>>> header(term, ui, host=host, dbinfo=dbinfo, tps=1, active_connections=79,
...        system_info=sysinfo, width=150)
PostgreSQL 13.1 - localhost - tester@host:5432/postgres - Ref.: 2s - Min. duration: 1.2s
 Size:       117.74M - 12B/s          | TPS:               1      | Active connections:              79      | Duration mode:       query
 Mem.:      42.5% - 1.87G/5.75G       | IO Max:       12/s
 Swap:       0.0% - 2.29K/5.88G       | Read:          128B/s - 6/s
 Load:        25.00 0.19 0.39         | Write:          8B/s - 9/s


Tests for columns_header()
--------------------------

>>> ui = UI.make(query_mode=QueryMode.activities,
...              flag=Flag.PID | Flag.DATABASE,
...              sort_key=SortKey.cpu)
>>> columns_header(term, ui, width=83)
PID    DATABASE                      state   Query

>>> ui = UI.make(query_mode=QueryMode.activities,
...              flag=Flag.CPU,
...              sort_key=SortKey.cpu)
>>> columns_header(term, ui)
  CPU%              state   Query

>>> ui = UI.make(query_mode=QueryMode.activities,
...              flag=Flag.MEM,
...              sort_key=SortKey.cpu)
>>> columns_header(term, ui)
MEM%              state   Query

>>> ui = UI.make(query_mode=QueryMode.blocking,
...              flag=Flag.PID | Flag.DATABASE | Flag.APPNAME | Flag.RELATION | Flag.CLIENT | Flag.WAIT,
...              sort_key=SortKey.duration)
>>> columns_header(term, ui, width=150)
PID    DATABASE                      APP           CLIENT  RELATION              state   Query

>>> ui.evolve(query_mode=QueryMode.activities)
>>> columns_header(term, ui, width=150)
PID    DATABASE                      APP           CLIENT  W              state   Query


Tests for processes_rows()
--------------------------

>>> processes1 = [
...     LocalRunningProcess(
...         pid="6239",
...         appname="pgbench",
...         database="pgbench",
...         user="postgres",
...         client="local",
...         cpu=0.1,
...         mem=0.993_254_939_413_836,
...         read=7,
...         write=12.3,
...         state="idle in transaction",
...         query="UPDATE pgbench_accounts SET abalance = abalance + 141 WHERE aid = 1932841;",
...         duration=0.0,
...         wait=False,
...         io_wait=False,
...         is_parallel_worker=False,
...     ),
...     LocalRunningProcess(
...         pid="6228",
...         appname="pgbench",
...         database="pgbench",
...         user="postgres",
...         client="local",
...         cpu=0.2,
...         mem=1.024_758_418_061_11,
...         read=0.2,
...         write=1_128_201,
...         state="active",
...         query="UPDATE pgbench_accounts SET abalance = abalance + 3062 WHERE aid = 7289374;",
...         duration=0.000413,
...         wait=False,
...         io_wait=True,
...         is_parallel_worker=True,
...     ),
...     LocalRunningProcess(
...         pid="1234",
...         appname="accounting",
...         database="business",
...         user="bob",
...         client="local",
...         cpu=2.4,
...         mem=1.031_191_760_016_45,
...         read=9_876_543.21,
...         write=1_234,
...         state="active",
...         query="SELECT product_id, p.name FROM products p LEFT JOIN sales s USING (product_id) WHERE s.date > CURRENT_DATE - INTERVAL '4 weeks' GROUP BY product_id, p.name, p.price, p.cost HAVING sum(p.price * s.units) > 5000;",
...         duration=1234,
...         wait=True,
...         io_wait=False,
...         is_parallel_worker=False,
...     ),
... ]

>>> ui = UI.make(flag=Flag.PID|Flag.CPU|Flag.MEM|Flag.DATABASE)

>>> processes_rows(term, ui, SelectableProcesses(processes1))
6239   pgbench             0.1  1.0      idle in trans   UPDATE pgbench_accounts
SET abalance = abalance + 141 WHERE aid = 1932841;
6228   pgbench             0.2  1.0             active   \_ UPDATE
pgbench_accounts SET abalance = abalance + 3062 WHERE aid = 7289374;
1234   business            2.4  1.0             active   SELECT product_id,
p.name FROM products p LEFT JOIN sales s USING (product_id) WHERE s.date >
CURRENT_DATE - INTERVAL '4 weeks' GROUP BY product_id, p.name, p.price, p.cost
HAVING sum(p.price * s.units) > 5000;

>>> ui.evolve(verbose_mode=QueryDisplayMode.truncate)
>>> processes_rows(term, ui, SelectableProcesses(processes1))
6239   pgbench             0.1  1.0      idle in trans   UPDATE pgbench_accounts
6228   pgbench             0.2  1.0             active   \_ UPDATE pgbench_accou
1234   business            2.4  1.0             active   SELECT product_id, p.na

>>> ui.evolve(verbose_mode=QueryDisplayMode.wrap)
>>> processes_rows(term, ui, SelectableProcesses(processes1))
6239   pgbench             0.1  1.0      idle in trans   UPDATE pgbench_accounts
                                                         SET abalance = abalance
                                                         + 141 WHERE aid =
                                                         1932841;
6228   pgbench             0.2  1.0             active   \_ UPDATE
                                                         pgbench_accounts SET
                                                         abalance = abalance +
                                                         3062 WHERE aid =
                                                         7289374;
1234   business            2.4  1.0             active   SELECT product_id,
                                                         p.name FROM products p
                                                         LEFT JOIN sales s USING
                                                         (product_id) WHERE
                                                         s.date > CURRENT_DATE -
                                                         INTERVAL '4 weeks'
                                                         GROUP BY product_id,
                                                         p.name, p.price, p.cost
                                                         HAVING sum(p.price *
                                                         s.units) > 5000;

>>> allflags = Flag.all()
>>> ui = UI.make(flag=allflags)
>>> term.width
80

Terminal is too narrow given selected flags, we switch to wrap_noindent mode
(TODO: this is buggy, the first line should be wrapped as well if too long)
>>> processes_rows(term, ui, SelectableProcesses(processes1), width=250)
6239   pgbench                   pgbench         postgres            local    0.1  1.0       7B      12B  0.000000  N    N      idle in trans   UPDATE pgbench_accounts SET abalance = abalance + 141 WHERE aid = 1932841;
6228   pgbench                   pgbench         postgres            local    0.2  1.0       0B    1.08M  0.000413  N    Y             active   \_ UPDATE pgbench_accounts SET abalance = abalance + 3062 WHERE aid = 7289374;
1234   business               accounting              bob            local    2.4  1.0    9.42M    1.21K  20:34.00  Y    N             active   SELECT product_id, p.name FROM products p LEFT JOIN sales s USING (product_id) WHERE s.date > CURRENT_DATE
- INTERVAL '4 weeks' GROUP BY product_id, p.name, p.price, p.cost HAVING sum(p.price * s.units) > 5000;

>>> ui = UI.make(flag=Flag.PID|Flag.DATABASE,
...              verbose_mode=QueryDisplayMode.truncate)
>>> processes_rows(term, ui, SelectableProcesses(processes1))
6239   pgbench               idle in trans   UPDATE pgbench_accounts SET abalanc
6228   pgbench                      active   \_ UPDATE pgbench_accounts SET abal
1234   business                     active   SELECT product_id, p.name FROM prod

>>> ui.evolve(verbose_mode=QueryDisplayMode.wrap)
>>> processes_rows(term, ui, SelectableProcesses(processes1))
6239   pgbench               idle in trans   UPDATE pgbench_accounts SET
                                             abalance = abalance + 141 WHERE aid
                                             = 1932841;
6228   pgbench                      active   \_ UPDATE pgbench_accounts SET
                                             abalance = abalance + 3062 WHERE
                                             aid = 7289374;
1234   business                     active   SELECT product_id, p.name FROM
                                             products p LEFT JOIN sales s USING
                                             (product_id) WHERE s.date >
                                             CURRENT_DATE - INTERVAL '4 weeks'
                                             GROUP BY product_id, p.name,
                                             p.price, p.cost HAVING sum(p.price
                                             * s.units) > 5000;

>>> processes2 = [
...     BWProcess(
...         pid="6239",
...         appname="pgbench",
...         database="pgbench",
...         user="postgres",
...         client="1.2.3.4",
...         mode="ExclusiveLock",
...         type="transactionid",
...         relation="None",
...         duration=666,
...         state="active",
...         query="END;"
...     ),
...     BWProcess(
...         pid="6228",
...         appname="pgbench",
...         database="pgbench",
...         user="postgres",
...         client="local",
...         mode="RowExclusiveLock",
...         type="tuple",
...         relation="ahah",
...         duration=0.000413,
...         state="idle in transaction",
...         query="UPDATE pgbench_branches SET bbalance = bbalance + 1788 WHERE bid = 68;",
...     ),
... ]
>>> ui.evolve(query_mode=QueryMode.waiting)
>>> processes_rows(term, ui, SelectableProcesses(processes2))
6239   pgbench                      active   END;
6228   pgbench               idle in trans   UPDATE pgbench_branches SET
                                             bbalance = bbalance + 1788 WHERE
                                             bid = 68;
>>> ui = UI.make(query_mode=QueryMode.blocking, flag=allflags)
>>> processes_rows(term, ui, SelectableProcesses(processes2), width=250)
6239   pgbench                   pgbench         postgres          1.2.3.4      None    transactionid    ExclusiveLock  11:06.00             active   END;
6228   pgbench                   pgbench         postgres            local      ahah            tuple RowExclusiveLock  0.000413      idle in trans   UPDATE pgbench_branches SET bbalance = bbalance + 1788 WHERE bid = 68;

>>> processes1b = [
...     RunningProcess(
...         pid=6239,
...         appname="pgbench",
...         database="pgbench",
...         user="postgres",
...         client="local",
...         state="idle in transaction",
...         query="UPDATE pgbench_accounts SET abalance = abalance + 141 WHERE aid = 1932841;",
...         duration=0.0,
...         wait=False,
...         is_parallel_worker=False,
...     ),
...     RunningProcess(
...         pid=6228,
...         appname="none",
...         database="pgbench",
...         user="postgres",
...         client="local",
...         state="active",
...         query="UPDATE pgbench_accounts SET abalance = abalance + 3062 WHERE aid = 7289374;",
...         duration=0.000413,
...         wait=False,
...         is_parallel_worker=True,
...     ),
...     RunningProcess(
...         pid=1234,
...         appname="accounting",
...         database="business",
...         user="bob",
...         client="192.168.0.47",
...         state="active",
...         query="SELECT product_id, p.name FROM products p LEFT JOIN sales s USING (product_id) WHERE s.date > CURRENT_DATE - INTERVAL '4 weeks' GROUP BY product_id, p.name, p.price, p.cost HAVING sum(p.price * s.units) > 5000;",
...         duration=1234,
...         wait=True,
...         is_parallel_worker=False,
...     ),
... ]
>>> all_but_local_flags = Flag.PID|Flag.DATABASE|Flag.APPNAME|Flag.USER|Flag.CLIENT|Flag.TIME|Flag.WAIT
>>> ui = UI.make(query_mode=QueryMode.activities,flag=all_but_local_flags)
>>> processes_rows(term, ui, SelectableProcesses(processes1b), width=200)
6239   pgbench                   pgbench         postgres            local  0.000000  N      idle in trans   UPDATE pgbench_accounts SET abalance = abalance + 141 WHERE aid = 1932841;
6228   pgbench                      none         postgres            local  0.000413  N             active   \_ UPDATE pgbench_accounts SET abalance = abalance + 3062 WHERE aid = 7289374;
1234   business               accounting              bob     192.168.0.47  20:34.00  Y             active   SELECT product_id, p.name FROM products p LEFT JOIN sales s USING (product_id) WHERE s.date
> CURRENT_DATE - INTERVAL '4 weeks' GROUP BY product_id, p.name, p.price, p.cost HAVING sum(p.price * s.units) > 5000;



Tests for footer_*()
--------------------

>>> footer_help(term)
F1/1 Running F2/2 Waiting F3/3 Blockin Space Pause/ q Quit       h Help         
>>> footer_interative_help(term)
C Cancel curre K Terminate cu Space Tag/unta Other Back to  q Quit              
>>> footer_message(term, "process 123 cancelled")
                             process 123 cancelled                              



Tests for screen()
------------------

>>> processes3 = [processes1[0], processes1[2]]

>>> host = Host("PostgreSQL 13", "testhost", "pgadm", "server.prod.tld", 5433, "app")
>>> dbinfo = DBInfo(10203040506070809, 9999)
>>> vmem = MemoryInfo(total=4_220_876_001, percent=2.5, used=1_001_232_608)
>>> swap = MemoryInfo(total=6_312_423_424, used=2_340, percent=1.0)
>>> io_read = IOCounter(bytes=128, count=6)
>>> io_write = IOCounter(bytes=8, count=9)
>>> load = LoadAverage(0.5, 1.9, 0.93)
>>> sysinfo = SystemInfo(vmem, swap, load, io_read, io_write, 76)
>>> ui = UI.make(
...     duration_mode=DurationMode.backend,
...     refresh_time=10,
...     min_duration=1,
...     query_mode=QueryMode.activities,
...     flag=Flag.PID|Flag.CPU|Flag.MEM|Flag.DATABASE,
...     sort_key=SortKey.cpu,
...     verbose_mode=QueryDisplayMode.truncate,
...     in_pause=False,
... )
>>> screen(
...     term,
...     ui,
...     host=host,
...     dbinfo=dbinfo,
...     tps=5,
...     active_connections=7,
...     activity_stats=(SelectableProcesses(processes3), sysinfo),
...     message=None,
...     width=150,
... )
PostgreSQL 13 - testhost - pgadm@server.prod.tld:5433/app - Ref.: 10s - Min. duration: 1s
 Size:         9.06P - 9.76K/s        | TPS:               5      | Active connections:               7      | Duration mode:     backend
 Mem.:      2.5% - 954.85M/3.93G      | IO Max:       76/s
 Swap:       1.0% - 2.29K/5.88G       | Read:          128B/s - 6/s
 Load:         0.50 1.90 0.93         | Write:          8B/s - 9/s
                                RUNNING QUERIES
PID    DATABASE           CPU% MEM%              state   Query
1234   business            2.4  1.0             active   SELECT product_id, p.name FROM products p LEFT JOIN sales s USING (product_id) WHERE s.date >
6239   pgbench             0.1  1.0      idle in trans   UPDATE pgbench_accounts SET abalance = abalance + 141 WHERE aid = 1932841;
F1/1 Running queries    F2/2 Waiting queries    F3/3 Blocking queries   Space Pause/unpause     q Quit                  h Help                        

(using terminal width)
>>> screen(
...     term,
...     ui,
...     host=host,
...     dbinfo=dbinfo,
...     tps=5,
...     active_connections=7,
...     activity_stats=(SelectableProcesses(processes3[:-1]), sysinfo),
...     message=f"Process {processes3[-1].pid} killed",
... )
PostgreSQL 13 - testhost - pgadm@server.prod.tld:5433/app - Ref.: 10s - Min.
 Size:         9.06P - 9.76K/s        | TPS:               5      | Active
 Mem.:      2.5% - 954.85M/3.93G      | IO Max:       76/s
 Swap:       1.0% - 2.29K/5.88G       | Read:          128B/s - 6/s
 Load:         0.50 1.90 0.93         | Write:          8B/s - 9/s
                                RUNNING QUERIES
PID    DATABASE           CPU% MEM%              state   Query
1234   business            2.4  1.0             active   SELECT product_id, p.na
                              Process 6239 killed                               
