Skip to content

gregtatum/spec-cpp

Repository files navigation

C++ Learning Spec

This is a test suite that encapsulates my C++ learning in a series of tests. The building process is done through a makefile so from the command line run make to build it, and then ./main to run it. Or do both steps at the same time with make test. Individual tests can be run by setting the TEST environment variable.

make test TEST=features::pointers

Requirements

The build process assumes that clang++ is on the path with the ability to use the std library c++1y.

ICU4C was added as a library, and it must be added to /usr/local. This directory is specified in makefile-icu.mk. To install the ICU library on macOS:

git clone git@github.com:unicode-org/icu.git
cd icu/icu4c/source
./runConfigureICU MacOSX

Test output


features::arrays

  arrays can be created on the stack.
    ✔ An array was created, but it's still uninitialized. Acces
    ✔ The value can be accessed, but its value could be anything. UNDEFINED BEHAVIOR
    ✔ Value at index 0 can be accessed
    ✔ Value at index 1 can be accessed
    ✔ Value at index 2 can be accessed
    ✔ Value at index 3 can be accessed
    ✔ The compiler doesn't care if we unintentionally read values outside of the array. UNDEFINED BEHAVIOR
  arrays can be initialized in one line
    ✔ Value at index 0 can be accessed
    ✔ Value at index 1 can be accessed
    ✔ Value at index 2 can be accessed
  arrays can be created through 'universal initialization'
    ✔ Value at index 0 can be accessed
    ✔ Value at index 1 can be accessed
    ✔ Value at index 2 can be accessed
  Arrays don't need to have every entry initialized
    ✔ Value at index 0 can be accessed
    ✔ Value at index 1 is not initialized
  Static arrays are always initialized to 0.
    ✔ The value is 0
    ✔ The value is 0
    ✔ The value is 0
  Heap allocated arrays
    ✔ Created 11 on the heap
    ✔ Created 22 on the heap
    ✔ Created 33 on the heap
  Arrays can be passed to functions
    ✔ One was added to array
    ✔ One was added to array
    ✔ One was added to array
  Arrays can be treated like pointers, and the memory address is copied to the calling function
    ✔ One was added to the first element
    ✔ The rest of the array is not modified
    ✔ The rest of the array is not modified
  Pointer arithmetic works on arrays coerced to pointers
    ✔ Can read the first element as a pointer
    ✔ Can read the second element using pointer arithmetic
    ✔ Can read the second element using pointer arithmetic
  You can pass by references, but only at a fixed array size
    ✔ First element not modified
    ✔ Second element was modified because the function call returned an lvalue reference
    ✔ The third element was not modified
  Passing arrays is mainly type checking by the compiler, but then it copies the memory address of the array to the callee's arguments.
    ✔ The memory values are the same.
  array sizeof() and passing arrays to functions
    ✔ The size of the first member is that of an int
    ✔ The same is true when looking at as a pointer
    ✔ The size of the array element is only accessible on the current stack
    ✔ Variable lengths can be created, but they are only stored on the current stack
    ✔ When passing to a function, the stack-allocated array degrades to a pointer.
    ✔ This also happens even when the size of the array in the arguments is explicit, like array[6]
    ✔ Size arguments are a lie

features::classes

  nested classes
    ✔ Can create a NestedOuterClass on the stack.
    ✔ Can create a NestedInnerClass, and access a static variable.
    ✔ Can create a NestedInnerClass, and access a static variable.
    ✔ Can create a NestedInnerClass, and access a static variable.
  default initialize in-class
    ✔ It can default initialize.
    ✔ It creates a string

features::const_test

  object of const type, 'const-qualified type'
    ✔ The numbers match
  const specifier can be before and after the type
    ✔ const before
    ✔ const after
  structs of const type do not have interior mutability
    ✔ The numbers match
  const-ness of class definitions
    ✔ GetNumber requires const in the function declaration
  const struct members
  const structs with mutable members
    ✔ The numbers match
  const pointers cannot have their contents mutated
  *const can be mutated but not re-assigned
  Consts can be combined: const TestStruct *const
  const as function arguments
    ✔ The function can add one.
  const can be cast away
    ✔ 

features::icu

  basic usage
    ✔ A pattern can be generated.
    ✔ The date can be formatted
  time zone testing
    ✔ A pattern can be generated.
    ✔ The date can be formatted
  combine date and time when formatting dates
    ✔ A pattern can be generated.
    ✔ The date can be formatted
  number format
    ✔ CurrencyUnit had no errors.
    ✔ FormatInt had no errors.
    ✔ ToString had no errors.
    ✔ The number can be formatted.
  empty string skeleton
    ✔ A pattern can be generated.
    ✔ The date can be formatted
  fixed decimal format approximation
    ✔ Formatting had no errors.
    ✔ The number can be formatted.
  fixed decimal format approximation
    ✔ Formatting had no errors.
    ✔ The number can be formatted.
  fixed decimal format approximation
    ✔ Formatting had no errors.
    ✔ The number can be formatted.

features::icu_capi

  udat_format with the C api
    ✔ Malloc succeeded.
    ✔ The strings are equal
  udat_format with the C api, truncated
    ✔ Able to create a date format object.
    ✔ The buffer overflowed.
    ✔ Formatted the string correctly into the buffer.
    ✔ The strings are equal

features::lvalueReference

  lvalue references
    ✔ The int value is 32
    ✔ The ref value is the same
    ✔ The int value has changed
    ✔ So has the ref value
    ✔ The ref value is changed
    ✔ The original value has changed as well
  const lvalue references
    ✔ The int value is 32
    ✔ The ref value is the same
    ✔ The int value has changed
    ✔ The ref value will change even thought it's const
  passing lvalue references to functions
    ✔ Starts as 32
    ✔ Is mutated and added by one
    ✔ The new value is 34
    ✔ But the original can't be changed
  lvalue references can be returned from another function
    ✔ Got the second entry
    ✔ The array value can be updated
    ✔ The array value can be updated
  lvalue references can be assigned to, as they are lvalues
    ✔ The array value is updated too
  lvalue references can be stored in structs
    ✔ The ref struct holds the value 32
    ✔ The struct holds the value 32
    ✔ The ref struct's value can be changed.
    ✔ The non-ref struct's value remains the same.
    ✔ The original value changes too
  lvalue references in structs can't break out to outer lexical scopes
    ✔ The ref struct can be initialized with a value.
    ✔ The struct  can be initialized with a value.
    ✔ Setting the intHolder in a different lexical scope is fine, as the value is copied.
    ✔ We can't assign a reference to a value in a exterior lexical scope block

features::misc

  std::string
    ✔ String comparison
    ✔ String view comparison
  constexpr
    ✔ The area is computed at compile time.
    ✔ The area is computed at run time.
    ✔ The area can be re-computed on changing member values
  using namespace
    ✔ 'using' follows normal scoping rules
    ✔ Namespaces can be used individually to simplify namespaces
    ✔ 'using' is bound by lexical scopes
  lambda basic
    ✔ Lambdas can be defined inline
  lambdas can take arguments
    ✔ 3+5=8
  lambdas can explicitly capture values
    ✔ 3+5+1=9
  lambdas capture by copying a value
    ✔ 3+5+1=9
  lambdas can also capture by reference
    ✔ 3+5+2=10
  lambdas can implictly capture values
    ✔ 3+5+1=9
  lambdas can implictly capture by copy
    ✔ 3+5+1=9
  lambdas can implictly capture by reference
    ✔ 3+5+2=10
  capture defaults and explicit copy captures
    ✔ It adds the original values.
    ✔ b is explicitly copied, while a is by reference

features::pointers

  stack values
    ✔ Declaring a simple value puts it on the stack.
  puts a value on the heap
    ✔ 🚧  The value is not initialized, so it could be anything. (possibly intermittent)
    ✔ Values placed on the heap can be accessed through the * operator.
  the value on the stack is the memory address of the heap
    ✔ The value itself is a memory address, so it shouldn't equal our value.
    ✔ The memory address is still in lexical scope and can be re-assigned, but it points at possibly anything in memory. Accesing it is UNDEFINED BEHAVIOR!
  multiple pointers point to the same place in memory
    ✔ The values are in the heap are the same
    ✔ The value on the stack is initially the same as what's on the heap
    ✔ The value on the heap was updated
    ✔ The other pointer points to the same value
    ✔ The value on the stack is a separate value, and is not updated
  references
    ✔ The value is on the stack
    ✔ The reference points to the value on the stack.
    ✔ The value on the stack was updated
    ✔ This is reflected in our own pointer.
  passing around pointers
    ✔ Starts as 32
    ✔ Is mutated and added by one
    ✔ The new value is 34
    ✔ But the original can't be changed

features::rvalueReference

  rvalue references
    ✔ rvalue references point to temporary values
  rvalue references can be passed to functions
    ✔ The rvalue reference function added one.

features::copymove

  Copyable
  MoveOnly
  DisableCopyMove
  Unspecified
  MoveOnlyMember

features::smartPointers

  Create a unique_ptr
    ✔ Can create a smart pointer
    ✔ After leaving it's scope, the reference is removed.
  Delete it before the end of the scope
    ✔ Can create a smart pointer
    ✔ Reseting deletes the object at the reference.
  Release the ownership of the object
    ✔ Can create a smart pointer
    ✔ The object was not removed from the heap
    ✔ The object was manually removed
  Create a shared_ptr
    ✔ A shared pointer is created, and shared with the outer scope
    ✔ The pointer is still shared, so the underlying object still exists.
    ✔ After leaving both scope, the object is destructed
  Create a weak_ptr
    ✔ A shared pointer is created, and shared with the outer scope
    ✔ The weak pointer is not expired
    ✔ The pointer should be deleted, as it was only weakly held
    ✔ The weak pointer is expired
  Create a weak_ptr, but lock it
    ✔ A shared pointer is created, and shared with the outer scope
    ✔ The weak pointer is not expired
    ✔ The pointer is still alive, because the weak ptr locked it
    ✔ The weak pointer is expired
    ✔ The lock and original value are out of scope, the object was deleted
    ✔ The weak pointer is expired

features::primes

  timing in serial
    ℹ It took 31 microseconds to compute 1000 primes in serial
  timing in parallel
    ℹ It took 567 microseconds to compute 1000 primes using concurrent writers

features::threads

  Created a thread

features::vector

  Can create a vector
  Vectors can be initialized with a size
    ✔ Vectors initialized with a size
  toString helper
    ✔ It creates a debug string for arrays with values.
    ✔ It creates a debug string for arrays without values.
  Vectors are initialized to 0
    ✔ Nothing is in the vector yet.
  Vectors can be pushed onto
    ✔ Nothing is in the vector yet.
    ✔ It has no size
    ✔ It has no capacity
    ✔ One thing is in the vector.
    ✔ Its size matches length
    ✔ Its capacity matches the size
    ✔ Two things are on the vector.
    ✔ Its size matches length
    ✔ Its capacity matches the size
    ✔ One thing is in the vector.
    ✔ Its size matches length
    ✔ Its capacity has not changed.
  Vectors retain capacity when popping
    ✔ One thing is in the vector.
    ✔ Its size matches length
    ✔ Its capacity still has the initial sizing.
  Vectors can be resized
    ✔ Size adds on to the size.
  Vectors can be resized with a value
    ✔ Size adds on to the size.
  std::vector::at
    ✔ Value can be access
    ✔ Value can be access
    ✔ Value can be access
    ✔ This is an out of range exception.
  std::vector::[]
    ✔ Value can be access
    ✔ Value can be access
    ✔ Value can be access
    ✔ UNDEFINED VALUE: It allows you to access out of range values.
  std::vector::at can be used as an lvalue
    ✔ The first item was assigned to.
  std::vector accessors
    ✔ Can access the front
    ✔ Can access the back
    ✔ Can access the underlying data
    ✔ Can access the underlying data
    ✔ Can access the underlying data
  std::vector only copies data, it does not modify it
    ✔ It matches the original, not the modified
  std::vector can be passed as a C-style array
24    ✔ 
  std::vector by default deep-clones in structs
    ✔ deux.a matches
    ✔ deux.b matches
    ✔ trois.a matches
    ✔ trois.b matches
    ✔ deux.a matches
    ✔ deux.b matches
    ✔ trois.a matches
    ✔ trois.b matches
  std::span with std::vector
    ✔ vector matches
    ✔ span matches
    ✔ vector changed
    ✔ the span changed too

rusty::box

  Box()
    ✔ Can create a boxed int
  Box destructor called for the pointer
    ✔ The destructor for the box was called
  Can convert to a raw pointer
    ✔ Can turn into a normal pointer.

rusty::option

  Option
    ✔ Can unwrap a value
    ✔ A some value is Some
    ✔ A some value is not None
    ✔ Cannot unwrap a None
    ✔ A none value is not Some
    ✔ A none value is None

rusty::vec

  Vec
    ✔ The vector starts with 0 capacity
    ✔ The initial length is also 0.
  Vec::push
    ✔ The capacity is now 1
    ✔ The length is also 1
    ✔ The value added is 1
    ✔ The second value is none
    ✔ The capacity is doubled after a push
    ✔ The length is also doubled after a push
    ✔ The value was added
    ✔ The value was added
    ✔ The last value is none
    ✔ The capacity is doubled after a push
    ✔ The length is only incremented
    ✔ The value was added
    ✔ The value was added
    ✔ The value was added
    ✔ The last value is none

src::test

  Assertions
    ✔ Does not throw
    ✔ Equality does work

mfbt::TestMaybe

  mozilla::Some
    ✔ There is some value
    ✔ There is not nothing
    ✔ There is a value
    ✔ There is a value
    ✔ Can access via pointer
    ✔ Can access via reference
  mozilla::Nothing
    ✔ There is no value
    ✔ This is nothing
    ✔ There is not value, so use default
  Can emplace a value
    ✔ There is no value
    ✔ There is now an emplaced value
  Can emplace a value with interesting constructors
    ✔ There is now an emplaced value

mfbt::TestRefPtr

  RefPtr works just like a unique_ptr with one reference
    ✔ Has one reference
    ✔ No objects have been killed in the inner scope
    ✔ The reference counted object is killed
  nullptr
    ✔ Uninitialized pointers are false on if checks
    ✔ RefPtr can be assigned to a nullptr
    ✔ RefPtr of course can be assigned.
  reassignment
    ✔ A starts with 1 ref count
    ✔ B starts with 1 ref count
    ✔ The references to A are now 2
    ✔ The references to B are now 2, as it's the same as A
    ✔ One object has been killed
    ✔ Both have been killed
  RefPtr pointer behavior
    ✔ It works like a normal pointer calling member functions.
  RefPtr can have multiple references and properly count them
    ✔ Has one reference
    ✔ Has two reference
    ✔ Has two reference
    ✔ No objects have been killed in the inner scope
    ✔ One reference was removed when it went out of scope
    ✔ No objects have been killed in the middle scope
    ✔ The reference counted object is killed
  observe the refcount by passing a copy of the RefPtr to a function
    ✔ Has one reference at the beginning
    ✔ It had two reference counts in the function call.
    ✔ Has one reference after the function call
    ✔ No objects have been killed in the inner scope
    ✔ The reference counted object is killed
  DANGEROUS! observe the refcount by passing a pointer to the RefPtr to a function
    ✔ Has one reference at the beginning
    ✔ DANGER! Passing by raw pointer obliterates the contract.
    ✔ Has one reference after the function call
    ✔ No objects have been killed in the inner scope
    ✔ The reference counted object is killed
  RefPtr retained by a static
    ✔ Has one reference after initialization
    ✔ Has two references, as one is kept as a static property
    ✔ The RefPtr was still not killed, as it is being retained by the HasStaticObj
    ✔ The reference had to be manually deleted

mfbt::TestResult

  Vectors are initialized to 0
    ✔ Nothing is in the vector yet.
  mozilla::Result
    ✔ Types match

memory::allocator

  A basic allocation
    ✔ No bytes allocated
    ✔ No bytes allocated
    ✔ It was able to allocate something
    ✔ Allocated some bytes
    ✔ It allocated a single aligned block
  Multiple allocations
    ✔ It was able to allocate something
    ✔ It was able to allocate something
    ✔ It was able to allocate something
    ✔ Allocated some bytes
    ✔ It allocated many aligned blocks
  Setting values at allocations
    ✔ a is equal to 11
    ✔ b is equal to 22
    ✔ c is equal to 33
  Freeing all allocations
    ✔ Some bytes have been allocated.
    ✔ Freeing the allocations results in no bytes.
  Re-using space when freeing up the memory
    ✔ a is equal to 11
    ✔ b is equal to 22
    ✔ c is equal to 33
    ✔ a2 is equal to 44
    ✔ b2 is equal to 55
    ✔ c2 is equal to 66
    ✔ a1 is equal to 44
    ✔ b1 is equal to 55
    ✔ c1 is equal to 66
  Values allocated get aligned to 8 bytes.
    ✔ The int is less than 8 bytes
    ✔ The allocation block is aligned
    ✔ The two allocations are aligned 8 bytes apart, plus the allocation block size.
  Values can be freed
    ✔ None of the original values are touched. a is equal to 11
    ✔ None of the original values are touched. b is equal to 22
    ✔ None of the original values are touched. c is equal to 33
    ✔ The re-allocated memory re-used the freed spot
    ✔ The original spot had its value changed.
    ✔ The new spot had its value changed.
  Freeing a block after an already free block will combine them into one block
    ✔ Starts out with 4 blocks
    ✔ After freeing the two middle ones, they are combined, and only 3 remain.
  Freeing a block before an already free block will combine into one block
    ✔ Starts out with 4 blocks
    ✔ After freeing the two middle ones, they are combined, and only 3 remain.
  Can allocate into a free block
    ✔ a is equal to 11
    ✔ b is equal to 22
    ✔ c is equal to 33
    ✔ d is equal to 33
    ✔ a is still equal to 11
    ✔ d is still equal to 33
    ✔ e is equal to 55
    ✔ The a block is earlier than the d block
    ✔ The e block was placed before the d block
    ✔ The e block was placed in the b block position

memory::stack

  Stack values are sequentially created backwards on the stack
    ✔ The diff of the addresses match
    ✔ The diff of the addresses match
    ✔ The diff of the addresses match
    ✔ The diff of the addresses match
  Stack values can be accessed using pointer arithmetic
    ✔ Can access the values via pointer arithmetic
    ✔ Can access the values via pointer arithmetic
    ✔ Can access the values via pointer arithmetic
    ✔ Can access the values via pointer arithmetic
    ✔ Can access the values via pointer arithmetic
  Stack values can be accessed using raw memory addresses
    ✔ Can access the values by raw memory access
    ✔ Can access the values by raw memory access
    ✔ Can access the values by raw memory access
    ✔ Can access the values by raw memory access
    ✔ Can access the values by raw memory access
  Stack values can be CHANGED using raw memory addresses, even on const values
    ✔ Value on the stack was changed
    ✔ Value on the stack was changed
    ✔ Value on the stack was changed
  Arrays are stack allocated
    ✔ Value at address matches array value
    ✔ Value at address matches array value
    ✔ Value at address matches array value
    ✔ Value at address matches array value
    ✔ Value at address matches array value
    ✔ Value at address matches array value
    ✔ Value at address matches array value
    ✔ Value at address matches array value
    ✔ Value at address matches array value
    ✔ Array 'a' matches when looking it up
    ✔ Array 'b' matches when looking it up
    ✔ Array 'c' matches when looking it up

 All tests passed!

About

An encoding of my C++ learnings into a spec test suite

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages