Add delta calculation mechanism

This commit is contained in:
Clint Byrum 2015-10-28 06:43:55 +09:00
parent 18d5f0809e
commit 7552a39882
2 changed files with 117 additions and 0 deletions

View File

@ -0,0 +1,46 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
def delta(previous, current):
product = {}
seen = set()
# Old keys
for k, v in previous.items():
if k not in current:
continue
newv = current[k]
if type(v) is not type(newv):
raise ValueError(
'Type of key %s changed from %s to %s' % (k,
type(v),
type(newv)))
if isinstance(v, int) or isinstance(v, float):
product[k] = newv - v
elif isinstance(v, dict):
product[k] = delta(v, newv)
else:
raise ValueError('Only mappings of numbers are understood')
seen.add(k)
# New keys
for k in set(current.keys()) - seen:
product[k] = current[k]
return product
def delta_with_file(previous_path, current_data):
with open(previous_path) as previous_file:
previous_data = json.loads(previous_file.read())
return delta(previous_data, current_data)

View File

@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
test_delta
----------------------------------
Tests for `openstack_qa_tools.collectors._delta`
"""
import testscenarios
from openstack_qa_tools.collectors import _delta
from openstack_qa_tools.tests import base
class TestOSQATDelta(testscenarios.WithScenarios, base.TestCase):
scenarios = [
('add1', dict(
previous={'zoo': {'aardvark': 9, 'zebra': 0}},
current={'zoo': {'aardvark': 12, 'zebra': 0}},
expected={'zoo': {'aardvark': 3, 'zebra': 0}})),
('newkey', dict(
previous={'zoo': {'bee': 0}},
current={'lake': {'trout': 1}, 'zoo': {'bee': 5}},
expected={'lake': {'trout': 1}, 'zoo': {'bee': 5}})),
('delkey', dict(
previous={'zoo': {'cat': 99}},
current={},
expected={})),
('newvar', dict(
previous={'zoo': {'dog': 9}},
current={'zoo': {'dog': 9, 'ocelot': 2}},
expected={'zoo': {'dog': 0, 'ocelot': 2}})),
('delvar', dict(
previous={'zoo': {'elephant': 1000, 'bear': 1}},
current={'zoo': {'elephant': 1000}},
expected={'zoo': {'elephant': 0}})),
('stringval', dict(
previous={'zoo': 'foo'},
current={'zoo': 0},
expected=ValueError)),
('newstrval', dict(
previous={'zoo': {'giraffe': 100}},
current={'zoo': {'giraffe': 'tall'}},
expected=ValueError)),
('changetype', dict(
previous={'zoo': {'horse': 7}},
current={'zoo': 15},
expected=ValueError)),
]
def test_delta(self):
if self.expected is ValueError:
self.assertRaises(ValueError, _delta.delta, self.previous,
self.current)
else:
self.assertEqual(self.expected, _delta.delta(self.previous,
self.current))