logo
首页技术栈工具库讨论
lio
lio
The Labeled IO (LIO) library is an information flow control (IFC) library. IFC is a mechanism that enforces security policies by tracking and controlling the flow of information within a system. Unlike discretionary access control (such as UNIX file permissions), IFC permits scenarios in which untrusted computation may have the ability to manipulate secret data without having the ability to further disclose that data. LIO is an IFC library that can be used to implement such untrusted computations. LIO provides combinators similar to those of IO for performing side-effecting computations (e.g., modifying mutable references, forking threads, throwing and catching exceptions, etc.) To track and control the flow of information, LIO associates a security policy, called a label, with every piece of data. A label may, for example, impose a restriction on who can observe, propagate, or modify the data to which it applies. Unlike standard IO operations, the LIO counterparts check the vailidity of labels before performing the (underlying IO) side-effecting computation. For example, before writing to a labeled variable, LIO asserts that the write will not violate any security policies associated with the data to be written. Most code should import module LIO and whichever label format the application is using (e.g., LIO.DCLabel to use the format that ships with the library). Side-effecting code should be specified as actions in the LIO monad. See LIO.Core for a description of the core library API, LIO.Label for a discussion of labels, and LIO.Run for functions allowing one to run an LIO computation from the IO monad. WARNING: For security, untrusted code must always be compiled with the -XSafe and -fpackage-trust SafeHaskell flags. See http://www.haskell.org/ghc/docs/latest/html/users_guide/safe-haskell.html for more details on the guarantees provided by SafeHaskell.
tdd-util
tdd-util
tdd-util is a small test framework for TDD (cf. https://en.wikipedia.org/wiki/Test-driven_development) that integrates three testing libraries, whose modules are all exported under Test.Util.Framework, while providing utilities based on each of these, exported under Test.Util, by wrapping the library test-framework. Getting Started To get started, an example that uses this library is this library's test suite itself and can be found at https://github.com/bairyn/tdd-util/tree/master/testsrc. Each module under src corresponds with a module under testsrc/Test that contains the tests for that module. (For example, this library currently exports two modules in src/Test/Util.hs and src/Test/Util/Framework.hs; their tests are located, respectively, in testsrc/Test/Test/Util.hs and testsrc/Test/Test/Util/Framework.hs; and a module in src/Data/Trie.hs would correspond with a test module in testsrc/Test/Trie.hs). This structure can be conveniently cargo culted from this library, but these conventions are not enforced. Test Modules Conventially, each module in src/X.hs corresponds with a module that contains tests for that module located at testsrc/Test/X.hs. None of these Test modules depend on each other by importing them. For a concrete example of such a test module, see https://github.com/bairyn/tdd-util/blob/master/testsrc/Test/Test/Util.hs. Each test module exports a list of test-framework's TTests (an alias to disambiguate between Test types from different libraries) named tests. This list of tests can either be run individually by importing the test module, and then running defaultMain tests; or be grouped together in the test-suite's Tests module (see below). In the tests themselves, very briefly, testGroup "Brief description of test" […] can be used to construct a single test-framework test (TTest) from a group of other tests, testProperty name prop_foo can be used to construct a TTest from a QuickCheck property, and testCase name $ do … can be used to construct a test from HUnit. See test-framework's documentation for more information about constructing QuickCheck and HUnit properties. Here is a segment of code from https://github.com/bairyn/tdd-util/blob/master/testsrc/Test/Test/Util.hs: Tests.hs Each test module is conventionally grouped into a single test module, at testsrc/Tests.hs (e.g. see https://github.com/bairyn/tdd-util/blob/master/testsrc/Tests.hs), that exports a list of TTests named tests. Interactively, this test module can be loaded in ghci, and the tests can be run as before, with defaultMain tests. These tests can also be specified in the project's cabal file, by invoking defaultMain on tests in an external Main.hs file under testsrc (e.g. see https://github.com/bairyn/tdd-util/blob/master/testsrc/Main.hs). Running this Main.hs will result in the test suite being run, so a test-suite section can be added to the cabal file as it is in https://github.com/bairyn/tdd-util/blob/master/tdd-util.cabal. When a test suite is specified, cabal will recognized it and, when configured to do so, will run it when installing your package, resulting in output that may look like this when it succeeds. This package's Tests.hs: Main.hs Example Main.hs conventially defines a simple program that invokes defaultMain tests from the test group that encapsulates the entire test suite in Tests.hs. Here is this package's Main.hs file: Cabal Configuration Your package's cabal configuration can be updated to point to testsrc/Main.hs/; here is a segment in this package's Cabal file that contains part of the specification for the package's test suite: Note that tdd-util is the only TDD library one needs to depend on, if one only uses QuickCheck, HUnit, and test-framework via Test.Util.Framework; this omission is strictly optional, of course. Test Running Example Here is the output of importing Test.Test.Util inside the testsrc directory and then running tests on my system (note this is not the result of running the entire test suite; to do that, either run Main.hs or run, with defaultMain, the tests exported from Tests.hs rather than Test.Test.Util), without the coloured formatting:
goldplate
goldplate
For package maintainers and hackage trustees goldplate is a cute and simple opaque golden test runner for CLI applications. You place your test cases in a directory, annotate them with .goldplate files, and that's it. It is completely language agnostic. And perhaps its best feature is that it can automatically✨🪄 fix your tests outputs! Give goldplate a try if: At Fugue, we've been using internal versions of this tool since 2016, so it should be pretty stable. Imagine we are up to testing the behaviour of echo command. In this very simple example, we run echo "Hello, world!" and expect it to print Hello, world! to the stdout stream as a result. Create a new file echo.goldplate and add the following content: Let's go through this bit by bit. The test invocation is specified by the command and arguments fields. We are invoking the echo process with a single argument, "Hello, world!". The expected results of our test live in the asserts field. This simple test has two asserts: We haven't created hello-world.txt yet, but that's not a problem. We can invoke goldplate --fix to create it: After hello-world.txt has been created with proper contents, subsequent goldplate invocations will pass: You can view the full example here: View example: You can pass one or multiple lines of input to the command by using the stdin field. View example: The environment field can be used to set environment variables for the program. goldplate also sets a number of environment variables. You can use these directly within the configuration JSON. In this example, we use: Rather than: We found this to be good practice, it makes mass-renaming of tests much easier. View example: .goldplate files are fairly small but if you have a whole directory of files that you just want to run the same command on, they can get very repetitive. This is why goldplate provides a simple way to pull in multiple input files. If the input_files field is set to a glob, all asserts will be ran for every matching input file. goldplate will set the following variables: View example: Sometimes you may want to do a find-and-replace on the actual output, for example to filter out timestamps or other information that you do not expect to match up against the expected output. View example: Many modern CLI tools output JSON. You can use the prettify_json post processor to make sure the JSON is converted to a normalized form with sorted keys and consistent indentation. View example: goldplate is geared towards checking the stdout and stderr outputs of a program, but you can also check that files were created with specific contents. If you do this, goldplate will remove these files and directories afterwards to leave a clean repository behind. Installation through source is done using standard Haskell tooling -- Cabal and stack both work well. Environment variables can be spliced into the configuration using ${VAR} syntax within strings. To escape this syntax, use $${VAR} to get a literal ${VAR}, $$${VAR} to get a literal $${VAR}, and so on. The test is always executed in the directory that holds the .goldplate file. goldplate will always set the following environment variables: When dealing with multiple input files, the following additional variables are set: Here is an example that outputs all of these environment variables: A similar project is smoke. I think goldplate has two major advantages over smoke:
streams
streams
Various Haskell 2010 stream comonads. * Data.Stream.Future provides a coinductive anti-causal stream, or non-empty ZipList. The comonad provides access to only the tail of the stream. Like a conventional ZipList, this is not a monad. Data.Stream.Future.Skew provides a non-empty skew-binary random-access-list with the semantics of Data.Stream.Future. As with Data.Stream.Future this stream is not a Monad, since the Applicative instance zips streams of potentially differing lengths. The random-access-list structure provides a number of operations logarithmic access time, but makes Data.Stream.Future.Skew.cons less productive. Where applicable Data.Stream.Infinite.Skew may be more efficient, due to a lazier and more efficient Applicative instance. Data.Stream.Infinite provides a coinductive infinite anti-causal stream. The Comonad provides access to the tail of the stream and the Applicative zips streams together. Unlike Future, infinite stream form a Monad. The monad diagonalizes the Stream, which is consistent with the behavior of the Applicative, and the view of a Stream as a isomorphic to the reader monad from the natural numbers. Being infinite in length, there is no Alternative instance. Data.Stream.Infinite.Skew provides an infinite skew-binary random-access-list with the semantics of Data.Stream.Infinite Since every stream is infinite, the Applicative instance can be considerably less strict than the corresponding instance for Data.Stream.Future.Skew and performs asymptotically better. Data.Stream.Infinite.Functional.Zipper provides a bi-infinite sequence, represented as a pure function with an accumulating parameter added to optimize moving the current focus. Data.Stream.Supply provides a comonadic supply of unique values, which are generated impurely as the tree is explored.
cassy
cassy
The objective is to completely isolate away the thrift layer, providing a more idiomatic and naruall Haskell experience working with Cassandra. Be sure to check out the README on Github for some more explanation and Release Notes, which is helpful in talking about what this library can do. Certain parts of the API was inspired by pycassa (Python client) and hscassandra (on Hackage). Please see the Github repository for more detailed documentation, release notes and examples. A brief explanation of modules: Database.Cassandra.Basic: Contains a low level, simple implementation of Cassandra interaction using the thrift API underneath. Database.Cassandra.Marshall: Intended to be the main high level module that you should use, Marshall allows you to pick the serialization strategy you would like to use at each function call. We recommend using casSafeCopy due to its support for evolving data types, although casJSON maybe another popular choice. Database.Cassandra.JSON: (Now deprecated; use Marshall instead) A higher level API that operates on values with ToJSON and FromJSON isntances from the aeson library. This module has in part been inspired by Bryan O'Sullivan's riak client for Haskell. Database.Cassandra.Pool: Handles a pool of connections to multiple servers in a cluster, splitting the load among them. Database.Cassandra.Pack: Handles column types that Cassandra recognizes and adds support for Composite Columns. Database.Cassandra.Types: A common set of types used everywhere. Potential TODOs include: Support for counters and batch mutators Support for database admin operations