import datetime from django.test import TestCase from django.core.exceptions import ValidationError from ..models import ( Cost, CostUse, Document, Good, GoodUse, Service, ServiceUse) THREE_YEARS = datetime.timedelta(days=365*3) class ServiceTests(TestCase): def setUp(self): self.doc = Document.objects.create(name='budget') self.electricity_cost = Cost.objects.create( name='electricity', price=10, document=self.doc, ) self.server = Good.objects.create( name="Computer", price=10, document=self.doc, provisioning_duration=THREE_YEARS, ) def test_get_prices_zero(self): s = Service.objects.create(name='Foo', document=self.doc) self.assertEqual(s.get_prices(), { 'total_recurring_price': 0, 'unit_recurring_price': 0, 'unit_goods_value_share': 0, 'total_goods_value_share': 0, }) def test_get_prices_w_costs(self): s = Service.objects.create(name='Foo', document=self.doc) CostUse.objects.create( service=s, resource=self.electricity_cost, share=0.4) self.assertEqual(s.get_prices(), { 'total_recurring_price': 10, 'unit_recurring_price': 0, 'unit_goods_value_share': 0, 'total_goods_value_share': 0, }) s.subscriptions_count = 2 s.save() self.assertEqual(s.get_prices(), { 'total_recurring_price': 10, 'unit_recurring_price': 5, 'unit_goods_value_share': 0, 'total_goods_value_share': 0, }) def test_get_prices_w_goods(self): s = Service.objects.create( name='Foo', document=self.doc, subscriptions_count=0) GoodUse.objects.create( service=s, resource=self.server, share=0.4) self.assertEqual(s.get_prices(), { 'total_recurring_price': 10/(365*3)*365.25/12, 'unit_recurring_price': 0, 'unit_goods_value_share': 0, 'total_goods_value_share': 10.0, }) s.subscriptions_count = 2 s.save() self.assertEqual(s.get_prices(), { 'total_recurring_price': 10/(365*3)*365.25/12, 'unit_recurring_price': 10/(365*3)*365.25/12/2, 'unit_goods_value_share': 5, 'total_goods_value_share': 10, }) class AbstractUseTests(TestCase): """ Testing AbstractUseTests through CostUse """ def setUp(self): self.doc = Document.objects.create(name='budget') self.hosting_service = Service.objects.create( name='Physical hosting', document=self.doc) self.mailbox_service = Service.objects.create( name='Mailbox', document=self.doc) self.electricity_cost = Cost.objects.create( name='electricity', price=10, document=self.doc, capacity_unit='A', total_capacity=4, ) self.carrier_connection = Cost.objects.create( name='carrier connection', price=100, document=self.doc, ) def test_can_add_service_share(self): use = CostUse( service=self.hosting_service, resource=self.electricity_cost, share=0.4) use.full_clean() use.save() def test_can_add_service_share_with_custom_unity(self): use = CostUse( service=self.hosting_service, resource=self.electricity_cost, share=2) # means 2 Amps self.hosting_service.subscriptions_count = 2 self.hosting_service.save() use.full_clean() use.save() self.assertEqual(use.share, 2.0) self.assertEqual(use.real_share(), 4.0) self.assertEqual(use.cost_share(), 10) self.assertEqual(use.unit_cost_share(), 5) def test_cannot_add_excess_share_one(self): use = CostUse( service=self.hosting_service, resource=self.electricity_cost, share=40.1) with self.assertRaises(ValidationError): use.full_clean() use.save() def test_add_several_service_share(self): u1 = CostUse( service=self.hosting_service, resource=self.electricity_cost, share=0.4) u1.full_clean() u1.save() u2 = CostUse( service=self.mailbox_service, resource=self.electricity_cost, share=0.6) u2.full_clean() u2.save() def test_add_several_service_share_excessive_sum(self): u1 = CostUse( service=self.hosting_service, resource=self.electricity_cost, share=3) u1.full_clean() u1.save() u2 = CostUse( service=self.mailbox_service, resource=self.electricity_cost, share=1.1) # Would be 4.1 out of 4 amp... with self.assertRaises(ValidationError): u2.full_clean() u2.save() def test_modify_service_share_no_error(self): u1 = CostUse( service=self.hosting_service, resource=self.electricity_cost, share=1) u1.full_clean() u1.save() u1.full_clean() u1.save() def test_real_shares(self): u1 = CostUse.objects.create( service=self.hosting_service, resource=self.electricity_cost, share=1.6) u2 = CostUse.objects.create( service=self.hosting_service, resource=self.electricity_cost, share=0.6) self.assertEqual(u1.real_share() + u2.real_share(), 4) self.assertEqual(u1.share/u2.share, u1.real_share()/u2.real_share()) def test_unit_value_share(self): self.mailbox_service.subscriptions_count = 2 self.mailbox_service.share = 0.5 self.hosting_service.save() self.hosting_service.subscriptions_count = 1 self.hosting_service.share = 0.5 self.hosting_service.save() mailbox_use = CostUse.objects.create( service=self.mailbox_service, resource=self.electricity_cost, share=2) hosting_use = CostUse.objects.create( service=self.hosting_service, resource=self.electricity_cost, share=2) self.assertEqual(mailbox_use.value_share(), 5) self.assertEqual(mailbox_use.unit_value_share(), 2.5) self.assertEqual(hosting_use.value_share(), 5) self.assertEqual(hosting_use.unit_value_share(), 5) def test_used(self): CostUse.objects.create( service=self.mailbox_service, resource=self.electricity_cost, share=0.5) self.assertEqual(self.electricity_cost.used(), 0.5) self.assertEqual(self.electricity_cost.unused(), 3.5) def test_service_using_service(self): """ Wifi+VPN is a service, but using VPN access So there is a service using another service """ vpn_service = Service.objects.create( name="VPN", document=self.doc, subscriptions_count=20, # includes wifi+vpn subscribers reusable=True, ) # both should be auto-set self.assertEqual(vpn_service.capacity_unit, 'services') self.assertEqual(vpn_service.total_capacity, 20) wifi_service = Service.objects.create( name="Wifi, via VPN", document=self.doc, subscriptions_count=2, reusable=True, ) self.assertEqual(vpn_service.capacity_unit, 'services') # To simplify, VPN is only using electricity CostUse.objects.create( service=vpn_service, resource=self.electricity_cost, share=0.5, # Amp ) # Wifi is using VPN + a carrier connection wifi_vpn_use = ServiceUse.objects.create( service=wifi_service, resource=vpn_service, share=2, ) CostUse.objects.create( service=wifi_service, resource=self.carrier_connection, share=1, # 100% ) self.assertEqual(wifi_vpn_use.share, 0.5*4*10/20*2) self.assertEqual(wifi_vpn_use.unit_share(), 0.5*4*10/20) # VPN this is the only service using electricity self.assertEqual(wifi_vpn_use.unit_real_share(), 10) # VPN is now using some gear, with deprecation provisioning hosting_access_fee = Good.objects.create( name='hosting access fee', price=360, provisioning_duration=THREE_YEARS, document=self.doc) GoodUse.objects.create( service=vpn_service, resource=hosting_access_fee, share=2) self.assertEqual( wifi_service.get_prices()['total_goods_value_share'], 36) self.assertEqual( wifi_service.get_prices()['unit_goods_value_share'], 18) def test_service_using_non_usable_service(self): serva = Service.objects.create( name='A', document=self.doc, subscriptions_count=4, reusable=False, ) with self.assertRaises(ValidationError): su = ServiceUse( service=self.mailbox_service, resource=serva, share=1, ) su.full_clean() su.save() def test_service_using_cyclic_service(self): """ We should not save any service dependency building a cycle """ a = Service.objects.create( name='a', document=self.doc, reusable=True, ) b = Service.objects.create( name='b', document=self.doc, reusable=True, ) c = Service.objects.create( name='c', document=self.doc, reusable=True, ) def create_clean(user, used): new_use = ServiceUse(service=user, resource=used, share=1) new_use.full_clean() new_use.save() create_clean(a, b) with self.assertRaises(ValidationError): create_clean(b, a) create_clean(b, c) with self.assertRaises(ValidationError): create_clean(c, a) class TestDocuments(TestCase): fixtures = ['full_example.yaml'] _all_models = [Document, Cost, Good, Service, GoodUse, CostUse, ServiceUse] def _count(self): return [i.objects.count() for i in self._all_models] def test_copy(self): initial_counts = self._count() old_doc = Document.objects.first() new_doc = old_doc.copy() self.assertNotEqual(new_doc.pk, old_doc.pk) self.assertEqual(self._count(), [i*2 for i in initial_counts]) old_doc.delete() self.assertEqual(self._count(), initial_counts)