text:
require 'spec_helper'

ML = Regexp::MatchLength

RSpec.describe(Regexp::MatchLength) do
  specify('literal') { expect(ML.of(/a/).minmax).to eq [1, 1] }
  specify('literal sequence') { expect(ML.of(/abc/).minmax).to eq [3, 3] }
  specify('dot') { expect(ML.of(/./).minmax).to eq [1, 1] }
  specify('set') { expect(ML.of(/[abc]/).minmax).to eq [1, 1] }
  specify('type') { expect(ML.of(/\d/).minmax).to eq [1, 1] }
  specify('escape') { expect(ML.of(/\n/).minmax).to eq [1, 1] }
  specify('property') { expect(ML.of(/\p{ascii}/).minmax).to eq [1, 1] }
  specify('codepoint list') { expect(ML.of(/\u{61 62 63}/).minmax).to eq [3, 3] }
  specify('multi-char literal') { expect(ML.of(/abc/).minmax).to eq [3, 3] }
  specify('fixed quantified') { expect(ML.of(/a{5}/).minmax).to eq [5, 5] }
  specify('range quantified') { expect(ML.of(/a{5,9}/).minmax).to eq [5, 9] }
  specify('nested quantified') { expect(ML.of(/(a{2}){3,4}/).minmax).to eq [6, 8] }
  specify('open-end quantified') { expect(ML.of(/a*/).minmax).to eq [0, Float::INFINITY] }
  specify('empty subexpression') { expect(ML.of(//).minmax).to eq [0, 0] }
  specify('anchor') { expect(ML.of(/^$/).minmax).to eq [0, 0] }
  specify('lookaround') { expect(ML.of(/(?=abc)/).minmax).to eq [0, 0] }
  specify('free space') { expect(ML.of(/   /x).minmax).to eq [0, 0] }
  specify('comment') { expect(ML.of(/(?#comment)/x).minmax).to eq [0, 0] }
  specify('backreference') { expect(ML.of(/(abc){2}\1/).minmax).to eq [9, 9] }
  specify('subexp call') { expect(ML.of(/(abc){2}\g<-1>/).minmax).to eq [9, 9] }
  specify('alternation') { expect(ML.of(/a|bcde/).minmax).to eq [1, 4] }
  specify('nested alternation') { expect(ML.of(/a|bc(d|efg)/).minmax).to eq [1, 5] }
  specify('quantified alternation') { expect(ML.of(/a|bcde?/).minmax).to eq [1, 4] }
  if ruby_version_at_least('2.4.1')
    specify('absence group') { expect(ML.of('(?~abc)').minmax).to eq [0, Float::INFINITY] }
  end

  specify('raises for missing references') do
    exp = RP.parse(/(a)\1/).last
    exp.referenced_expression = nil
    expect { exp.match_length }.to raise_error(ArgumentError)
  end

  describe('::of') do
    it('works with Regexps') { expect(ML.of(/foo/).minmax).to eq [3, 3] }
    it('works with Strings') { expect(ML.of('foo').minmax).to eq [3, 3] }
    it('works with Expressions') { expect(ML.of(RP.parse(/foo/)).minmax).to eq [3, 3] }
  end

  describe('Expression::Base#match_length') do
    it('returns the MatchLength') { expect(RP.parse(/abc/).match_length.minmax).to eq [3, 3] }
  end

  describe('Expression::Base#inner_match_length') do
    it 'returns the MatchLength of an expression that does not count towards parent match_length' do
      exp = RP.parse(/(?=ab|cdef)/)[0]
      expect(exp).to be_a Regexp::Expression::Assertion::Base
      expect(exp.match_length.minmax).to eq [0, 0]
      expect(exp.inner_match_length.minmax).to eq [2, 4]
    end
  end

  describe('#include?') do
    specify('unquantified') do
      expect(ML.of(/a/)).to include 1
      expect(ML.of(/a/)).not_to include 0
      expect(ML.of(/a/)).not_to include 2
    end

    specify('fixed quantified') do
      expect(ML.of(/a{5}/)).to include 5
      expect(ML.of(/a{5}/)).not_to include 0
      expect(ML.of(/a{5}/)).not_to include 4
      expect(ML.of(/a{5}/)).not_to include 6
    end

    specify('variably quantified') do
      expect(ML.of(/a?/)).to include 0
      expect(ML.of(/a?/)).to include 1
      expect(ML.of(/a?/)).not_to include 2
    end

    specify('nested quantified') do
      expect(ML.of(/(a{2}){3,4}/)).to include 6
      expect(ML.of(/(a{2}){3,4}/)).to include 8
      expect(ML.of(/(a{2}){3,4}/)).not_to include 0
      expect(ML.of(/(a{2}){3,4}/)).not_to include 5
      expect(ML.of(/(a{2}){3,4}/)).not_to include 7
      expect(ML.of(/(a{2}){3,4}/)).not_to include 9
    end

    specify('branches') do
      expect(ML.of(/ab|cdef/)).to include 2
      expect(ML.of(/ab|cdef/)).to include 4
      expect(ML.of(/ab|cdef/)).not_to include 0
      expect(ML.of(/ab|cdef/)).not_to include 3
      expect(ML.of(/ab|cdef/)).not_to include 5
    end

    specify('called on leaf node') do
      expect(ML.of(RP.parse(/a{2}/)[0])).to include 2
      expect(ML.of(RP.parse(/a{2}/)[0])).not_to include 0
      expect(ML.of(RP.parse(/a{2}/)[0])).not_to include 1
      expect(ML.of(RP.parse(/a{2}/)[0])).not_to include 3
    end
  end

  describe('#fixed?') do
    specify('unquantified') { expect(ML.of(/a/)).to be_fixed }
    specify('fixed quantified') { expect(ML.of(/a{5}/)).to be_fixed }
    specify('variably quantified') { expect(ML.of(/a?/)).not_to be_fixed }
    specify('equal branches') { expect(ML.of(/ab|cd/)).to be_fixed }
    specify('unequal branches') { expect(ML.of(/ab|cdef/)).not_to be_fixed }
    specify('equal quantified branches') { expect(ML.of(/a{2}|cd/)).to be_fixed }
    specify('unequal quantified branches') { expect(ML.of(/a{3}|cd/)).not_to be_fixed }
    specify('empty') { expect(ML.of(//)).to be_fixed }
  end

  describe('#each') do
    it 'returns an Enumerator if called without a block' do
      result = ML.of(/a?/).each
      expect(result).to be_a(Enumerator)
      expect(result.next).to eq 0
      expect(result.next).to eq 1
      expect { result.next }.to raise_error(StopIteration)
    end

    it 'is aware of limit option even if called without a block' do
      result = ML.of(/a?/).each(limit: 1)
      expect(result).to be_a(Enumerator)
      expect(result.next).to eq 0
      expect { result.next }.to raise_error(StopIteration)
    end

    it 'is limited to 1000 iterations in case there are infinite match lengths' do
      expect(ML.of(/a*/).first(3000).size).to eq 1000
    end

    it 'scaffolds the Enumerable interface' do
      expect(ML.of(/abc|defg/).count).to eq 2
      expect(ML.of(/(ab)*/).first(5)).to eq [0, 2, 4, 6, 8]
      expect(ML.of(/a{,10}/).any? { |len| len > 20 }).to be false
    end
  end

  describe('#endless_each') do
    it 'returns an Enumerator if called without a block' do
      result = ML.of(/a?/).endless_each
      expect(result).to be_a(Enumerator)
      expect(result.next).to eq 0
      expect(result.next).to eq 1
      expect { result.next }.to raise_error(StopIteration)
    end

    it 'never stops iterating for infinite match lengths' do
      expect(ML.of(/a*/).endless_each.first(3000).size).to eq 3000
    end
  end

  describe('#inspect') do
    it 'is nice' do
      result = RP.parse(/a{2,4}/)[0].match_length
      expect(result.inspect).to eq '#<Regexp::MatchLength<Literal> min=2 max=4>'
    end
  end
end


text:
package com.ekemait.charting.chart.ganttchart.row.item;

import java.util.ArrayList;
import java.util.List;

import com.ekemait.charting.fusion.ganttchart.Milestones;
import com.ekemait.charting.fusion.ganttchart.Tasks;

/**
 * Container class for row items
 *
 * @author kekema
 *
 */
public class Items
{
	private final List<Item> itemChildren = new ArrayList<Item>();

	/**
	 * Add a task item
	 *
	 * @return
	 */
	public Task createTask()
	{
		Task task = new Task();
		itemChildren.add(task);
		return task;
	}

	/**
	 * Add an event item
	 *
	 * @return
	 */
	public Event createEvent()
	{
		Event event = new Event();
		itemChildren.add(event);
		return event;
	}

	/**
	 * Add a milestone item
	 *
	 * @return
	 */
	public Milestone createMilestone()
	{
		Milestone milestone = new Milestone();
		itemChildren.add(milestone);
		return milestone;
	}

	/**
	 * Get first item description which can be used for the row description in
	 * case the row has no description defined.
	 *
	 * @return
	 */
	public String getFirstItemDescription()
	{
		String result = null;
		if (!itemChildren.isEmpty())
		{
			Item item = itemChildren.get(0);
			if (item != null)
			{
				result = item.getDescription();
			}
		}
		return result;
	}

	/**
	 * Add all row items to the given fusion chart
	 *
	 * @param fcGanttChart
	 * @param fcTasks
	 * @param fcMilestones
	 * @param rowNumber
	 */
	public void addToFusionGanttChart(com.ekemait.charting.fusion.ganttchart.GanttChart fcGanttChart, Tasks fcTasks, Milestones fcMilestones, int rowNumber)
	{
		int itemNumber = 0;
		for (Item item : itemChildren)
		{
			itemNumber++;
			item.addToFusionGanttChart(fcGanttChart, fcTasks, fcMilestones, rowNumber, itemNumber);
		}
	}
}

redpajama_set_name: RedPajamaGithub


text:
from copy import deepcopy

import docker

from .errors import BlockadeError
from .net import NetworkState, BlockadeNetwork
from .state import BlockadeStateFactory

class Blockade(object):
    def __init__(self, config, state_factory=None, network=None,
                 docker_client=None):
        self.config = config
        self.state_factory = state_factory or BlockadeStateFactory()
        self.network = network or BlockadeNetwork(config)
        self.docker_client = docker_client or docker.Client()

    def create(self):
        container_state = {}
        for container in self.config.sorted_containers:
            veth_device = self.network.new_veth_device_name()
            container_state[container.name] = {"veth_device": veth_device}

        # generate blockade ID and persist
        state = self.state_factory.initialize(container_state)

        container_descriptions = []
        for container in self.config.sorted_containers:
            veth_device = container_state[container.name]['veth_device']
            container_id = self._start_container(state.blockade_id, container,
                                                 veth_device)
            description = self._get_container_description(
                state, container.name, container_id)
            container_descriptions.append(description)

        return container_descriptions

    def _start_container(self, blockade_id, container, veth_device):
        container_name = docker_container_name(blockade_id, container.name)
        volumes = list(container.volumes.values()) or None
        response = self.docker_client.create_container(
            container.image, command=container.command, name=container_name,
            ports=container.expose_ports, volumes=volumes, hostname=container.name,
            environment=container.environment)
        container_id = response['Id']

        links = dict((docker_container_name(blockade_id, link), alias)
                     for link, alias in container.links.items())

        lxc_conf = deepcopy(container.lxc_conf)
        lxc_conf['lxc.network.veth.pair'] = veth_device
        self.docker_client.start(container_id, lxc_conf=lxc_conf, links=links,
            binds=container.volumes, port_bindings=container.publish_ports)
        return container_id

    def _get_container_description(self, state, name, container_id,
                                   network_state=True, ip_partitions=None):
        try:
            container = self.docker_client.inspect_container(container_id)
        except docker.APIError as e:
            if e.response.status_code == 404:
                return Container(name, container_id, ContainerState.MISSING)
            else:
                raise

        state_dict = container.get('State')
        if state_dict and state_dict.get('Running'):
            container_state = ContainerState.UP
        else:
            container_state = ContainerState.DOWN

        extras = {}
        network = container.get('NetworkSettings')
        ip = None
        if network:
            ip = network.get('IPAddress')
            if ip:
                extras['ip_address'] = ip

        if (network_state and name in state.containers
                and container_state == ContainerState.UP):
            device = state.containers[name]['veth_device']
            extras['veth_device'] = device
            extras['network_state'] = self.network.network_state(device)

            # include partition ID if we were provided a map of them
            if ip_partitions and ip:
                extras['partition'] = ip_partitions.get(ip)
        else:
            extras['network_state'] = NetworkState.UNKNOWN
            extras['veth_device'] = None

        return Container(name, container_id, container_state, **extras)

    def destroy(self, force=False):
        state = self.state_factory.load()

        containers = self._get_docker_containers(state.blockade_id)
        for container in list(containers.values()):
            container_id = container['Id']
            self.docker_client.stop(container_id, timeout=3)
            self.docker_client.remove_container(container_id)

        self.network.restore(state.blockade_id)
        self.state_factory.destroy()

    def _get_docker_containers(self, blockade_id):
        # look for containers prefixed with our blockade ID
        prefix = "/" + blockade_id + "-"
        d = {}
        for container in self.docker_client.containers(all=True):
            for name in container['Names']:
                if name.startswith(prefix):
                    name = name[len(prefix):]
                    d[name] = container
                    break
        return d

    def _get_all_containers(self, state):
        containers = []
        ip_partitions = self.network.get_ip_partitions(state.blockade_id)
        docker_containers = self._get_docker_containers(state.blockade_id)
        for name, container in docker_containers.items():
            containers.append(self._get_container_description(state, name,
                              container['Id'], ip_partitions=ip_partitions))
        return containers

    def status(self):
        state = self.state_factory.load()
        return self._get_all_containers(state)

    def _get_running_containers(self, container_names=None, state=None):
        state = state or self.state_factory.load()
        containers = self._get_all_containers(state)

        running = dict((c.name, c) for c in containers
                       if c.state == ContainerState.UP)
        if container_names is None:
            return list(running.values())

        found = []
        for name in container_names:
            container = running.get(name)
            if not container:
                raise BlockadeError("Container %s is not found or not running"
                                    % (name,))
            found.append(container)
        return found

    def _get_running_container(self, container_name, state=None):
        return self._get_running_containers((container_name,), state)[0]

    def flaky(self, container_names=None, include_all=False):
        if include_all:
            container_names = None
        containers = self._get_running_containers(container_names)
        for container in containers:
            self.network.flaky(container.veth_device)

    def slow(self, container_names=None, include_all=False):
        if include_all:
            container_names = None
        containers = self._get_running_containers(container_names)
        for container in containers:
            self.network.slow(container.veth_device)

    def fast(self, container_names=None, include_all=False):
        if include_all:
            container_names = None
        containers = self._get_running_containers(container_names)
        for container in containers:
            self.network.fast(container.veth_device)

    def partition(self, partitions):
        state = self.state_factory.load()
        containers = self._get_running_containers(state=state)
        container_dict = dict((c.name, c) for c in containers)
        partitions = expand_partitions(list(container_dict.keys()), partitions)

        container_partitions = []
        for partition in partitions:
            container_partitions.append([container_dict[c] for c in partition])

        self.network.partition_containers(state.blockade_id,
                                          container_partitions)

    def join(self):
        state = self.state_factory.load()
        self.network.restore(state.blockade_id)

    def logs(self, container_name):
        container = self._get_running_container(container_name)
        return self.docker_client.logs(container.container_id)

class Container(object):
    ip_address = None
    veth_device = None
    network_state = NetworkState.NORMAL
    partition = None

    def __init__(self, name, container_id, state, **kwargs):
        self.name = name
        self.container_id = container_id
        self.state = state
        for k, v in kwargs.items():
            setattr(self, k, v)

    def to_dict(self):
        return dict(name=self.name, container_id=self.container_id,
                    state=self.state, ip_address=self.ip_address,
                    veth_device=self.veth_device,
                    network_state=self.network_state,
                    partition=self.partition)

class ContainerState(object):
    UP = "UP"
    DOWN = "DOWN"
    MISSING = "MISSING"

def docker_container_name(blockade_id, name):
    return '-'.join((blockade_id, name))

def expand_partitions(containers, partitions):
    """Validate the partitions of containers. If there are any containers
    not in any partition, place them in an new partition.
    """
    all_names = frozenset(containers)
    partitions = [frozenset(p) for p in partitions]

    unknown = set()
    overlap = set()
    union = set()

    for index, partition in enumerate(partitions):
        unknown.update(partition - all_names)
        union.update(partition)

        for other in partitions[index+1:]:
            overlap.update(partition.intersection(other))

    if unknown:
        raise BlockadeError("Partitions have unknown containers: %s" %
                            list(unknown))

    if overlap:
        raise BlockadeError("Partitions have overlapping containers: %s" %
                            list(overlap))

    # put any leftover containers in an implicit partition
    leftover = all_names.difference(union)
    if leftover:
        partitions.append(leftover)

    return partitions


text:
import contextlib
import os
import sys
import unittest
from unittest.mock import patch
from test.support.script_helper import (assert_python_ok, assert_python_failure,
                                        interpreter_requires_environment)
from test import support
try:
    import threading
except ImportError:
    threading = None
try:
    import _testcapi
except ImportError:
    _testcapi = None

try:
    import tracemalloc
except ImportError:
    raise unittest.SkipTest("tracemalloc is required")

EMPTY_STRING_SIZE = sys.getsizeof(b'')

def get_frames(nframe, lineno_delta):
    frames = []
    frame = sys._getframe(1)
    for index in range(nframe):
        code = frame.f_code
        lineno = frame.f_lineno + lineno_delta
        frames.append((code.co_filename, lineno))
        lineno_delta = 0
        frame = frame.f_back
        if frame is None:
            break
    return tuple(frames)

def allocate_bytes(size):
    nframe = tracemalloc.get_traceback_limit()
    bytes_len = (size - EMPTY_STRING_SIZE)
    frames = get_frames(nframe, 1)
    data = b'x' * bytes_len
    return data, tracemalloc.Traceback(frames)

def create_snapshots():
    traceback_limit = 2

    # _tracemalloc._get_traces() returns a list of (domain, size,
    # traceback_frames) tuples. traceback_frames is a tuple of (filename,
    # line_number) tuples.
    raw_traces = [
        (0, 10, (('a.py', 2), ('b.py', 4))),
        (0, 10, (('a.py', 2), ('b.py', 4))),
        (0, 10, (('a.py', 2), ('b.py', 4))),

        (1, 2, (('a.py', 5), ('b.py', 4))),

        (2, 66, (('b.py', 1),)),

        (3, 7, (('<unknown>', 0),)),
    ]
    snapshot = tracemalloc.Snapshot(raw_traces, traceback_limit)

    raw_traces2 = [
        (0, 10, (('a.py', 2), ('b.py', 4))),
        (0, 10, (('a.py', 2), ('b.py', 4))),
        (0, 10, (('a.py', 2), ('b.py', 4))),

        (2, 2, (('a.py', 5), ('b.py', 4))),
        (2, 5000, (('a.py', 5), ('b.py', 4))),

        (4, 400, (('c.py', 578),)),
    ]
    snapshot2 = tracemalloc.Snapshot(raw_traces2, traceback_limit)

    return (snapshot, snapshot2)

def frame(filename, lineno):
    return tracemalloc._Frame((filename, lineno))

def traceback(*frames):
    return tracemalloc.Traceback(frames)

def traceback_lineno(filename, lineno):
    return traceback((filename, lineno))

def traceback_filename(filename):
    return traceback_lineno(filename, 0)

class TestTracemallocEnabled(unittest.TestCase):
    def setUp(self):
        if tracemalloc.is_tracing():
            self.skipTest("tracemalloc must be stopped before the test")

        tracemalloc.start(1)

    def tearDown(self):
        tracemalloc.stop()

    def test_get_tracemalloc_memory(self):
        data = [allocate_bytes(123) for count in range(1000)]
        size = tracemalloc.get_tracemalloc_memory()
        self.assertGreaterEqual(size, 0)

        tracemalloc.clear_traces()
        size2 = tracemalloc.get_tracemalloc_memory()
        self.assertGreaterEqual(size2, 0)
        self.assertLessEqual(size2, size)

    def test_get_object_traceback(self):
        tracemalloc.clear_traces()
        obj_size = 12345
        obj, obj_traceback = allocate_bytes(obj_size)
        traceback = tracemalloc.get_object_traceback(obj)
        self.assertEqual(traceback, obj_traceback)

    def test_set_traceback_limit(self):
        obj_size = 10

        tracemalloc.stop()
        self.assertRaises(ValueError, tracemalloc.start, -1)

        tracemalloc.stop()
        tracemalloc.start(10)
        obj2, obj2_traceback = allocate_bytes(obj_size)
        traceback = tracemalloc.get_object_traceback(obj2)
        self.assertEqual(len(traceback), 10)
        self.assertEqual(traceback, obj2_traceback)

        tracemalloc.stop()
        tracemalloc.start(1)
        obj, obj_traceback = allocate_bytes(obj_size)
        traceback = tracemalloc.get_object_traceback(obj)
        self.assertEqual(len(traceback), 1)
        self.assertEqual(traceback, obj_traceback)

    def find_trace(self, traces, traceback):
        for trace in traces:
            if trace[2] == traceback._frames:
                return trace

        self.fail("trace not found")

    def test_get_traces(self):
        tracemalloc.clear_traces()
        obj_size = 12345
        obj, obj_traceback = allocate_bytes(obj_size)

        traces = tracemalloc._get_traces()
        trace = self.find_trace(traces, obj_traceback)

        self.assertIsInstance(trace, tuple)
        domain, size, traceback = trace
        self.assertEqual(size, obj_size)
        self.assertEqual(traceback, obj_traceback._frames)

        tracemalloc.stop()
        self.assertEqual(tracemalloc._get_traces(), [])

    def test_get_traces_intern_traceback(self):
        # dummy wrappers to get more useful and identical frames in the traceback
        def allocate_bytes2(size):
            return allocate_bytes(size)
        def allocate_bytes3(size):
            return allocate_bytes2(size)
        def allocate_bytes4(size):
            return allocate_bytes3(size)

        # Ensure that two identical tracebacks are not duplicated
        tracemalloc.stop()
        tracemalloc.start(4)
        obj_size = 123
        obj1, obj1_traceback = allocate_bytes4(obj_size)
        obj2, obj2_traceback = allocate_bytes4(obj_size)

        traces = tracemalloc._get_traces()

        trace1 = self.find_trace(traces, obj1_traceback)
        trace2 = self.find_trace(traces, obj2_traceback)
        domain1, size1, traceback1 = trace1
        domain2, size2, traceback2 = trace2
        self.assertIs(traceback2, traceback1)

    def test_get_traced_memory(self):
        # Python allocates some internals objects, so the test must tolerate
        # a small difference between the expected size and the real usage
        max_error = 2048

        # allocate one object
        obj_size = 1024 * 1024
        tracemalloc.clear_traces()
        obj, obj_traceback = allocate_bytes(obj_size)
        size, peak_size = tracemalloc.get_traced_memory()
        self.assertGreaterEqual(size, obj_size)
        self.assertGreaterEqual(peak_size, size)

        self.assertLessEqual(size - obj_size, max_error)
        self.assertLessEqual(peak_size - size, max_error)

        # destroy the object
        obj = None
        size2, peak_size2 = tracemalloc.get_traced_memory()
        self.assertLess(size2, size)
        self.assertGreaterEqual(size - size2, obj_size - max_error)
        self.assertGreaterEqual(peak_size2, peak_size)

        # clear_traces() must reset traced memory counters
        tracemalloc.clear_traces()
        self.assertEqual(tracemalloc.get_traced_memory(), (0, 0))

        # allocate another object
        obj, obj_traceback = allocate_bytes(obj_size)
        size, peak_size = tracemalloc.get_traced_memory()
        self.assertGreaterEqual(size, obj_size)

        # stop() also resets traced memory counters
        tracemalloc.stop()
        self.assertEqual(tracemalloc.get_traced_memory(), (0, 0))

    def test_clear_traces(self):
        obj, obj_traceback = allocate_bytes(123)
        traceback = tracemalloc.get_object_traceback(obj)
        self.assertIsNotNone(traceback)

        tracemalloc.clear_traces()
        traceback2 = tracemalloc.get_object_traceback(obj)
        self.assertIsNone(traceback2)

    def test_is_tracing(self):
        tracemalloc.stop()
        self.assertFalse(tracemalloc.is_tracing())

        tracemalloc.start()
        self.assertTrue(tracemalloc.is_tracing())

    def test_snapshot(self):
        obj, source = allocate_bytes(123)

        # take a snapshot
        snapshot = tracemalloc.take_snapshot()

        # write on disk
        snapshot.dump(support.TESTFN)
        self.addCleanup(support.unlink, support.TESTFN)

        # load from disk
        snapshot2 = tracemalloc.Snapshot.load(support.TESTFN)
        self.assertEqual(snapshot2.traces, snapshot.traces)

        # tracemalloc must be tracing memory allocations to take a snapshot
        tracemalloc.stop()
        with self.assertRaises(RuntimeError) as cm:
            tracemalloc.take_snapshot()
        self.assertEqual(str(cm.exception),
                         "the tracemalloc module must be tracing memory "
                         "allocations to take a snapshot")

    def test_snapshot_save_attr(self):
        # take a snapshot with a new attribute
        snapshot = tracemalloc.take_snapshot()
        snapshot.test_attr = "new"
        snapshot.dump(support.TESTFN)
        self.addCleanup(support.unlink, support.TESTFN)

        # load() should recreate the attribute
        snapshot2 = tracemalloc.Snapshot.load(support.TESTFN)
        self.assertEqual(snapshot2.test_attr, "new")

    def fork_child(self):
        if not tracemalloc.is_tracing():
            return 2

        obj_size = 12345
        obj, obj_traceback = allocate_bytes(obj_size)
        traceback = tracemalloc.get_object_traceback(obj)
        if traceback is None:
            return 3

        # everything is fine
        return 0

    @unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork()')
    def test_fork(self):
        # check that tracemalloc is still working after fork
        pid = os.fork()
        if not pid:
            # child
            exitcode = 1
            try:
                exitcode = self.fork_child()
            finally:
                os._exit(exitcode)
        else:
            pid2, status = os.waitpid(pid, 0)
            self.assertTrue(os.WIFEXITED(status))
            exitcode = os.WEXITSTATUS(status)
            self.assertEqual(exitcode, 0)

class TestSnapshot(unittest.TestCase):
    maxDiff = 4000

    def test_create_snapshot(self):
        raw_traces = [(0, 5, (('a.py', 2),))]

        with contextlib.ExitStack() as stack:
            stack.enter_context(patch.object(tracemalloc, 'is_tracing',
                                             return_value=True))
            stack.enter_context(patch.object(tracemalloc, 'get_traceback_limit',
                                             return_value=5))
            stack.enter_context(patch.object(tracemalloc, '_get_traces',
                                             return_value=raw_traces))

            snapshot = tracemalloc.take_snapshot()
            self.assertEqual(snapshot.traceback_limit, 5)
            self.assertEqual(len(snapshot.traces), 1)
            trace = snapshot.traces[0]
            self.assertEqual(trace.size, 5)
            self.assertEqual(len(trace.traceback), 1)
            self.assertEqual(trace.traceback[0].filename, 'a.py')
            self.assertEqual(trace.traceback[0].lineno, 2)

    def test_filter_traces(self):
        snapshot, snapshot2 = create_snapshots()
        filter1 = tracemalloc.Filter(False, "b.py")
        filter2 = tracemalloc.Filter(True, "a.py", 2)
        filter3 = tracemalloc.Filter(True, "a.py", 5)

        original_traces = list(snapshot.traces._traces)

        # exclude b.py
        snapshot3 = snapshot.filter_traces((filter1,))
        self.assertEqual(snapshot3.traces._traces, [
            (0, 10, (('a.py', 2), ('b.py', 4))),
            (0, 10, (('a.py', 2), ('b.py', 4))),
            (0, 10, (('a.py', 2), ('b.py', 4))),
            (1, 2, (('a.py', 5), ('b.py', 4))),
            (3, 7, (('<unknown>', 0),)),
        ])

        # filter_traces() must not touch the original snapshot
        self.assertEqual(snapshot.traces._traces, original_traces)

        # only include two lines of a.py
        snapshot4 = snapshot3.filter_traces((filter2, filter3))
        self.assertEqual(snapshot4.traces._traces, [
            (0, 10, (('a.py', 2), ('b.py', 4))),
            (0, 10, (('a.py', 2), ('b.py', 4))),
            (0, 10, (('a.py', 2), ('b.py', 4))),
            (1, 2, (('a.py', 5), ('b.py', 4))),
        ])

        # No filter: just duplicate the snapshot
        snapshot5 = snapshot.filter_traces(())
        self.assertIsNot(snapshot5, snapshot)
        self.assertIsNot(snapshot5.traces, snapshot.traces)
        self.assertEqual(snapshot5.traces, snapshot.traces)

        self.assertRaises(TypeError, snapshot.filter_traces, filter1)

    def test_filter_traces_domain(self):
        snapshot, snapshot2 = create_snapshots()
        filter1 = tracemalloc.Filter(False, "a.py", domain=1)
        filter2 = tracemalloc.Filter(True, "a.py", domain=1)

        original_traces = list(snapshot.traces._traces)

        # exclude a.py of domain 1
        snapshot3 = snapshot.filter_traces((filter1,))
        self.assertEqual(snapshot3.traces._traces, [
            (0, 10, (('a.py', 2), ('b.py', 4))),
            (0, 10, (('a.py', 2), ('b.py', 4))),
            (0, 10, (('a.py', 2), ('b.py', 4))),
            (2, 66, (('b.py', 1),)),
            (3, 7, (('<unknown>', 0),)),
        ])

        # include domain 1
        snapshot3 = snapshot.filter_traces((filter1,))
        self.assertEqual(snapshot3.traces._traces, [
            (0, 10, (('a.py', 2), ('b.py', 4))),
            (0, 10, (('a.py', 2), ('b.py', 4))),
            (0, 10, (('a.py', 2), ('b.py', 4))),
            (2, 66, (('b.py', 1),)),
            (3, 7, (('<unknown>', 0),)),
        ])

    def test_filter_traces_domain_filter(self):
        snapshot, snapshot2 = create_snapshots()
        filter1 = tracemalloc.DomainFilter(False, domain=3)
        filter2 = tracemalloc.DomainFilter(True, domain=3)

        # exclude domain 2
        snapshot3 = snapshot.filter_traces((filter1,))
        self.assertEqual(snapshot3.traces._traces, [
            (0, 10, (('a.py', 2), ('b.py', 4))),
            (0, 10, (('a.py', 2), ('b.py', 4))),
            (0, 10, (('a.py', 2), ('b.py', 4))),
            (1, 2, (('a.py', 5), ('b.py', 4))),
            (2, 66, (('b.py', 1),)),
        ])

        # include domain 2
        snapshot3 = snapshot.filter_traces((filter2,))
        self.assertEqual(snapshot3.traces._traces, [
            (3, 7, (('<unknown>', 0),)),
        ])

    def test_snapshot_group_by_line(self):
        snapshot, snapshot2 = create_snapshots()
        tb_0 = traceback_lineno('<unknown>', 0)
        tb_a_2 = traceback_lineno('a.py', 2)
        tb_a_5 = traceback_lineno('a.py', 5)
        tb_b_1 = traceback_lineno('b.py', 1)
        tb_c_578 = traceback_lineno('c.py', 578)

        # stats per file and line
        stats1 = snapshot.statistics('lineno')
        self.assertEqual(stats1, [
            tracemalloc.Statistic(tb_b_1, 66, 1),
            tracemalloc.Statistic(tb_a_2, 30, 3),
            tracemalloc.Statistic(tb_0, 7, 1),
            tracemalloc.Statistic(tb_a_5, 2, 1),
        ])

        # stats per file and line (2)
        stats2 = snapshot2.statistics('lineno')
        self.assertEqual(stats2, [
            tracemalloc.Statistic(tb_a_5, 5002, 2),
            tracemalloc.Statistic(tb_c_578, 400, 1),
            tracemalloc.Statistic(tb_a_2, 30, 3),
        ])

        # stats diff per file and line
        statistics = snapshot2.compare_to(snapshot, 'lineno')
        self.assertEqual(statistics, [
            tracemalloc.StatisticDiff(tb_a_5, 5002, 5000, 2, 1),
            tracemalloc.StatisticDiff(tb_c_578, 400, 400, 1, 1),
            tracemalloc.StatisticDiff(tb_b_1, 0, -66, 0, -1),
            tracemalloc.StatisticDiff(tb_0, 0, -7, 0, -1),
            tracemalloc.StatisticDiff(tb_a_2, 30, 0, 3, 0),
        ])

    def test_snapshot_group_by_file(self):
        snapshot, snapshot2 = create_snapshots()
        tb_0 = traceback_filename('<unknown>')
        tb_a = traceback_filename('a.py')
        tb_b = traceback_filename('b.py')
        tb_c = traceback_filename('c.py')

        # stats per file
        stats1 = snapshot.statistics('filename')
        self.assertEqual(stats1, [
            tracemalloc.Statistic(tb_b, 66, 1),
            tracemalloc.Statistic(tb_a, 32, 4),
            tracemalloc.Statistic(tb_0, 7, 1),
        ])

        # stats per file (2)
        stats2 = snapshot2.statistics('filename')
        self.assertEqual(stats2, [
            tracemalloc.Statistic(tb_a, 5032, 5),
            tracemalloc.Statistic(tb_c, 400, 1),
        ])

        # stats diff per file
        diff = snapshot2.compare_to(snapshot, 'filename')
        self.assertEqual(diff, [
            tracemalloc.StatisticDiff(tb_a, 5032, 5000, 5, 1),
            tracemalloc.StatisticDiff(tb_c, 400, 400, 1, 1),
            tracemalloc.StatisticDiff(tb_b, 0, -66, 0, -1),
            tracemalloc.StatisticDiff(tb_0, 0, -7, 0, -1),
        ])

    def test_snapshot_group_by_traceback(self):
        snapshot, snapshot2 = create_snapshots()

        # stats per file
        tb1 = traceback(('a.py', 2), ('b.py', 4))
        tb2 = traceback(('a.py', 5), ('b.py', 4))
        tb3 = traceback(('b.py', 1))
        tb4 = traceback(('<unknown>', 0))
        stats1 = snapshot.statistics('traceback')
        self.assertEqual(stats1, [
            tracemalloc.Statistic(tb3, 66, 1),
            tracemalloc.Statistic(tb1, 30, 3),
            tracemalloc.Statistic(tb4, 7, 1),
            tracemalloc.Statistic(tb2, 2, 1),
        ])

        # stats per file (2)
        tb5 = traceback(('c.py', 578))
        stats2 = snapshot2.statistics('traceback')
        self.assertEqual(stats2, [
            tracemalloc.Statistic(tb2, 5002, 2),
            tracemalloc.Statistic(tb5, 400, 1),
            tracemalloc.Statistic(tb1, 30, 3),
        ])

        # stats diff per file
        diff = snapshot2.compare_to(snapshot, 'traceback')
        self.assertEqual(diff, [
            tracemalloc.StatisticDiff(tb2, 5002, 5000, 2, 1),
            tracemalloc.StatisticDiff(tb5, 400, 400, 1, 1),
            tracemalloc.StatisticDiff(tb3, 0, -66, 0, -1),
            tracemalloc.StatisticDiff(tb4, 0, -7, 0, -1),
            tracemalloc.StatisticDiff(tb1, 30, 0, 3, 0),
        ])

        self.assertRaises(ValueError,
                          snapshot.statistics, 'traceback', cumulative=True)

    def test_snapshot_group_by_cumulative(self):
        snapshot, snapshot2 = create_snapshots()
        tb_0 = traceback_filename('<unknown>')
        tb_a = traceback_filename('a.py')
        tb_b = traceback_filename('b.py')
        tb_a_2 = traceback_lineno('a.py', 2)
        tb_a_5 = traceback_lineno('a.py', 5)
        tb_b_1 = traceback_lineno('b.py', 1)
        tb_b_4 = traceback_lineno('b.py', 4)

        # per file
        stats = snapshot.statistics('filename', True)
        self.assertEqual(stats, [
            tracemalloc.Statistic(tb_b, 98, 5),
            tracemalloc.Statistic(tb_a, 32, 4),
            tracemalloc.Statistic(tb_0, 7, 1),
        ])

        # per line
        stats = snapshot.statistics('lineno', True)
        self.assertEqual(stats, [
            tracemalloc.Statistic(tb_b_1, 66, 1),
            tracemalloc.Statistic(tb_b_4, 32, 4),
            tracemalloc.Statistic(tb_a_2, 30, 3),
            tracemalloc.Statistic(tb_0, 7, 1),
            tracemalloc.Statistic(tb_a_5, 2, 1),
        ])

    def test_trace_format(self):
        snapshot, snapshot2 = create_snapshots()
        trace = snapshot.traces[0]
        self.assertEqual(str(trace), 'a.py:2: 10 B')
        traceback = trace.traceback
        self.assertEqual(str(traceback), 'a.py:2')
        frame = traceback[0]
        self.assertEqual(str(frame), 'a.py:2')

    def test_statistic_format(self):
        snapshot, snapshot2 = create_snapshots()
        stats = snapshot.statistics('lineno')
        stat = stats[0]
        self.assertEqual(str(stat),
                         'b.py:1: size=66 B, count=1, average=66 B')

    def test_statistic_diff_format(self):
        snapshot, snapshot2 = create_snapshots()
        stats = snapshot2.compare_to(snapshot, 'lineno')
        stat = stats[0]
        self.assertEqual(str(stat),
                         'a.py:5: size=5002 B (+5000 B), count=2 (+1), average=2501 B')

    def test_slices(self):
        snapshot, snapshot2 = create_snapshots()
        self.assertEqual(snapshot.traces[:2],
                         (snapshot.traces[0], snapshot.traces[1]))

        traceback = snapshot.traces[0].traceback
        self.assertEqual(traceback[:2],
                         (traceback[0], traceback[1]))

    def test_format_traceback(self):
        snapshot, snapshot2 = create_snapshots()
        def getline(filename, lineno):
            return '  <%s, %s>' % (filename, lineno)
        with unittest.mock.patch('tracemalloc.linecache.getline',
                                 side_effect=getline):
            tb = snapshot.traces[0].traceback
            self.assertEqual(tb.format(),
                             ['  File "a.py", line 2',
                              '    <a.py, 2>',
                              '  File "b.py", line 4',
                              '    <b.py, 4>'])

            self.assertEqual(tb.format(limit=1),
                             ['  File "a.py", line 2',
                              '    <a.py, 2>'])

            self.assertEqual(tb.format(limit=-1),
                             [])

class TestFilters(unittest.TestCase):
    maxDiff = 2048

    def test_filter_attributes(self):
        # test default values
        f = tracemalloc.Filter(True, "abc")
        self.assertEqual(f.inclusive, True)
        self.assertEqual(f.filename_pattern, "abc")
        self.assertIsNone(f.lineno)
        self.assertEqual(f.all_frames, False)

        # test custom values
        f = tracemalloc.Filter(False, "test.py", 123, True)
        self.assertEqual(f.inclusive, False)
        self.assertEqual(f.filename_pattern, "test.py")
        self.assertEqual(f.lineno, 123)
        self.assertEqual(f.all_frames, True)

        # parameters passed by keyword
        f = tracemalloc.Filter(inclusive=False, filename_pattern="test.py", lineno=123, all_frames=True)
        self.assertEqual(f.inclusive, False)
        self.assertEqual(f.filename_pattern, "test.py")
        self.assertEqual(f.lineno, 123)
        self.assertEqual(f.all_frames, True)

        # read-only attribute
        self.assertRaises(AttributeError, setattr, f, "filename_pattern", "abc")

    def test_filter_match(self):
        # filter without line number
        f = tracemalloc.Filter(True, "abc")
        self.assertTrue(f._match_frame("abc", 0))
        self.assertTrue(f._match_frame("abc", 5))
        self.assertTrue(f._match_frame("abc", 10))
        self.assertFalse(f._match_frame("12356", 0))
        self.assertFalse(f._match_frame("12356", 5))
        self.assertFalse(f._match_frame("12356", 10))

        f = tracemalloc.Filter(False, "abc")
        self.assertFalse(f._match_frame("abc", 0))
        self.assertFalse(f._match_frame("abc", 5))
        self.assertFalse(f._match_frame("abc", 10))
        self.assertTrue(f._match_frame("12356", 0))
        self.assertTrue(f._match_frame("12356", 5))
        self.assertTrue(f._match_frame("12356", 10))

        # filter with line number > 0
        f = tracemalloc.Filter(True, "abc", 5)
        self.assertFalse(f._match_frame("abc", 0))
        self.assertTrue(f._match_frame("abc", 5))
        self.assertFalse(f._match_frame("abc", 10))
        self.assertFalse(f._match_frame("12356", 0))
        self.assertFalse(f._match_frame("12356", 5))
        self.assertFalse(f._match_frame("12356", 10))

        f = tracemalloc.Filter(False, "abc", 5)
        self.assertTrue(f._match_frame("abc", 0))
        self.assertFalse(f._match_frame("abc", 5))
        self.assertTrue(f._match_frame("abc", 10))
        self.assertTrue(f._match_frame("12356", 0))
        self.assertTrue(f._match_frame("12356", 5))
        self.assertTrue(f._match_frame("12356", 10))

        # filter with line number 0
        f = tracemalloc.Filter(True, "abc", 0)
        self.assertTrue(f._match_frame("abc", 0))
        self.assertFalse(f._match_frame("abc", 5))
        self.assertFalse(f._match_frame("abc", 10))
        self.assertFalse(f._match_frame("12356", 0))
        self.assertFalse(f._match_frame("12356", 5))
        self.assertFalse(f._match_frame("12356", 10))

        f = tracemalloc.Filter(False, "abc", 0)
        self.assertFalse(f._match_frame("abc", 0))
        self.assertTrue(f._match_frame("abc", 5))
        self.assertTrue(f._match_frame("abc", 10))
        self.assertTrue(f._match_frame("12356", 0))
        self.assertTrue(f._match_frame("12356", 5))
        self.assertTrue(f._match_frame("12356", 10))

    def test_filter_match_filename(self):
        def fnmatch(inclusive, filename, pattern):
            f = tracemalloc.Filter(inclusive, pattern)
            return f._match_frame(filename, 0)

        self.assertTrue(fnmatch(True, "abc", "abc"))
        self.assertFalse(fnmatch(True, "12356", "abc"))
        self.assertFalse(fnmatch(True, "<unknown>", "abc"))

        self.assertFalse(fnmatch(False, "abc", "abc"))
        self.assertTrue(fnmatch(False, "12356", "abc"))
        self.assertTrue(fnmatch(False, "<unknown>", "abc"))

    def test_filter_match_filename_joker(self):
        def fnmatch(filename, pattern):
            filter = tracemalloc.Filter(True, pattern)
            return filter._match_frame(filename, 0)

        # empty string
        self.assertFalse(fnmatch('abc', ''))
        self.assertFalse(fnmatch('', 'abc'))
        self.assertTrue(fnmatch('', ''))
        self.assertTrue(fnmatch('', '*'))

        # no *
        self.assertTrue(fnmatch('abc', 'abc'))
        self.assertFalse(fnmatch('abc', 'abcd'))
        self.assertFalse(fnmatch('abc', 'def'))

        # a*
        self.assertTrue(fnmatch('abc', 'a*'))
        self.assertTrue(fnmatch('abc', 'abc*'))
        self.assertFalse(fnmatch('abc', 'b*'))
        self.assertFalse(fnmatch('abc', 'abcd*'))

        # a*b
        self.assertTrue(fnmatch('abc', 'a*c'))
        self.assertTrue(fnmatch('abcdcx', 'a*cx'))
        self.assertFalse(fnmatch('abb', 'a*c'))
        self.assertFalse(fnmatch('abcdce', 'a*cx'))

        # a*b*c
        self.assertTrue(fnmatch('abcde', 'a*c*e'))
        self.assertTrue(fnmatch('abcbdefeg', 'a*bd*eg'))
        self.assertFalse(fnmatch('abcdd', 'a*c*e'))
        self.assertFalse(fnmatch('abcbdefef', 'a*bd*eg'))

        # replace .pyc suffix with .py
        self.assertTrue(fnmatch('a.pyc', 'a.py'))
        self.assertTrue(fnmatch('a.py', 'a.pyc'))

        if os.name == 'nt':
            # case insensitive
            self.assertTrue(fnmatch('aBC', 'ABc'))
            self.assertTrue(fnmatch('aBcDe', 'Ab*dE'))

            self.assertTrue(fnmatch('a.pyc', 'a.PY'))
            self.assertTrue(fnmatch('a.py', 'a.PYC'))
        else:
            # case sensitive
            self.assertFalse(fnmatch('aBC', 'ABc'))
            self.assertFalse(fnmatch('aBcDe', 'Ab*dE'))

            self.assertFalse(fnmatch('a.pyc', 'a.PY'))
            self.assertFalse(fnmatch('a.py', 'a.PYC'))

        if os.name == 'nt':
            # normalize alternate separator "/" to the standard separator "\"
            self.assertTrue(fnmatch(r'a/b', r'a\b'))
            self.assertTrue(fnmatch(r'a\b', r'a/b'))
            self.assertTrue(fnmatch(r'a/b\c', r'a\b/c'))
            self.assertTrue(fnmatch(r'a/b/c', r'a\b\c'))
        else:
            # there is no alternate separator
            self.assertFalse(fnmatch(r'a/b', r'a\b'))
            self.assertFalse(fnmatch(r'a\b', r'a/b'))
            self.assertFalse(fnmatch(r'a/b\c', r'a\b/c'))
            self.assertFalse(fnmatch(r'a/b/c', r'a\b\c'))

        # as of 3.5, .pyo is no longer munged to .py
        self.assertFalse(fnmatch('a.pyo', 'a.py'))

    def test_filter_match_trace(self):
        t1 = (("a.py", 2), ("b.py", 3))
        t2 = (("b.py", 4), ("b.py", 5))
        t3 = (("c.py", 5), ('<unknown>', 0))
        unknown = (('<unknown>', 0),)

        f = tracemalloc.Filter(True, "b.py", all_frames=True)
        self.assertTrue(f._match_traceback(t1))
        self.assertTrue(f._match_traceback(t2))
        self.assertFalse(f._match_traceback(t3))
        self.assertFalse(f._match_traceback(unknown))

        f = tracemalloc.Filter(True, "b.py", all_frames=False)
        self.assertFalse(f._match_traceback(t1))
        self.assertTrue(f._match_traceback(t2))
        self.assertFalse(f._match_traceback(t3))
        self.assertFalse(f._match_traceback(unknown))

        f = tracemalloc.Filter(False, "b.py", all_frames=True)
        self.assertFalse(f._match_traceback(t1))
        self.assertFalse(f._match_traceback(t2))
        self.assertTrue(f._match_traceback(t3))
        self.assertTrue(f._match_traceback(unknown))

        f = tracemalloc.Filter(False, "b.py", all_frames=False)
        self.assertTrue(f._match_traceback(t1))
        self.assertFalse(f._match_traceback(t2))
        self.assertTrue(f._match_traceback(t3))
        self.assertTrue(f._match_traceback(unknown))

        f = tracemalloc.Filter(False, "<unknown>", all_frames=False)
        self.assertTrue(f._match_traceback(t1))
        self.assertTrue(f._match_traceback(t2))
        self.assertTrue(f._match_traceback(t3))
        self.assertFalse(f._match_traceback(unknown))

        f = tracemalloc.Filter(True, "<unknown>", all_frames=True)
        self.assertFalse(f._match_traceback(t1))
        self.assertFalse(f._match_traceback(t2))
        self.assertTrue(f._match_traceback(t3))
        self.assertTrue(f._match_traceback(unknown))

        f = tracemalloc.Filter(False, "<unknown>", all_frames=True)
        self.assertTrue(f._match_traceback(t1))
        self.assertTrue(f._match_traceback(t2))
        self.assertFalse(f._match_traceback(t3))
        self.assertFalse(f._match_traceback(unknown))

class TestCommandLine(unittest.TestCase):
    def test_env_var_disabled_by_default(self):
        # not tracing by default
        code = 'import tracemalloc; print(tracemalloc.is_tracing())'
        ok, stdout, stderr = assert_python_ok('-c', code)
        stdout = stdout.rstrip()
        self.assertEqual(stdout, b'False')

    @unittest.skipIf(interpreter_requires_environment(),
                     'Cannot run -E tests when PYTHON env vars are required.')
    def test_env_var_ignored_with_E(self):
        """PYTHON* environment variables must be ignored when -E is present."""
        code = 'import tracemalloc; print(tracemalloc.is_tracing())'
        ok, stdout, stderr = assert_python_ok('-E', '-c', code, PYTHONTRACEMALLOC='1')
        stdout = stdout.rstrip()
        self.assertEqual(stdout, b'False')

    def test_env_var_enabled_at_startup(self):
        # tracing at startup
        code = 'import tracemalloc; print(tracemalloc.is_tracing())'
        ok, stdout, stderr = assert_python_ok('-c', code, PYTHONTRACEMALLOC='1')
        stdout = stdout.rstrip()
        self.assertEqual(stdout, b'True')

    def test_env_limit(self):
        # start and set the number of frames
        code = 'import tracemalloc; print(tracemalloc.get_traceback_limit())'
        ok, stdout, stderr = assert_python_ok('-c', code, PYTHONTRACEMALLOC='10')
        stdout = stdout.rstrip()
        self.assertEqual(stdout, b'10')

    def test_env_var_invalid(self):
        for nframe in (-1, 0, 2**30):
            with self.subTest(nframe=nframe):
                with support.SuppressCrashReport():
                    ok, stdout, stderr = assert_python_failure(
                        '-c', 'pass',
                        PYTHONTRACEMALLOC=str(nframe))
                    self.assertIn(b'PYTHONTRACEMALLOC: invalid '
                                  b'number of frames',
                                  stderr)

    def test_sys_xoptions(self):
        for xoptions, nframe in (
            ('tracemalloc', 1),
            ('tracemalloc=1', 1),
            ('tracemalloc=15', 15),
        ):
            with self.subTest(xoptions=xoptions, nframe=nframe):
                code = 'import tracemalloc; print(tracemalloc.get_traceback_limit())'
                ok, stdout, stderr = assert_python_ok('-X', xoptions, '-c', code)
                stdout = stdout.rstrip()
                self.assertEqual(stdout, str(nframe).encode('ascii'))

    def test_sys_xoptions_invalid(self):
        for nframe in (-1, 0, 2**30):
            with self.subTest(nframe=nframe):
                with support.SuppressCrashReport():
                    args = ('-X', 'tracemalloc=%s' % nframe, '-c', 'pass')
                    ok, stdout, stderr = assert_python_failure(*args)
                    self.assertIn(b'-X tracemalloc=NFRAME: invalid '
                                  b'number of frames',
                                  stderr)

    def test_pymem_alloc0(self):
        # Issue #21639: Check that PyMem_Malloc(0) with tracemalloc enabled
        # does not crash.
        code = 'import _testcapi; _testcapi.test_pymem_alloc0(); 1'
        assert_python_ok('-X', 'tracemalloc', '-c', code)

@unittest.skipIf(_testcapi is None, 'need _testcapi')
class TestCAPI(unittest.TestCase):
    maxDiff = 80 * 20

    def setUp(self):
        if tracemalloc.is_tracing():
            self.skipTest("tracemalloc must be stopped before the test")

        self.domain = 5
        self.size = 123
        self.obj = allocate_bytes(self.size)[0]

        # for the type "object", id(obj) is the address of its memory block.
        # This type is not tracked by the garbage collector
        self.ptr = id(self.obj)

    def tearDown(self):
        tracemalloc.stop()

    def get_traceback(self):
        frames = _testcapi.tracemalloc_get_traceback(self.domain, self.ptr)
        if frames is not None:
            return tracemalloc.Traceback(frames)
        else:
            return None

    def track(self, release_gil=False, nframe=1):
        frames = get_frames(nframe, 2)
        _testcapi.tracemalloc_track(self.domain, self.ptr, self.size,
                                    release_gil)
        return frames

    def untrack(self):
        _testcapi.tracemalloc_untrack(self.domain, self.ptr)

    def get_traced_memory(self):
        # Get the traced size in the domain
        snapshot = tracemalloc.take_snapshot()
        domain_filter = tracemalloc.DomainFilter(True, self.domain)
        snapshot = snapshot.filter_traces([domain_filter])
        return sum(trace.size for trace in snapshot.traces)

    def check_track(self, release_gil):
        nframe = 5
        tracemalloc.start(nframe)

        size = tracemalloc.get_traced_memory()[0]

        frames = self.track(release_gil, nframe)
        self.assertEqual(self.get_traceback(),
                         tracemalloc.Traceback(frames))

        self.assertEqual(self.get_traced_memory(), self.size)

    def test_track(self):
        self.check_track(False)

    def test_track_without_gil(self):
        # check that calling _PyTraceMalloc_Track() without holding the GIL
        # works too
        self.check_track(True)

    def test_track_already_tracked(self):
        nframe = 5
        tracemalloc.start(nframe)

        # track a first time
        self.track()

        # calling _PyTraceMalloc_Track() must remove the old trace and add
        # a new trace with the new traceback
        frames = self.track(nframe=nframe)
        self.assertEqual(self.get_traceback(),
                         tracemalloc.Traceback(frames))

    def test_untrack(self):
        tracemalloc.start()

        self.track()
        self.assertIsNotNone(self.get_traceback())
        self.assertEqual(self.get_traced_memory(), self.size)

        # untrack must remove the trace
        self.untrack()
        self.assertIsNone(self.get_traceback())
        self.assertEqual(self.get_traced_memory(), 0)

        # calling _PyTraceMalloc_Untrack() multiple times must not crash
        self.untrack()
        self.untrack()

    def test_stop_track(self):
        tracemalloc.start()
        tracemalloc.stop()

        with self.assertRaises(RuntimeError):
            self.track()
        self.assertIsNone(self.get_traceback())

    def test_stop_untrack(self):
        tracemalloc.start()
        self.track()

        tracemalloc.stop()
        with self.assertRaises(RuntimeError):
            self.untrack()

def test_main():
    support.run_unittest(
        TestTracemallocEnabled,
        TestSnapshot,
        TestFilters,
        TestCommandLine,
        TestCAPI,
    )

if __name__ == "__main__":
    test_main()


text:
package xyz.hyperreal.bvm

import xyz.hyperreal.bvm.VM.{ONE, ZERO}
import xyz.hyperreal.dal.IntType

trait VMType {
  val name: String
  val extending: List[VMType]
  val members: Map[Symbol, VMMember]
}

abstract class VMMember {
  //val clas: VMClass
  val name: String
}

abstract class VMNativeMethod extends VMMember {
  def method: PartialFunction[(VM, VMObject, Any), Any]
}

abstract class VMClass extends VMNonResizableUniqueNonIterableObject with VMType with VMUnordered with VMNonUpdatable with VMNonSet {
  val name: String
  val parent: VMClass

  def canBuild: Boolean = false
  def build(from: Iterator[VMObject]): VMObject = sys.error("can't build from iterator")

  override def toString: String = s"class $name"
}

trait VMBuilder extends VMClass {
  override def canBuild: Boolean = true
}

abstract class VMObject extends Ordered[VMObject] {
  val clas: VMClass
  val outer: Option[VMObject] = None

  def toInt: Int =
    this match {
      case n @ VMNumber(IntType, _) => n.value.intValue
      case _                        => sys.error(s"expected integer: $this")
    }

  def isOrdered: Boolean

  def compare(that: VMObject): Int

  def isPair: Boolean = isInstanceOf[VMSeq] && size == 2

  def toPair: (VMObject, VMObject) = (apply(ZERO), apply(ONE))

  val isIterable: Boolean

  def iterator: Iterator[VMObject]

  def append(elem: VMObject): VMObject

  def concat(iterable: VMObject): VMObject

  def size: Int

  def isEmpty: Boolean = size == 0

  def nonEmpty: Boolean = size > 0

  def head: VMObject

  def tail: VMObject

  val isSequence: Boolean

  def apply(key: VMObject): VMObject

  val isSet: Boolean

  def contains(key: VMObject): Boolean

  val isResizable: Boolean

  def addOne(elem: VMObject): Unit

  def addAll(seq: VMObject): Unit = seq.iterator foreach addOne

  def subtractOne(elem: VMObject): Unit

  def subtractAll(seq: VMObject): Unit = seq.iterator foreach subtractOne

  val isMap: Boolean

  def get(key: VMObject): Option[VMObject]

  val isUpdatable: Boolean

  def update(key: VMObject, value: VMObject): Unit

  def toString: String
}

trait VMNonUpdatable {
  val isUpdatable: Boolean = false

  def update(key: VMObject, value: VMObject): Unit = sys.error(s"immutable: $this")
}

trait VMUnordered {
  def isOrdered: Boolean = false

  def compare(that: VMObject): Int = sys.error(s"unordered: $this")
}

trait VMNonIterable extends VMNonSequence with VMNonMap {
  val isIterable: Boolean = false

  def iterator: Iterator[VMObject] = sys.error("no iterator method")

  def size: Int = sys.error("no size method")

  def append(elem: VMObject): VMObject = sys.error("no append method")

  def concat(iterable: VMObject): VMObject = sys.error("no concat method")
}

trait VMResizableIterableNonSequence extends VMNonSequence with VMNonAppendable {
  val isResizable = true
  val isIterable = true
}

trait VMNonSequence {
  val isSequence: Boolean = false

  def apply(key: VMObject): VMObject = sys.error("no apply method")

  def head: VMObject = sys.error("no head method")

  def tail: VMObject = sys.error("no tail method")
}

trait VMNonMap {
  val isMap: Boolean = false

  def get(key: VMObject): Option[VMObject] = sys.error("no get method")
}

trait VMNonSet {
  val isSet: Boolean = false

  def contains(key: VMObject): Boolean = sys.error("no contains method")
}

abstract class VMNonSequenceObject extends VMObject with VMNonSequence with VMNonResizable

abstract class VMNonIterableObject extends VMObject with VMNonIterable with VMNonResizable

object VMClassClass extends VMClass {
  val name: String = "Class"
  val parent: VMClass = VMObjectClass
  val extending: List[VMType] = List(parent)
  val members: Map[Symbol, VMMember] = Map()
  val clas: VMClass = VMClassClass
}

trait VMNonResizable {
  val isResizable: Boolean = false

  def addOne(elem: VMObject): Unit = sys.error("can't add element")

  def subtractOne(elem: VMObject): Unit = sys.error("can't subtract element")
}

trait VMNonAppendable {
  def append(elem: VMObject): VMObject = sys.error("can't append")

  def concat(iterable: VMObject): VMObject = sys.error("can't concatenate")
}

trait VMNonResizableIterable extends VMObject with VMNonResizable {
  val isIterable: Boolean = true
}

trait VMResizableIterable extends VMObject {
  val isIterable: Boolean = true
  val isResizable: Boolean = true
}

trait VMNonResizableSequence extends VMNonResizableIterable {
  val isSequence: Boolean = true
}

trait VMNonAppendableNonResizableSequence extends VMNonResizableSequence with VMNonAppendable

trait VMNonAppendableNonResizableNonMapSequence extends VMNonAppendableNonResizableSequence with VMNonMap

trait VMResizableSequence extends VMResizableIterable {
  val isSequence: Boolean = true
}

object VMObjectClass extends VMClass {
  val parent: VMClass = null
  val name: String = "Object"
  val extending: List[VMType] = Nil
  val members: Map[Symbol, VMMember] = Map()
  val clas: VMClass = VMClassClass
}

object VMUnitClass extends VMClass {
  val parent: VMClass = VMObjectClass
  val name: String = "Unit"
  val extending: List[VMType] = List(VMObjectClass)
  val members: Map[Symbol, VMMember] = Map()
  val clas: VMClass = VMClassClass
}

object VMVoid extends VMNonResizableUniqueNonIterableObject {
  val clas: VMClass = VMUnitClass

  override def toString: String = "()"
}

abstract class VMNonResizableUniqueNonIterableObject
    extends VMObject
    with VMNonIterable
    with VMNonResizable
    with VMUnordered
    with VMNonUpdatable
    with VMNonSet

object VMUndefinedClass extends VMClass {
  val parent: VMClass = VMObjectClass
  val name: String = "Undefined"
  val extending: List[VMType] = List(VMObjectClass)
  val members: Map[Symbol, VMMember] = Map()
  val clas: VMClass = VMClassClass
}

object VMUndefined extends VMNonResizableUniqueNonIterableObject {
  val clas: VMClass = VMUndefinedClass

  override def toString: String = "undefined"
}

object VMNullClass extends VMClass {
  val parent: VMClass = VMObjectClass
  val name: String = "Undefined"
  val extending: List[VMType] = List(VMObjectClass)
  val members: Map[Symbol, VMMember] = Map()
  val clas: VMClass = VMClassClass
}

object VMNull extends VMNonResizableUniqueNonIterableObject {
  val clas: VMClass = VMNullClass

  override def toString: String = "null"
}

object VMBooleanClass extends VMClass {
  val parent: VMClass = VMObjectClass
  val name: String = "Boolean"
  val extending: List[VMType] = List(VMObjectClass)
  val members: Map[Symbol, VMMember] = Map()
  val clas: VMClass = VMClassClass
}

trait VMBoolean {
  val b: Boolean

  override def hashCode(): Int = b.hashCode

  override def equals(obj: Any): Boolean = b == obj
}

object VMTrue extends VMNonResizableUniqueNonIterableObject with VMBoolean {
  val clas: VMClass = VMBooleanClass
  val b: Boolean = true

  override def toString: String = "true"
}

object VMFalse extends VMNonResizableUniqueNonIterableObject with VMBoolean {
  val clas: VMClass = VMBooleanClass
  val b: Boolean = false

  override def toString: String = "false"
}

object VMBoolean {
  def apply(b: Boolean): VMObject = if (b) VMTrue else VMFalse
}


text:
module Dominusrb
  module DiscordCommands
    module Debug
      extend Discordrb::Commands::CommandContainer

      # default "false"
      debug = false

      command :debug , description: 'swap debug mode' do |event|
        unless event.user.id == BOT.bot_app.owner.id
          event.respond 'You are not Bot Owner'
          break
        end

        if debug
          BOT.debug '-------- debug mode OFF --------'
          BOT.mode=:normal
          debug = false
          event.respond "`debug mode` **OFF**"
        else
          BOT.mode=:debug
          BOT.debug '-------- debug mode ON --------'
          debug = true
          event.respond "`debug mode` **ON**"
        end
      end
    end
  end
end


text:
//
//  NSObject+MJKeyValue.m
//  MJExtension
//
//  Created by mj on 13-8-24.
//  Copyright (c) 2013年 小码哥. All rights reserved.
//

#import "NSObject+MJKeyValue.h"
#import "NSObject+MJProperty.h"
#import "NSString+MJExtension.h"
#import "MJProperty.h"
#import "MJPropertyType.h"
#import "MJExtensionConst.h"
#import "MJFoundation.h"
#import "NSString+MJExtension.h"
#import "NSObject+MJClass.h"

@implementation NSObject (MJKeyValue)

#pragma mark - 模型 -> 字典时的参考
/** 模型转字典时,字典的key是否参考replacedKeyFromPropertyName等方法(父类设置了,子类也会继承下来) */
static const char MJReferenceReplacedKeyWhenCreatingKeyValuesKey = '\0';

+ (void)referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference
{
    objc_setAssociatedObject(self, &MJReferenceReplacedKeyWhenCreatingKeyValuesKey, @(reference), OBJC_ASSOCIATION_ASSIGN);
}

+ (BOOL)isReferenceReplacedKeyWhenCreatingKeyValues
{
    __block id value = objc_getAssociatedObject(self, &MJReferenceReplacedKeyWhenCreatingKeyValuesKey);
    if (!value) {
        [self enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) {
            value = objc_getAssociatedObject(c, &MJReferenceReplacedKeyWhenCreatingKeyValuesKey);

            if (value) *stop = YES;
        }];
    }
    return [value boolValue];
}

#pragma mark - --常用的对象--
static NSNumberFormatter *_numberFormatter;
+ (void)load
{
    _numberFormatter = [[NSNumberFormatter alloc] init];
}

#pragma mark - --公共方法--
#pragma mark - 字典 -> 模型
- (instancetype)setKeyValues:(id)keyValues
{
    return [self setKeyValues:keyValues error:nil];
}

- (instancetype)setKeyValues:(id)keyValues error:(NSError *__autoreleasing *)error
{
    return [self setKeyValues:keyValues context:nil error:error];
}

- (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context
{
    return [self setKeyValues:keyValues context:context error:nil];
}

/**
 核心代码:
 */
- (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError *__autoreleasing *)error
{
    // 获得JSON对象
    keyValues = [keyValues JSONObject];

    MJExtensionAssertError([keyValues isKindOfClass:[NSDictionary class]], self, error, @"keyValues参数不是一个字典");

    @try {
        Class aClass = [self class];
        NSArray *allowedPropertyNames = [aClass totalAllowedPropertyNames];
        NSArray *ignoredPropertyNames = [aClass totalIgnoredPropertyNames];

        //通过封装的方法回调一个通过运行时编写的,用于返回属性列表的方法。
        [aClass enumerateProperties:^(MJProperty *property, BOOL *stop) {
            // 0.检测是否被忽略
            if (allowedPropertyNames.count && ![allowedPropertyNames containsObject:property.name]) return;
            if ([ignoredPropertyNames containsObject:property.name]) return;

            // 1.取出属性值
            id value;
            NSArray *propertyKeyses = [property propertyKeysForClass:aClass];
            for (NSArray *propertyKeys in propertyKeyses) {
                value = keyValues;
                for (MJPropertyKey *propertyKey in propertyKeys) {
                    value = [propertyKey valueInObject:value];
                }
                if (value) break;
            }

            // 值的过滤
            id newValue = [aClass getNewValueFromObject:self oldValue:value property:property];
            if (newValue) value = newValue;

            // 如果没有值,就直接返回
            if (!value || value == [NSNull null]) return;

            // 2.如果是模型属性
            MJPropertyType *type = property.type;
            Class typeClass = type.typeClass;
            Class objectClass = [property objectClassInArrayForClass:[self class]];
            if (!type.isFromFoundation && typeClass) {
                value = [typeClass objectWithKeyValues:value context:context error:error];
            } else if (objectClass) {
                // string array -> url array
                if (objectClass == [NSURL class] && [value isKindOfClass:[NSArray class]]) {
                    NSMutableArray *urlArray = [NSMutableArray array];
                    for (NSString *string in value) {
                        if (![string isKindOfClass:[NSString class]]) continue;
                        [urlArray addObject:string.url];
                    }
                    value = urlArray;
                } else {
                    // 3.字典数组-->模型数组
                    value = [objectClass objectArrayWithKeyValuesArray:value context:context error:error];
                }
            } else if (typeClass == [NSString class]) {
                if ([value isKindOfClass:[NSNumber class]]) {
                    // NSNumber -> NSString
                    value = [value description];
                } else if ([value isKindOfClass:[NSURL class]]) {
                    // NSURL -> NSString
                    value = [value absoluteString];
                }
            } else if ([value isKindOfClass:[NSString class]]) {
                if (typeClass == [NSURL class]) {
                    // NSString -> NSURL
                    // 字符串转码
                    value = [value url];
                } else if (type.isNumberType) {
                    NSString *oldValue = value;

                    // NSString -> NSNumber
                    value = [_numberFormatter numberFromString:oldValue];

                    // 如果是BOOL
                    if (type.isBoolType) {
                        // 字符串转BOOL(字符串没有charValue方法)
                        // 系统会调用字符串的charValue转为BOOL类型
                        NSString *lower = [oldValue lowercaseString];
                        if ([lower isEqualToString:@"yes"] || [lower isEqualToString:@"true"]) {
                            value = @YES;
                        } else if ([lower isEqualToString:@"no"] || [lower isEqualToString:@"false"]) {
                            value = @NO;
                        }
                    }
                }
            }

            // 4.赋值
            [property setValue:value forObject:self];
        }];

        // 转换完毕
        if ([self respondsToSelector:@selector(keyValuesDidFinishConvertingToObject)]) {
            [self keyValuesDidFinishConvertingToObject];
        }
    } @catch (NSException *exception) {
        MJExtensionBuildError(error, exception.reason);
        NSLog(@"%@", exception);
    }
    return self;
}

+ (instancetype)objectWithKeyValues:(id)keyValues
{
    return [self objectWithKeyValues:keyValues error:nil];
}

+ (instancetype)objectWithKeyValues:(id)keyValues error:(NSError *__autoreleasing *)error
{
    return [self objectWithKeyValues:keyValues context:nil error:error];
}

+ (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context
{
    return [self objectWithKeyValues:keyValues context:context error:nil];
}

+ (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError *__autoreleasing *)error
{
    if (keyValues == nil) return nil;
    if ([self isSubclassOfClass:[NSManagedObject class]] && context) {
        return [[NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass(self) inManagedObjectContext:context] setKeyValues:keyValues context:context error:error];
    }
    return [[[self alloc] init] setKeyValues:keyValues error:error];
}

+ (instancetype)objectWithFilename:(NSString *)filename
{
    return [self objectWithFilename:filename error:nil];
}

+ (instancetype)objectWithFilename:(NSString *)filename error:(NSError *__autoreleasing *)error
{
    MJExtensionAssertError(filename != nil, nil, error, @"filename参数为nil");

    return [self objectWithFile:[[NSBundle mainBundle] pathForResource:filename ofType:nil] error:error];
}

+ (instancetype)objectWithFile:(NSString *)file
{
    return [self objectWithFile:file error:nil];
}

+ (instancetype)objectWithFile:(NSString *)file error:(NSError *__autoreleasing *)error
{
    MJExtensionAssertError(file != nil, nil, error, @"file参数为nil");

    return [self objectWithKeyValues:[NSDictionary dictionaryWithContentsOfFile:file] error:error];
}

#pragma mark - 字典数组 -> 模型数组
+ (NSMutableArray *)objectArrayWithKeyValuesArray:(NSArray *)keyValuesArray
{
    return [self objectArrayWithKeyValuesArray:keyValuesArray error:nil];
}

+ (NSMutableArray *)objectArrayWithKeyValuesArray:(NSArray *)keyValuesArray error:(NSError *__autoreleasing *)error
{
    return [self objectArrayWithKeyValuesArray:keyValuesArray context:nil error:error];
}

+ (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context
{
    return [self objectArrayWithKeyValuesArray:keyValuesArray context:context error:nil];
}

+ (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context error:(NSError *__autoreleasing *)error
{
    // 如果数组里面放的是NSString、NSNumber等数据
    if ([MJFoundation isClassFromFoundation:self]) return keyValuesArray;

    // 如果是JSON字符串
    keyValuesArray = [keyValuesArray JSONObject];

    // 1.判断真实性
    MJExtensionAssertError([keyValuesArray isKindOfClass:[NSArray class]], nil, error, @"keyValuesArray参数不是一个数组");

    // 2.创建数组
    NSMutableArray *modelArray = [NSMutableArray array];

    // 3.遍历
    for (NSDictionary *keyValues in keyValuesArray) {
        if ([keyValues isKindOfClass:[NSArray class]]){
            [modelArray addObject:[self objectArrayWithKeyValuesArray:keyValues context:context error:error]];
        } else {
            id model = [self objectWithKeyValues:keyValues context:context error:error];
            if (model) [modelArray addObject:model];
        }
    }

    return modelArray;
}

+ (NSMutableArray *)objectArrayWithFilename:(NSString *)filename
{
    return [self objectArrayWithFilename:filename error:nil];
}

+ (NSMutableArray *)objectArrayWithFilename:(NSString *)filename error:(NSError *__autoreleasing *)error
{
    MJExtensionAssertError(filename != nil, nil, error, @"filename参数为nil");

    return [self objectArrayWithFile:[[NSBundle mainBundle] pathForResource:filename ofType:nil] error:error];
}

+ (NSMutableArray *)objectArrayWithFile:(NSString *)file
{
    return [self objectArrayWithFile:file error:nil];
}

+ (NSMutableArray *)objectArrayWithFile:(NSString *)file error:(NSError *__autoreleasing *)error
{
    MJExtensionAssertError(file != nil, nil, error, @"file参数为nil");

    return [self objectArrayWithKeyValuesArray:[NSArray arrayWithContentsOfFile:file] error:error];
}

#pragma mark - 模型 -> 字典
- (NSMutableDictionary *)keyValues
{
    return [self keyValuesWithError:nil];
}

- (NSMutableDictionary *)keyValuesWithError:(NSError *__autoreleasing *)error
{
    return [self keyValuesWithIgnoredKeys:nil error:error];
}

- (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys
{
    return [self keyValuesWithKeys:keys error:nil];
}

- (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys error:(NSError *__autoreleasing *)error
{
    return [self keyValuesWithKeys:keys ignoredKeys:nil error:error];
}

- (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys
{
    return [self keyValuesWithIgnoredKeys:ignoredKeys error:nil];
}

- (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys error:(NSError *__autoreleasing *)error
{
    return [self keyValuesWithKeys:nil ignoredKeys:ignoredKeys error:error];
}

- (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys ignoredKeys:(NSArray *)ignoredKeys error:(NSError *__autoreleasing *)error
{
    // 如果自己不是模型类
    if ([MJFoundation isClassFromFoundation:[self class]]) return (NSMutableDictionary *)self;

    id keyValues = [NSMutableDictionary dictionary];

    @try {
        Class aClass = [self class];
        NSArray *allowedPropertyNames = [aClass totalAllowedPropertyNames];
        NSArray *ignoredPropertyNames = [aClass totalIgnoredPropertyNames];

        [aClass enumerateProperties:^(MJProperty *property, BOOL *stop) {
            // 0.检测是否被忽略
            if (allowedPropertyNames.count && ![allowedPropertyNames containsObject:property.name]) return;
            if ([ignoredPropertyNames containsObject:property.name]) return;
            if (keys.count && ![keys containsObject:property.name]) return;
            if ([ignoredKeys containsObject:property.name]) return;

            // 1.取出属性值
            id value = [property valueForObject:self];
            if (!value) return;

            // 2.如果是模型属性
            MJPropertyType *type = property.type;
            Class typeClass = type.typeClass;
            if (!type.isFromFoundation && typeClass) {
                value = [value keyValues];
            } else if ([value isKindOfClass:[NSArray class]]) {
                // 3.处理数组里面有模型的情况
                value = [NSObject keyValuesArrayWithObjectArray:value];
            } else if (typeClass == [NSURL class]) {
                value = [value absoluteString];
            }

            // 4.赋值
            if ([aClass isReferenceReplacedKeyWhenCreatingKeyValues]) {
                NSArray *propertyKeys = [[property propertyKeysForClass:aClass] firstObject];
                NSUInteger keyCount = propertyKeys.count;
                // 创建字典
                __block id innerContainer = keyValues;
                [propertyKeys enumerateObjectsUsingBlock:^(MJPropertyKey *propertyKey, NSUInteger idx, BOOL *stop) {
                    // 下一个属性
                    MJPropertyKey *nextPropertyKey = nil;
                    if (idx != keyCount - 1) {
                        nextPropertyKey = propertyKeys[idx + 1];
                    }

                    if (nextPropertyKey) { // 不是最后一个key
                        // 当前propertyKey对应的字典或者数组
                        id tempInnerContainer = [propertyKey valueInObject:innerContainer];
                        if (tempInnerContainer == nil || [tempInnerContainer isKindOfClass:[NSNull class]]) {
                            if (nextPropertyKey.type == MJPropertyKeyTypeDictionary) {
                                tempInnerContainer = [NSMutableDictionary dictionary];
                            } else {
                                tempInnerContainer = [NSMutableArray array];
                            }
                            if (propertyKey.type == MJPropertyKeyTypeDictionary) {
                                innerContainer[propertyKey.name] = tempInnerContainer;
                            } else {
                                innerContainer[propertyKey.name.intValue] = tempInnerContainer;
                            }
                        }

                        if ([tempInnerContainer isKindOfClass:[NSMutableArray class]]) {
                            int index = nextPropertyKey.name.intValue;
                            while ([tempInnerContainer count] < index + 1) {
                                [tempInnerContainer addObject:[NSNull null]];
                            }
                        }

                        innerContainer = tempInnerContainer;
                    } else { // 最后一个key
                        if (propertyKey.type == MJPropertyKeyTypeDictionary) {
                            innerContainer[propertyKey.name] = value;
                        } else {
                            innerContainer[propertyKey.name.intValue] = value;
                        }
                    }
                }];
            } else {
                keyValues[property.name] = value;
            }
        }];

        // 去除系统自动增加的元素
        if ([keyValues isKindOfClass:[NSMutableDictionary class]]) {
            [keyValues removeObjectsForKeys:@[@"superclass", @"debugDescription", @"description", @"hash"]];
        }

        // 转换完毕
        if ([self respondsToSelector:@selector(objectDidFinishConvertingToKeyValues)]) {
            [self objectDidFinishConvertingToKeyValues];
        }
    } @catch (NSException *exception) {
        MJExtensionBuildError(error, exception.reason);
        NSLog(@"%@", exception);
    }

    return keyValues;
}
#pragma mark - 模型数组 -> 字典数组
+ (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray
{
    return [self keyValuesArrayWithObjectArray:objectArray error:nil];
}

+ (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray error:(NSError *__autoreleasing *)error
{
    return [self keyValuesArrayWithObjectArray:objectArray ignoredKeys:nil error:error];
}

+ (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys
{
    return [self keyValuesArrayWithObjectArray:objectArray keys:keys error:nil];
}

+ (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys
{
    return [self keyValuesArrayWithObjectArray:objectArray ignoredKeys:ignoredKeys error:nil];
}

+ (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys error:(NSError *__autoreleasing *)error
{
    return [self keyValuesArrayWithObjectArray:objectArray keys:keys ignoredKeys:nil error:error];
}

+ (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys error:(NSError *__autoreleasing *)error
{
    return [self keyValuesArrayWithObjectArray:objectArray keys:nil ignoredKeys:ignoredKeys error:error];
}

+ (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys ignoredKeys:(NSArray *)ignoredKeys error:(NSError *__autoreleasing *)error
{
    // 0.判断真实性
    MJExtensionAssertError([objectArray isKindOfClass:[NSArray class]], nil, error, @"objectArray参数不是一个数组");

    // 1.创建数组
    NSMutableArray *keyValuesArray = [NSMutableArray array];
    for (id object in objectArray) {
        if (keys) {
            [keyValuesArray addObject:[object keyValuesWithKeys:keys error:error]];
        } else {
            [keyValuesArray addObject:[object keyValuesWithIgnoredKeys:ignoredKeys error:error]];
        }
    }
    return keyValuesArray;
}

#pragma mark - 转换为JSON
- (NSData *)JSONData
{
    if ([self isKindOfClass:[NSString class]]) {
        return [((NSString *)self) dataUsingEncoding:NSUTF8StringEncoding];
    } else if ([self isKindOfClass:[NSData class]]) {
        return (NSData *)self;
    }

    return [NSJSONSerialization dataWithJSONObject:[self JSONObject] options:kNilOptions error:nil];
}

- (id)JSONObject
{
    if ([self isKindOfClass:[NSString class]]) {
        return [NSJSONSerialization JSONObjectWithData:[((NSString *)self) dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
    } else if ([self isKindOfClass:[NSData class]]) {
        return [NSJSONSerialization JSONObjectWithData:(NSData *)self options:kNilOptions error:nil];
    }

    return self.keyValues;
}

- (NSString *)JSONString
{
    if ([self isKindOfClass:[NSString class]]) {
        return (NSString *)self;
    } else if ([self isKindOfClass:[NSData class]]) {
        return [[NSString alloc] initWithData:(NSData *)self encoding:NSUTF8StringEncoding];
    }

    return [[NSString alloc] initWithData:[self JSONData] encoding:NSUTF8StringEncoding];
}
@end


text:
void
_malloc_stats_r (struct _reent *ptr)
{
  malloc_stats ();
}


text:
package com.perunlabs.testinjector.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.List;

@SuppressWarnings("serial")
public class MoreThanOneBindingAnnotationException extends RuntimeException {
  public MoreThanOneBindingAnnotationException(Field field, List<Annotation> annotations) {
    super("Field " + field.getName() + " has more than one binding annotation: "
        + annotationList(annotations));
  }

  private static String annotationList(List<Annotation> annotations) {
    StringBuilder builder = new StringBuilder();

    for (int i = 0; i < annotations.size(); i++) {
      if (i != 0) {
        builder.append(", ");
      }
      builder.append("@" + annotations.get(i).annotationType().getSimpleName());
    }
    return builder.toString();
  }
}


text:
// ------------------------------------------------------------------------------
//  <auto-generated>
//      This code was generated by SpecFlow (http://www.specflow.org/).
//      SpecFlow Version:1.9.0.77
//      SpecFlow Generator Version:1.9.0.0
//      Runtime Version:4.0.30319.34003
//
//      Changes to this file may cause incorrect behavior and will be lost if
//      the code is regenerated.
//  </auto-generated>
// ------------------------------------------------------------------------------
#region Designer generated code
#pragma warning disable
namespace Meganium.SystemTests.Features.Importacao
{
    using TechTalk.SpecFlow;

    [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.9.0.77")]
    [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [NUnit.Framework.TestFixtureAttribute()]
    [NUnit.Framework.DescriptionAttribute("Importar Fotos do Facebook")]
    public partial class ImportarFotosDoFacebookFeature
    {

        private static TechTalk.SpecFlow.ITestRunner testRunner;

#line 1 "ImportarFotosDoFacebook.feature"
#line hidden

        [NUnit.Framework.TestFixtureSetUpAttribute()]
        public virtual void FeatureSetup()
        {
            testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner();
            TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("pt-BR"), "Importar Fotos do Facebook", "Como administrador do site\r\nGostaria de importar minhas fotos do Facebook\r\nDe mod" +
                    "o que os usuários finais as visualizem", ProgrammingLanguage.CSharp, ((string[])(null)));
            testRunner.OnFeatureStart(featureInfo);
        }

        [NUnit.Framework.TestFixtureTearDownAttribute()]
        public virtual void FeatureTearDown()
        {
            testRunner.OnFeatureEnd();
            testRunner = null;
        }

        [NUnit.Framework.SetUpAttribute()]
        public virtual void TestInitialize()
        {
        }

        [NUnit.Framework.TearDownAttribute()]
        public virtual void ScenarioTearDown()
        {
            testRunner.OnScenarioEnd();
        }

        public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo)
        {
            testRunner.OnScenarioStart(scenarioInfo);
        }

        public virtual void ScenarioCleanup()
        {
            testRunner.CollectScenarioErrors();
        }

        [NUnit.Framework.TestAttribute()]
        [NUnit.Framework.DescriptionAttribute("Importar Fotos do Facebook com sucesso")]
        public virtual void ImportarFotosDoFacebookComSucesso()
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Importar Fotos do Facebook com sucesso", ((string[])(null)));
#line 7
this.ScenarioSetup(scenarioInfo);
#line 8
 testRunner.Given("que estou logado", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Dado ");
#line 9
 testRunner.When("entro na página \"/Admin/Import\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Quando ");
#line 10
 testRunner.And("seleciono \"Fotos do Facebook\" no campo \"PluginName\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "E ");
#line 11
 testRunner.And("clico no botão \"Avançar\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "E ");
#line 12
 testRunner.And("digito \"megasiteteste@gmail.com\" no campo \"email\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "E ");
#line 13
 testRunner.And("digito \"123mudar*\" no campo \"pass\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "E ");
#line 14
 testRunner.And("clico no botão \"login\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "E ");
#line 15
 testRunner.And("clico no botão \"Importar tudo\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "E ");
#line 16
 testRunner.Then("estou na página \"/Admin/Import\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Então ");
#line 17
 testRunner.And("deu uma mensagem de sucesso", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "E ");
#line hidden
            this.ScenarioCleanup();
        }
    }
}
#pragma warning restore
#endregion


text:
@implementation SBSlingCollisionController

- (void) checkCollisionAgainstBallAndSling {
    kmVec3* headPosition = _slingCollider.position;
    kmVec3* headVelocity = _slingCollider.velocity;

    kmVec3 ballPosition = _ballCollider.position;
    kmVec3* ballVelocity = _ballCollider.velocity;

    if (headPosition == NULL || headVelocity == NULL || ballVelocity == NULL) {
        return;
    }

    float ballRadius = _ballCollider.radius;
    float headRadius = _slingCollider.radius;

    float radii = ballRadius + headRadius;

    BOOL headIsWithinBallHitbox =
        fabs(headPosition->x - ballPosition.x) < radii &&
        fabs(headPosition->y - ballPosition.y) < radii &&
        fabs(headPosition->z - ballPosition.z) < radii;

    if (headIsWithinBallHitbox) {
        float distance = kmVec3DistanceSq(headPosition, &ballPosition);

        if (distance < radii) {
            kmVec3 directionFromBallToHead;
            kmVec3Normalize(&directionFromBallToHead, kmVec3Subtract(&directionFromBallToHead, headPosition, &ballPosition));

            kmVec3 directionFromHeadToBall;
            kmVec3Scale(&directionFromHeadToBall, &directionFromBallToHead, -1);

            kmVec3 contactAdjustment;
            kmVec3Scale(&contactAdjustment, &directionFromBallToHead, ballRadius);

            kmVec3 contactPoint;
            kmVec3Add(&contactPoint, &ballPosition, &contactAdjustment);

            kmVec3 headPositionAdjustment;
            kmVec3Scale(&headPositionAdjustment, &directionFromBallToHead, radii);

            kmVec3Add(headPosition, &ballPosition, &headPositionAdjustment);

            kmVec3 reflectedHeadVelocity;
            kmVec3Reflect(&reflectedHeadVelocity, headVelocity, &directionFromBallToHead);
            //kmVec3Scale(&reflectedHeadVelocity, &reflectedHeadVelocity, 0.9f);

            kmVec3Assign(headVelocity, &reflectedHeadVelocity);

            float headForce = kmVec3LengthSq(headVelocity);

            kmVec3 addedBallVelocity;
            kmVec3Scale(&addedBallVelocity, &directionFromHeadToBall, headForce);

            kmVec3Add(ballVelocity, ballVelocity, &addedBallVelocity);

            _ballCollider.mostRecentCollider = _slingCollider;

            [self resolvedCollisionBetweenCollidable: _slingCollider
                                       andCollidable: _ballCollider
                                      atContactPoint: contactPoint];

            float gain = headForce * 10;

            if (gain > 1) {
                gain = 1;
            }

            [[NVAudioCache sharedCache] playSoundWithKey: kAudioSlingCollision gain: gain pitch: 1.0f location: CGPointZero shouldLoop: NO sourceID: -1];
        }
    }
}

- (void) checkCollisionAgainstSlingAndBoundaries {
    kmVec3* position = _slingCollider.position;
    kmVec3* velocity = _slingCollider.velocity;

    if (position == NULL || velocity == NULL) {
        return;
    }

    float r = _slingCollider.radius;

    float d = _playingFieldController.width / 2;
    float w = _playingFieldController.height / 2;

    kmVec3 min;
    kmVec3Fill(&min, -d, -w, 0);

    kmVec3 max;
    kmVec3Fill(&max, d, w, 0);

    NVAABB bounds = {
        min, max
    };

    SBCollisionWall result = [SBCollisionController innerWallCollisionForSphereWithCenter: position
                                                                                andRadius: r
                                                                        againstBoundaries: bounds];

    kmVec3 reflectionPlane;
    kmVec3 contactPoint;

    if ((result & SBCollisionWallLeft) != 0) {
        position->x = min.x + r;

        kmVec3Fill(&reflectionPlane, 1, 0, 0);
        kmVec3Fill(&contactPoint, min.x, position->y, position->z);
    } else if ((result & SBCollisionWallRight) != 0) {
        position->x = max.x - r;

        kmVec3Fill(&reflectionPlane, -1, 0, 0);
        kmVec3Fill(&contactPoint, max.x, position->y, position->z);
    }

    if ((result & SBCollisionWallDown) != 0) {
        position->y = min.y + r;

        kmVec3Fill(&reflectionPlane, 0, -1, 0);
        kmVec3Fill(&contactPoint, position->x, min.y, position->z);
    } else if ((result & SBCollisionWallUp) != 0) {
        position->y = max.y - r;

        kmVec3Fill(&reflectionPlane, 0, 1, 0);
        kmVec3Fill(&contactPoint, position->x, max.y, position->z);
    }

    if (result != SBCollisionWallNone) {
        float l = kmVec3LengthSq(velocity);

        if (l > kmEpsilon) {
            float gain = l * 25;

            if (gain < 0.1f) {
                gain = 0.1f;
            } else if (gain > 1) {
                gain = 1;
            }

            [[NVAudioCache sharedCache] playSoundWithKey: kAudioWallCollision gain: gain pitch: 1.0f location: CGPointZero shouldLoop: NO sourceID: -1];

            kmVec3Reflect(velocity, velocity, &reflectionPlane);

            [self resolvedCollisionAtContactPoint: contactPoint];
        }
    }

    position->z = 0;
}

- (void) resolve {
    [self checkCollisionAgainstBallAndSling];
    [self checkCollisionAgainstSlingAndBoundaries];
}

@end


text:
import numpy as np
import scipy.sparse as sp
from pymg.transfer_base import TransferBase

class LinearTransferPeriodic(TransferBase):
    """Implementation of the linear prolongation and restriction operators

    Attributes:
        I_2htoh (scipy.sparse.csc_matrix): prolongation matrix
        I_hto2h (scipy.sparse.csc_matrix): restriction matrix
    """

    def __init__(self, ndofs_fine, ndofs_coarse, *args, **kwargs):
        """Initialization routine for transfer operators

        Args:
            ndofs_fine (int): number of DOFs on the fine grid
            ndofs_coarse (int): number of DOFs on the coarse grid
            *args: Variable length argument list
            **kwargs: Arbitrary keyword arguments
        """
        # for this particular transfer class, we need to make a few assumptions
        assert isinstance(ndofs_fine, int), type(ndofs_fine)
        assert isinstance(ndofs_coarse, int)
        # assert (ndofs_fine) % 2 == 0
        # assert ndofs_coarse == (ndofs_fine) / 2
        if ndofs_fine % 2 == 1:
            self.odd = True
            assert ndofs_coarse == (ndofs_fine + 1) / 2 - 1
        else:
            self.odd = False
            assert ndofs_coarse == (ndofs_fine) / 2

        super(LinearTransferPeriodic, self).__init__(ndofs_fine, ndofs_coarse, *args, **kwargs)

        # pre-compute prolongation and restriction matrices
        self.I_2htoh = self.__get_prolongation_matrix(ndofs_coarse, ndofs_fine)
        self.I_hto2h = self.__get_restriction_matrix()

    def __get_prolongation_matrix(self, ndofs_coarse, ndofs_fine):
        """Helper routine for the prolongation operator

        Args:
            ndofs_fine (int): number of DOFs on the fine grid
            ndofs_coarse (int): number of DOFs on the coarse grid

        Returns:
            scipy.sparse.csc_matrix: sparse prolongation matrix of size
                `ndofs_fine` x `ndofs_coarse`
        """

        # This is a workaround, since I am not aware of a suitable way to do
        # this directly with sparse matrices.
        if self.odd:
            P = np.zeros((ndofs_fine, ndofs_coarse))
            np.fill_diagonal(P[1::2, :], 1)
            np.fill_diagonal(P[0::2, :], 1.0 / 2.0)
            np.fill_diagonal(P[2::2, :], 1.0 / 2.0)
            P[0, -1] = 1.0 / 2.0
            P[-1, 0] = 1.0 / 2.0
        else:
            P = np.zeros((ndofs_fine, ndofs_coarse))
            np.fill_diagonal(P[0::2, :], 1)
            np.fill_diagonal(P[1::2, :], 1.0 / 2.0)
            np.fill_diagonal(P[1::2, 1:], 1.0 / 2.0)
            P[-1, 0] = 1.0 / 2.0

        return sp.csc_matrix(P)

    def __get_restriction_matrix(self):
        """Helper routine for the restriction operator

        Returns:
           scipy.sparse.csc_matrix: sparse restriction matrix of size
                `ndofs_coarse` x `ndofs_fine`
        """
        assert hasattr(self, 'I_2htoh')
        return 0.5 * sp.csc_matrix(self.I_2htoh.T)

    def restrict(self, u_coarse):
        """Routine to apply restriction

        Args:
            u_coarse (numpy.ndarray): vector on coarse grid, size `ndofs_coarse`
        Returns:
            numpy.ndarray: vector on fine grid, size `ndofs_fine`
        """
        return self.I_hto2h.dot(u_coarse)

    def prolong(self, u_fine):
        """Routine to apply prolongation

        Args:
            u_fine (numpy.ndarray): vector on fine grid, size `ndofs_fine`
        Returns:
            numpy.ndarray: vector on coarse grid, size `ndofs_coarse`
        """
        return self.I_2htoh.dot(u_fine)


text:
require 'rails_helper'

RSpec.describe 'SchoolClasses', type: :request do
  # index
  describe 'GET /school_classes' do
    it 'lists all the school classes' do
      FactoryGirl.create :school_class, name: 'KJ'
      FactoryGirl.create :school_class, name: '1B'

      get school_classes_path

      expect(response).to have_http_status(:success)

      body = JSON.parse(response.body)
      names = body.fetch('data').map { |school_class| school_class.fetch('attributes').fetch('name') }

      expect(names).to match_array(%w(KJ 1B))
    end
  end

  # show
  describe 'GET /school_classes/:1' do
    let(:school_class) { FactoryGirl.create :school_class, name: 'KJ' }

    it 'returns the specified school_class' do
      get school_class_path(school_class)

      expect(response).to have_http_status(:success)

      body = JSON.parse(response.body)

      expect(body.fetch('data').fetch('attributes').fetch('name')).to eq 'KJ'
    end
  end

  # create
  describe 'POST /school_classes' do
    it 'creates the specified school_class' do
      teacher = FactoryGirl.create :teacher
      school_class = { data: { type: 'school_classes', attributes: { name: '1B', teacher_id: teacher.id } } }

      expect do
        post school_classes_path, params: school_class.to_json, headers: { 'Content-Type': 'application/vnd.api+json' }

        expect(response).to have_http_status(:created)
        expect(response.headers['Location']).to eq school_class_url(SchoolClass.last)

        body = JSON.parse(response.body)
        attributes = body.fetch('data').fetch('attributes')
        relationships = body.fetch('data').fetch('relationships')

        expect(attributes.fetch('name')).to eq '1B'
        expect(relationships.fetch('teacher').fetch('data').fetch('id')).to eq teacher.id.to_s
      end.to change(SchoolClass, :count).by 1
    end

    it 'fails to create the specific school_class with missing data' do
      school_class = { data: { type: 'school_classes', attributes: { foo: 'bar' } } }

      expect do
        post school_classes_path, params: school_class.to_json, headers: { 'Content-Type': 'application/vnd.api+json' }

        body = JSON.parse(response.body)
        errors = body.fetch('errors')
        errors = errors.sort_by { |error| [error.dig('source', 'pointer'), error['detail']] }

        expected = [
          { 'source' => { 'pointer' => '/data/attributes/name' },    'detail' => "can't be blank" },
          { 'source' => { 'pointer' => '/data/attributes/teacher' }, 'detail' => 'must exist' }
        ]

        expect(errors).to eql(expected)
      end.not_to change(SchoolClass, :count)
    end
  end

  # update
  describe 'PUT /school_class/:id' do
    let(:school_class) { FactoryGirl.create :school_class }

    it 'updates the specified school_class' do
      put_school_class = { data: { type: 'school_classes', id: school_class.id, attributes: { name: '1C' } } }

      put school_class_path(school_class),
          params: put_school_class.to_json,
          headers: { 'Content-Type': 'application/vnd.api+json' }

      expect(response).to have_http_status(:success)

      body = JSON.parse(response.body)

      expect(body.fetch('data').fetch('attributes').fetch('name')).to eq '1C'
    end
  end

  # destroy
  describe 'DELETE /school_class/:id' do
    it 'deletes the specified school_class' do
      school_class = FactoryGirl.create :school_class

      expect do
        delete school_class_path(school_class)

        expect(response).to have_http_status(:no_content)
      end.to change(SchoolClass, :count).by(-1)
    end
  end
end