diff options
Diffstat (limited to 'lib')
213 files changed, 16593 insertions, 6788 deletions
diff --git a/lib/.gitignore b/lib/.gitignore new file mode 100644 index 0000000000..0cb938ea7c --- /dev/null +++ b/lib/.gitignore @@ -0,0 +1,471 @@ +# erl_interface + +/erl_interface/bin +/erl_interface/obj.mt +/erl_interface/obj.st +/erl_interface/obj + +# megaco + +/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3a.erl +/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3a.hrl +/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3b.erl +/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3b.hrl +/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3c.erl +/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3c.hrl +/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v1.erl +/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v1.hrl +/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v2.erl +/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v2.hrl +/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v3.erl +/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_v3.hrl +/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3a.erl +/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3a.hrl +/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3b.erl +/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3b.hrl +/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3c.erl +/megaco/src/binary/megaco_ber_bin_media_gateway_control_prev3c.hrl +/megaco/src/binary/megaco_ber_bin_media_gateway_control_v1.erl +/megaco/src/binary/megaco_ber_bin_media_gateway_control_v1.hrl +/megaco/src/binary/megaco_ber_bin_media_gateway_control_v2.erl +/megaco/src/binary/megaco_ber_bin_media_gateway_control_v2.hrl +/megaco/src/binary/megaco_ber_bin_media_gateway_control_v3.erl +/megaco/src/binary/megaco_ber_bin_media_gateway_control_v3.hrl +/megaco/src/binary/megaco_ber_media_gateway_control_prev3a.erl +/megaco/src/binary/megaco_ber_media_gateway_control_prev3a.hrl +/megaco/src/binary/megaco_ber_media_gateway_control_prev3b.erl +/megaco/src/binary/megaco_ber_media_gateway_control_prev3b.hrl +/megaco/src/binary/megaco_ber_media_gateway_control_prev3c.erl +/megaco/src/binary/megaco_ber_media_gateway_control_prev3c.hrl +/megaco/src/binary/megaco_ber_media_gateway_control_v1.erl +/megaco/src/binary/megaco_ber_media_gateway_control_v1.hrl +/megaco/src/binary/megaco_ber_media_gateway_control_v2.erl +/megaco/src/binary/megaco_ber_media_gateway_control_v2.hrl +/megaco/src/binary/megaco_ber_media_gateway_control_v3.erl +/megaco/src/binary/megaco_ber_media_gateway_control_v3.hrl +/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_prev3a.erl +/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_prev3a.hrl +/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_prev3b.erl +/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_prev3b.hrl +/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_prev3c.erl +/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_prev3c.hrl +/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_v1.erl +/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_v1.hrl +/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_v2.erl +/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_v2.hrl +/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_v3.erl +/megaco/src/binary/megaco_per_bin_drv_media_gateway_control_v3.hrl +/megaco/src/binary/megaco_per_bin_media_gateway_control_prev3a.erl +/megaco/src/binary/megaco_per_bin_media_gateway_control_prev3a.hrl +/megaco/src/binary/megaco_per_bin_media_gateway_control_prev3b.erl +/megaco/src/binary/megaco_per_bin_media_gateway_control_prev3b.hrl +/megaco/src/binary/megaco_per_bin_media_gateway_control_prev3c.erl +/megaco/src/binary/megaco_per_bin_media_gateway_control_prev3c.hrl +/megaco/src/binary/megaco_per_bin_media_gateway_control_v1.erl +/megaco/src/binary/megaco_per_bin_media_gateway_control_v1.hrl +/megaco/src/binary/megaco_per_bin_media_gateway_control_v2.erl +/megaco/src/binary/megaco_per_bin_media_gateway_control_v2.hrl +/megaco/src/binary/megaco_per_bin_media_gateway_control_v3.erl +/megaco/src/binary/megaco_per_bin_media_gateway_control_v3.hrl +/megaco/src/binary/megaco_per_media_gateway_control_prev3a.erl +/megaco/src/binary/megaco_per_media_gateway_control_prev3a.hrl +/megaco/src/binary/megaco_per_media_gateway_control_prev3b.erl +/megaco/src/binary/megaco_per_media_gateway_control_prev3b.hrl +/megaco/src/binary/megaco_per_media_gateway_control_prev3c.erl +/megaco/src/binary/megaco_per_media_gateway_control_prev3c.hrl +/megaco/src/binary/megaco_per_media_gateway_control_v1.erl +/megaco/src/binary/megaco_per_media_gateway_control_v1.hrl +/megaco/src/binary/megaco_per_media_gateway_control_v2.erl +/megaco/src/binary/megaco_per_media_gateway_control_v2.hrl +/megaco/src/binary/megaco_per_media_gateway_control_v3.erl +/megaco/src/binary/megaco_per_media_gateway_control_v3.hrl +/megaco/src/binary/prebuild.skip +/megaco/src/flex/megaco_flex_scanner_drv.c +/megaco/src/flex/megaco_flex_scanner_drv.flex +/megaco/src/flex/megaco_flex_scanner_drv_mt.c +/megaco/src/flex/megaco_flex_scanner_drv_mt.flex +/megaco/src/text/megaco_text_mini_parser.erl +/megaco/src/text/megaco_text_parser_prev3a.erl +/megaco/src/text/megaco_text_parser_prev3b.erl +/megaco/src/text/megaco_text_parser_prev3c.erl +/megaco/src/text/megaco_text_parser_v1.erl +/megaco/src/text/megaco_text_parser_v2.erl +/megaco/src/text/megaco_text_parser_v3.erl + +# orber & cos* applications + +/cosEvent/include/CosEventChannelAdmin.hrl +/cosEvent/include/CosEventChannelAdmin_ConsumerAdmin.hrl +/cosEvent/include/CosEventChannelAdmin_EventChannel.hrl +/cosEvent/include/CosEventChannelAdmin_ProxyPullConsumer.hrl +/cosEvent/include/CosEventChannelAdmin_ProxyPullSupplier.hrl +/cosEvent/include/CosEventChannelAdmin_ProxyPushConsumer.hrl +/cosEvent/include/CosEventChannelAdmin_ProxyPushSupplier.hrl +/cosEvent/include/CosEventChannelAdmin_SupplierAdmin.hrl +/cosEvent/include/CosEventComm.hrl +/cosEvent/include/CosEventComm_PullConsumer.hrl +/cosEvent/include/CosEventComm_PullSupplier.hrl +/cosEvent/include/CosEventComm_PushConsumer.hrl +/cosEvent/include/CosEventComm_PushSupplier.hrl +/cosEvent/include/oe_CosEventChannelAdmin.hrl +/cosEvent/include/oe_CosEventComm.hrl +/cosEvent/src/CosEventChannelAdmin_AlreadyConnected.erl +/cosEvent/src/CosEventChannelAdmin_ConsumerAdmin.erl +/cosEvent/src/CosEventChannelAdmin_EventChannel.erl +/cosEvent/src/CosEventChannelAdmin_ProxyPullConsumer.erl +/cosEvent/src/CosEventChannelAdmin_ProxyPullSupplier.erl +/cosEvent/src/CosEventChannelAdmin_ProxyPushConsumer.erl +/cosEvent/src/CosEventChannelAdmin_ProxyPushSupplier.erl +/cosEvent/src/CosEventChannelAdmin_SupplierAdmin.erl +/cosEvent/src/CosEventChannelAdmin_TypeError.erl +/cosEvent/src/CosEventComm_Disconnected.erl +/cosEvent/src/CosEventComm_PullConsumer.erl +/cosEvent/src/CosEventComm_PullSupplier.erl +/cosEvent/src/CosEventComm_PushConsumer.erl +/cosEvent/src/CosEventComm_PushSupplier.erl +/cosEvent/src/oe_CosEventChannelAdmin.erl +/cosEvent/src/oe_CosEventComm.erl +/cosEvent/src/oe_CosEventComm_CAdmin.erl +/cosEvent/src/oe_CosEventComm_CAdmin.hrl +/cosEvent/src/oe_CosEventComm_Channel.erl +/cosEvent/src/oe_CosEventComm_Channel.hrl +/cosEvent/src/oe_CosEventComm_Event.erl +/cosEvent/src/oe_CosEventComm_Event.hrl +/cosEvent/src/oe_CosEventComm_PullerS.erl +/cosEvent/src/oe_CosEventComm_PullerS.hrl +/cosEvent/src/oe_CosEventComm_PusherS.erl +/cosEvent/src/oe_CosEventComm_PusherS.hrl +/cosEvent/src/oe_cosEventApp.erl +/cosEvent/src/oe_cosEventApp.hrl +/cosEventDomain/include/CosEventDomainAdmin.hrl +/cosEventDomain/include/CosEventDomainAdmin_EventDomain.hrl +/cosEventDomain/include/CosEventDomainAdmin_EventDomainFactory.hrl +/cosEventDomain/include/oe_CosEventDomainAdmin.hrl +/cosEventDomain/src/CosEventDomainAdmin.erl +/cosEventDomain/src/CosEventDomainAdmin_AlreadyExists.erl +/cosEventDomain/src/CosEventDomainAdmin_Connection.erl +/cosEventDomain/src/CosEventDomainAdmin_ConnectionIDSeq.erl +/cosEventDomain/src/CosEventDomainAdmin_ConnectionNotFound.erl +/cosEventDomain/src/CosEventDomainAdmin_CycleCreationForbidden.erl +/cosEventDomain/src/CosEventDomainAdmin_CycleSeq.erl +/cosEventDomain/src/CosEventDomainAdmin_DiamondCreationForbidden.erl +/cosEventDomain/src/CosEventDomainAdmin_DiamondSeq.erl +/cosEventDomain/src/CosEventDomainAdmin_DomainIDSeq.erl +/cosEventDomain/src/CosEventDomainAdmin_DomainNotFound.erl +/cosEventDomain/src/CosEventDomainAdmin_EventDomain.erl +/cosEventDomain/src/CosEventDomainAdmin_EventDomainFactory.erl +/cosEventDomain/src/CosEventDomainAdmin_MemberIDSeq.erl +/cosEventDomain/src/CosEventDomainAdmin_RouteSeq.erl +/cosEventDomain/src/oe_CosEventDomainAdmin.erl +/cosFileTransfer/include/CosFileTransfer.hrl +/cosFileTransfer/include/CosFileTransfer_Directory.hrl +/cosFileTransfer/include/CosFileTransfer_File.hrl +/cosFileTransfer/include/CosFileTransfer_FileIterator.hrl +/cosFileTransfer/include/CosFileTransfer_FileTransferSession.hrl +/cosFileTransfer/include/CosFileTransfer_VirtualFileSystem.hrl +/cosFileTransfer/include/oe_CosFileTransfer.hrl +/cosFileTransfer/src/CosFileTransfer.erl +/cosFileTransfer/src/CosFileTransfer_AccessLevel.erl +/cosFileTransfer/src/CosFileTransfer_CommandNotImplementedException.erl +/cosFileTransfer/src/CosFileTransfer_Directory.erl +/cosFileTransfer/src/CosFileTransfer_File.erl +/cosFileTransfer/src/CosFileTransfer_FileIterator.erl +/cosFileTransfer/src/CosFileTransfer_FileList.erl +/cosFileTransfer/src/CosFileTransfer_FileNameList.erl +/cosFileTransfer/src/CosFileTransfer_FileNotFoundException.erl +/cosFileTransfer/src/CosFileTransfer_FileTransferSession.erl +/cosFileTransfer/src/CosFileTransfer_FileWrapper.erl +/cosFileTransfer/src/CosFileTransfer_IllegalOperationException.erl +/cosFileTransfer/src/CosFileTransfer_ProtocolAddressList.erl +/cosFileTransfer/src/CosFileTransfer_ProtocolSupport.erl +/cosFileTransfer/src/CosFileTransfer_RequestFailureException.erl +/cosFileTransfer/src/CosFileTransfer_SessionException.erl +/cosFileTransfer/src/CosFileTransfer_SupportedProtocolAddresses.erl +/cosFileTransfer/src/CosFileTransfer_TransferException.erl +/cosFileTransfer/src/CosFileTransfer_VirtualFileSystem.erl +/cosFileTransfer/src/CosFileTransfer_VirtualFileSystem_ContentList.erl +/cosFileTransfer/src/oe_CosFileTransfer.erl +/cosNotification/include/CosNotification.hrl +/cosNotification/include/CosNotification_AdminPropertiesAdmin.hrl +/cosNotification/include/CosNotification_QoSAdmin.hrl +/cosNotification/include/CosNotifyChannelAdmin.hrl +/cosNotification/include/CosNotifyChannelAdmin_ConsumerAdmin.hrl +/cosNotification/include/CosNotifyChannelAdmin_EventChannel.hrl +/cosNotification/include/CosNotifyChannelAdmin_EventChannelFactory.hrl +/cosNotification/include/CosNotifyChannelAdmin_ProxyConsumer.hrl +/cosNotification/include/CosNotifyChannelAdmin_ProxyPullConsumer.hrl +/cosNotification/include/CosNotifyChannelAdmin_ProxyPullSupplier.hrl +/cosNotification/include/CosNotifyChannelAdmin_ProxyPushConsumer.hrl +/cosNotification/include/CosNotifyChannelAdmin_ProxyPushSupplier.hrl +/cosNotification/include/CosNotifyChannelAdmin_ProxySupplier.hrl +/cosNotification/include/CosNotifyChannelAdmin_SequenceProxyPullConsumer.hrl +/cosNotification/include/CosNotifyChannelAdmin_SequenceProxyPullSupplier.hrl +/cosNotification/include/CosNotifyChannelAdmin_SequenceProxyPushConsumer.hrl +/cosNotification/include/CosNotifyChannelAdmin_SequenceProxyPushSupplier.hrl +/cosNotification/include/CosNotifyChannelAdmin_StructuredProxyPullConsumer.hrl +/cosNotification/include/CosNotifyChannelAdmin_StructuredProxyPullSupplier.hrl +/cosNotification/include/CosNotifyChannelAdmin_StructuredProxyPushConsumer.hrl +/cosNotification/include/CosNotifyChannelAdmin_StructuredProxyPushSupplier.hrl +/cosNotification/include/CosNotifyChannelAdmin_SupplierAdmin.hrl +/cosNotification/include/CosNotifyComm.hrl +/cosNotification/include/CosNotifyComm_NotifyPublish.hrl +/cosNotification/include/CosNotifyComm_NotifySubscribe.hrl +/cosNotification/include/CosNotifyComm_PullConsumer.hrl +/cosNotification/include/CosNotifyComm_PullSupplier.hrl +/cosNotification/include/CosNotifyComm_PushConsumer.hrl +/cosNotification/include/CosNotifyComm_PushSupplier.hrl +/cosNotification/include/CosNotifyComm_SequencePullConsumer.hrl +/cosNotification/include/CosNotifyComm_SequencePullSupplier.hrl +/cosNotification/include/CosNotifyComm_SequencePushConsumer.hrl +/cosNotification/include/CosNotifyComm_SequencePushSupplier.hrl +/cosNotification/include/CosNotifyComm_StructuredPullConsumer.hrl +/cosNotification/include/CosNotifyComm_StructuredPullSupplier.hrl +/cosNotification/include/CosNotifyComm_StructuredPushConsumer.hrl +/cosNotification/include/CosNotifyComm_StructuredPushSupplier.hrl +/cosNotification/include/CosNotifyFilter.hrl +/cosNotification/include/CosNotifyFilter_Filter.hrl +/cosNotification/include/CosNotifyFilter_FilterAdmin.hrl +/cosNotification/include/CosNotifyFilter_FilterFactory.hrl +/cosNotification/include/CosNotifyFilter_MappingFilter.hrl +/cosNotification/include/oe_CosNotification.hrl +/cosNotification/include/oe_CosNotifyChannelAdmin.hrl +/cosNotification/include/oe_CosNotifyComm.hrl +/cosNotification/include/oe_CosNotifyFilter.hrl +/cosNotification/src/CosNotification.erl +/cosNotification/src/CosNotification_AdminPropertiesAdmin.erl +/cosNotification/src/CosNotification_EventBatch.erl +/cosNotification/src/CosNotification_EventHeader.erl +/cosNotification/src/CosNotification_EventType.erl +/cosNotification/src/CosNotification_EventTypeSeq.erl +/cosNotification/src/CosNotification_FixedEventHeader.erl +/cosNotification/src/CosNotification_NamedPropertyRange.erl +/cosNotification/src/CosNotification_NamedPropertyRangeSeq.erl +/cosNotification/src/CosNotification_Property.erl +/cosNotification/src/CosNotification_PropertyError.erl +/cosNotification/src/CosNotification_PropertyErrorSeq.erl +/cosNotification/src/CosNotification_PropertyRange.erl +/cosNotification/src/CosNotification_PropertySeq.erl +/cosNotification/src/CosNotification_QoSAdmin.erl +/cosNotification/src/CosNotification_StructuredEvent.erl +/cosNotification/src/CosNotification_UnsupportedAdmin.erl +/cosNotification/src/CosNotification_UnsupportedQoS.erl +/cosNotification/src/CosNotifyChannelAdmin_AdminIDSeq.erl +/cosNotification/src/CosNotifyChannelAdmin_AdminLimit.erl +/cosNotification/src/CosNotifyChannelAdmin_AdminLimitExceeded.erl +/cosNotification/src/CosNotifyChannelAdmin_AdminNotFound.erl +/cosNotification/src/CosNotifyChannelAdmin_ChannelIDSeq.erl +/cosNotification/src/CosNotifyChannelAdmin_ChannelNotFound.erl +/cosNotification/src/CosNotifyChannelAdmin_ConnectionAlreadyActive.erl +/cosNotification/src/CosNotifyChannelAdmin_ConnectionAlreadyInactive.erl +/cosNotification/src/CosNotifyChannelAdmin_ConsumerAdmin.erl +/cosNotification/src/CosNotifyChannelAdmin_EventChannel.erl +/cosNotification/src/CosNotifyChannelAdmin_EventChannelFactory.erl +/cosNotification/src/CosNotifyChannelAdmin_NotConnected.erl +/cosNotification/src/CosNotifyChannelAdmin_ProxyConsumer.erl +/cosNotification/src/CosNotifyChannelAdmin_ProxyIDSeq.erl +/cosNotification/src/CosNotifyChannelAdmin_ProxyNotFound.erl +/cosNotification/src/CosNotifyChannelAdmin_ProxyPullConsumer.erl +/cosNotification/src/CosNotifyChannelAdmin_ProxyPullSupplier.erl +/cosNotification/src/CosNotifyChannelAdmin_ProxyPushConsumer.erl +/cosNotification/src/CosNotifyChannelAdmin_ProxyPushSupplier.erl +/cosNotification/src/CosNotifyChannelAdmin_ProxySupplier.erl +/cosNotification/src/CosNotifyChannelAdmin_SequenceProxyPullConsumer.erl +/cosNotification/src/CosNotifyChannelAdmin_SequenceProxyPullSupplier.erl +/cosNotification/src/CosNotifyChannelAdmin_SequenceProxyPushConsumer.erl +/cosNotification/src/CosNotifyChannelAdmin_SequenceProxyPushSupplier.erl +/cosNotification/src/CosNotifyChannelAdmin_StructuredProxyPullConsumer.erl +/cosNotification/src/CosNotifyChannelAdmin_StructuredProxyPullSupplier.erl +/cosNotification/src/CosNotifyChannelAdmin_StructuredProxyPushConsumer.erl +/cosNotification/src/CosNotifyChannelAdmin_StructuredProxyPushSupplier.erl +/cosNotification/src/CosNotifyChannelAdmin_SupplierAdmin.erl +/cosNotification/src/CosNotifyComm_InvalidEventType.erl +/cosNotification/src/CosNotifyComm_NotifyPublish.erl +/cosNotification/src/CosNotifyComm_NotifySubscribe.erl +/cosNotification/src/CosNotifyComm_PullConsumer.erl +/cosNotification/src/CosNotifyComm_PullSupplier.erl +/cosNotification/src/CosNotifyComm_PushConsumer.erl +/cosNotification/src/CosNotifyComm_PushSupplier.erl +/cosNotification/src/CosNotifyComm_SequencePullConsumer.erl +/cosNotification/src/CosNotifyComm_SequencePullSupplier.erl +/cosNotification/src/CosNotifyComm_SequencePushConsumer.erl +/cosNotification/src/CosNotifyComm_SequencePushSupplier.erl +/cosNotification/src/CosNotifyComm_StructuredPullConsumer.erl +/cosNotification/src/CosNotifyComm_StructuredPullSupplier.erl +/cosNotification/src/CosNotifyComm_StructuredPushConsumer.erl +/cosNotification/src/CosNotifyComm_StructuredPushSupplier.erl +/cosNotification/src/CosNotifyFilter_CallbackIDSeq.erl +/cosNotification/src/CosNotifyFilter_CallbackNotFound.erl +/cosNotification/src/CosNotifyFilter_ConstraintExp.erl +/cosNotification/src/CosNotifyFilter_ConstraintExpSeq.erl +/cosNotification/src/CosNotifyFilter_ConstraintIDSeq.erl +/cosNotification/src/CosNotifyFilter_ConstraintInfo.erl +/cosNotification/src/CosNotifyFilter_ConstraintInfoSeq.erl +/cosNotification/src/CosNotifyFilter_ConstraintNotFound.erl +/cosNotification/src/CosNotifyFilter_DuplicateConstraintID.erl +/cosNotification/src/CosNotifyFilter_Filter.erl +/cosNotification/src/CosNotifyFilter_FilterAdmin.erl +/cosNotification/src/CosNotifyFilter_FilterFactory.erl +/cosNotification/src/CosNotifyFilter_FilterIDSeq.erl +/cosNotification/src/CosNotifyFilter_FilterNotFound.erl +/cosNotification/src/CosNotifyFilter_InvalidConstraint.erl +/cosNotification/src/CosNotifyFilter_InvalidGrammar.erl +/cosNotification/src/CosNotifyFilter_InvalidValue.erl +/cosNotification/src/CosNotifyFilter_MappingConstraintInfo.erl +/cosNotification/src/CosNotifyFilter_MappingConstraintInfoSeq.erl +/cosNotification/src/CosNotifyFilter_MappingConstraintPair.erl +/cosNotification/src/CosNotifyFilter_MappingConstraintPairSeq.erl +/cosNotification/src/CosNotifyFilter_MappingFilter.erl +/cosNotification/src/CosNotifyFilter_UnsupportedFilterableData.erl +/cosNotification/src/cosNotification_Grammar.erl +/cosNotification/src/oe_CosNotification.erl +/cosNotification/src/oe_CosNotificationComm.hrl +/cosNotification/src/oe_CosNotificationComm_Event.erl +/cosNotification/src/oe_CosNotificationComm_Event.hrl +/cosNotification/src/oe_CosNotifyChannelAdmin.erl +/cosNotification/src/oe_CosNotifyComm.erl +/cosNotification/src/oe_CosNotifyFilter.erl +/cosNotification/src/oe_cosNotificationAppComm.erl +/cosNotification/src/oe_cosNotificationAppComm.hrl +/cosProperty/include/CosPropertyService.hrl +/cosProperty/include/CosPropertyService_PropertiesIterator.hrl +/cosProperty/include/CosPropertyService_PropertyNamesIterator.hrl +/cosProperty/include/CosPropertyService_PropertySet.hrl +/cosProperty/include/CosPropertyService_PropertySetDef.hrl +/cosProperty/include/CosPropertyService_PropertySetDefFactory.hrl +/cosProperty/include/CosPropertyService_PropertySetFactory.hrl +/cosProperty/include/oe_CosProperty.hrl +/cosProperty/src/CosPropertyService_ConflictingProperty.erl +/cosProperty/src/CosPropertyService_ConstraintNotSupported.erl +/cosProperty/src/CosPropertyService_FixedProperty.erl +/cosProperty/src/CosPropertyService_InvalidPropertyName.erl +/cosProperty/src/CosPropertyService_MultipleExceptions.erl +/cosProperty/src/CosPropertyService_Properties.erl +/cosProperty/src/CosPropertyService_PropertiesIterator.erl +/cosProperty/src/CosPropertyService_Property.erl +/cosProperty/src/CosPropertyService_PropertyDef.erl +/cosProperty/src/CosPropertyService_PropertyDefs.erl +/cosProperty/src/CosPropertyService_PropertyException.erl +/cosProperty/src/CosPropertyService_PropertyExceptions.erl +/cosProperty/src/CosPropertyService_PropertyMode.erl +/cosProperty/src/CosPropertyService_PropertyModes.erl +/cosProperty/src/CosPropertyService_PropertyNames.erl +/cosProperty/src/CosPropertyService_PropertyNamesIterator.erl +/cosProperty/src/CosPropertyService_PropertyNotFound.erl +/cosProperty/src/CosPropertyService_PropertySet.erl +/cosProperty/src/CosPropertyService_PropertySetDef.erl +/cosProperty/src/CosPropertyService_PropertySetDefFactory.erl +/cosProperty/src/CosPropertyService_PropertySetFactory.erl +/cosProperty/src/CosPropertyService_PropertyTypes.erl +/cosProperty/src/CosPropertyService_ReadOnlyProperty.erl +/cosProperty/src/CosPropertyService_UnsupportedMode.erl +/cosProperty/src/CosPropertyService_UnsupportedProperty.erl +/cosProperty/src/CosPropertyService_UnsupportedTypeCode.erl +/cosProperty/src/oe_CosProperty.erl +/cosTime/include/CosTime.hrl +/cosTime/include/CosTime_TIO.hrl +/cosTime/include/CosTime_TimeService.hrl +/cosTime/include/CosTime_UTO.hrl +/cosTime/include/CosTimerEvent.hrl +/cosTime/include/CosTimerEvent_TimerEventHandler.hrl +/cosTime/include/CosTimerEvent_TimerEventService.hrl +/cosTime/include/TimeBase.hrl +/cosTime/include/oe_CosTime.hrl +/cosTime/include/oe_CosTimerEvent.hrl +/cosTime/include/oe_TimeBase.hrl +/cosTime/src/CosTime_TIO.erl +/cosTime/src/CosTime_TimeService.erl +/cosTime/src/CosTime_TimeUnavailable.erl +/cosTime/src/CosTime_UTO.erl +/cosTime/src/CosTimerEvent_TimerEventHandler.erl +/cosTime/src/CosTimerEvent_TimerEventService.erl +/cosTime/src/CosTimerEvent_TimerEventT.erl +/cosTime/src/TimeBase_IntervalT.erl +/cosTime/src/TimeBase_UtcT.erl +/cosTime/src/oe_CosTime.erl +/cosTime/src/oe_CosTimerEvent.erl +/cosTime/src/oe_TimeBase.erl +/cosTransactions/include/CosTransactions.hrl +/cosTransactions/include/CosTransactions_Control.hrl +/cosTransactions/include/CosTransactions_Coordinator.hrl +/cosTransactions/include/CosTransactions_RecoveryCoordinator.hrl +/cosTransactions/include/CosTransactions_Resource.hrl +/cosTransactions/include/CosTransactions_SubtransactionAwareResource.hrl +/cosTransactions/include/CosTransactions_Terminator.hrl +/cosTransactions/include/CosTransactions_TransactionFactory.hrl +/cosTransactions/include/ETraP.hrl +/cosTransactions/include/ETraP_Server.hrl +/cosTransactions/include/oe_CosTransactions.hrl +/cosTransactions/src/CosTransactions_Control.erl +/cosTransactions/src/CosTransactions_Coordinator.erl +/cosTransactions/src/CosTransactions_HeuristicCommit.erl +/cosTransactions/src/CosTransactions_HeuristicHazard.erl +/cosTransactions/src/CosTransactions_HeuristicMixed.erl +/cosTransactions/src/CosTransactions_HeuristicRollback.erl +/cosTransactions/src/CosTransactions_Inactive.erl +/cosTransactions/src/CosTransactions_InvalidControl.erl +/cosTransactions/src/CosTransactions_NoTransaction.erl +/cosTransactions/src/CosTransactions_NotPrepared.erl +/cosTransactions/src/CosTransactions_NotSubtransaction.erl +/cosTransactions/src/CosTransactions_PropagationContext.erl +/cosTransactions/src/CosTransactions_RecoveryCoordinator.erl +/cosTransactions/src/CosTransactions_Resource.erl +/cosTransactions/src/CosTransactions_SubtransactionAwareResource.erl +/cosTransactions/src/CosTransactions_SubtransactionsUnavailable.erl +/cosTransactions/src/CosTransactions_SynchronizationUnavailable.erl +/cosTransactions/src/CosTransactions_Terminator.erl +/cosTransactions/src/CosTransactions_TransIdentity.erl +/cosTransactions/src/CosTransactions_TransactionFactory.erl +/cosTransactions/src/CosTransactions_Unavailable.erl +/cosTransactions/src/CosTransactions_WrongTransaction.erl +/cosTransactions/src/CosTransactions_otid_t.erl +/cosTransactions/src/ETraP_Server.erl +/cosTransactions/src/oe_CosTransactions.erl +/orber/COSS/CosNaming/CosNaming.hrl +/orber/COSS/CosNaming/CosNaming_Binding.erl +/orber/COSS/CosNaming/CosNaming_BindingIterator.erl +/orber/COSS/CosNaming/CosNaming_BindingIterator.hrl +/orber/COSS/CosNaming/CosNaming_BindingList.erl +/orber/COSS/CosNaming/CosNaming_Name.erl +/orber/COSS/CosNaming/CosNaming_NameComponent.erl +/orber/COSS/CosNaming/CosNaming_NamingContext.erl +/orber/COSS/CosNaming/CosNaming_NamingContext.hrl +/orber/COSS/CosNaming/CosNaming_NamingContextExt.erl +/orber/COSS/CosNaming/CosNaming_NamingContextExt.hrl +/orber/COSS/CosNaming/CosNaming_NamingContextExt_AlreadyBound.erl +/orber/COSS/CosNaming/CosNaming_NamingContextExt_CannotProceed.erl +/orber/COSS/CosNaming/CosNaming_NamingContextExt_InvalidAddress.erl +/orber/COSS/CosNaming/CosNaming_NamingContextExt_InvalidName.erl +/orber/COSS/CosNaming/CosNaming_NamingContextExt_NotEmpty.erl +/orber/COSS/CosNaming/CosNaming_NamingContextExt_NotFound.erl +/orber/COSS/CosNaming/CosNaming_NamingContext_AlreadyBound.erl +/orber/COSS/CosNaming/CosNaming_NamingContext_CannotProceed.erl +/orber/COSS/CosNaming/CosNaming_NamingContext_InvalidName.erl +/orber/COSS/CosNaming/CosNaming_NamingContext_NotEmpty.erl +/orber/COSS/CosNaming/CosNaming_NamingContext_NotFound.erl +/orber/COSS/CosNaming/oe_cos_naming.erl +/orber/COSS/CosNaming/oe_cos_naming.hrl +/orber/COSS/CosNaming/oe_cos_naming_ext.erl +/orber/COSS/CosNaming/oe_cos_naming_ext.hrl +/orber/examples/Stack/StackModule.hrl +/orber/examples/Stack/StackModule_EmptyStack.erl +/orber/examples/Stack/StackModule_Stack.erl +/orber/examples/Stack/StackModule_Stack.hrl +/orber/examples/Stack/StackModule_StackFactory.erl +/orber/examples/Stack/StackModule_StackFactory.hrl +/orber/examples/Stack/oe_stack.erl +/orber/examples/Stack/oe_stack.hrl +/orber/src/CORBA.hrl +/orber/src/OrberApp.hrl +/orber/src/OrberApp_IFR.erl +/orber/src/OrberApp_IFR.hrl +/orber/src/erlang.hrl +/orber/src/erlang_binary.erl +/orber/src/erlang_pid.erl +/orber/src/erlang_port.erl +/orber/src/erlang_ref.erl +/orber/src/oe_CORBA.erl +/orber/src/oe_CORBA.hrl +/orber/src/oe_OrberIFR.erl +/orber/src/oe_OrberIFR.hrl +/orber/src/oe_erlang.erl +/orber/src/oe_erlang.hrl diff --git a/lib/asn1/doc/src/Makefile b/lib/asn1/doc/src/Makefile index be8755f0ff..d29225f6c9 100644 --- a/lib/asn1/doc/src/Makefile +++ b/lib/asn1/doc/src/Makefile @@ -51,9 +51,7 @@ XML_REF3_FILES = asn1ct.xml \ GEN_XML = \ asn1_spec.xml -XML_PART_FILES = \ - part.xml \ - part_notes.xml +XML_PART_FILES = part.xml XML_HTML_FILE = \ notes_history.xml diff --git a/lib/asn1/doc/src/note.gif b/lib/asn1/doc/src/note.gif Binary files differdeleted file mode 100644 index 6fffe30419..0000000000 --- a/lib/asn1/doc/src/note.gif +++ /dev/null diff --git a/lib/asn1/doc/src/notes_history.xml b/lib/asn1/doc/src/notes_history.xml deleted file mode 100644 index e6c423e79e..0000000000 --- a/lib/asn1/doc/src/notes_history.xml +++ /dev/null @@ -1,1782 +0,0 @@ -<?xml version="1.0" encoding="latin1" ?> -<!DOCTYPE chapter SYSTEM "chapter.dtd"> - -<chapter> - <header> - <copyright> - <year>2006</year><year>2009</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - </legalnotice> - - <title>ASN1 Release Notes</title> - <prepared>Bertil Karlsson</prepared> - <responsible></responsible> - <docno></docno> - <approved></approved> - <checked></checked> - <date>06-04-24</date> - <rev></rev> - <file>notes_history.sgml</file> - </header> - <p>This document describes the changes made to the asn1 system - from version to version. The intention of this document is to - list all incompatibilities as well as all enhancements and - bug-fixes for every release of the asn1 application. Each release of asn1 - thus constitutes one section in this document. The title of each - section is the version number of asn1.</p> - - - <section> - <title>Asn1 1.4.4.14</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Data in info/0 in generated code is moved to attribute - asn1_info, thus vsn value remains the same if compiler - options for asn1-spec differs but the generated code is - the same.</p> - <p>Own Id: OTP-6462</p> - </item> - <item> - <p>Dialyzer warnings on asn1 are removed, i.e. dead code - removed.</p> - <p>Own Id: OTP-6506</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.4.13</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Now it is possible to use 'asn1config' and 'inline' - options together. It is also possible to use 'inline' on - a single file like: - <c>asn1ct:compile("MyASN1spec.asn",[inline])</c>.</p> - <p>Own Id: OTP-6405</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.4.12</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>As a complement to the option "{inline,OutputFile}" it is - now possible to use the option "inline". Then asn1 creates - an output file with the name of the source .set file.</p> - <p>Own Id: OTP-6314</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.4.11</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>When compiling an asn1 source that reference a type in - another source the compiler uses the asn1db file of the - other source to resolve the reference. It also tests - whether the other source has been updated since the - asn1db file was generated. This last test was to brutal - in that it exits compilation when no source was found, - even though a asn1db file existed. Changed behavior from - a brutal exit to a warning.</p> - <p>Own Id: OTP-6143</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.4.10</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>asn1 encoding failed on BIT STRING with constraint - <c>(SIZE (32..MAX))</c>.</p> - <p>Own Id: OTP-5932</p> - </item> - <item> - <p>Race condition removed in server for variable names for - generated code.</p> - <p>Own Id: OTP-6111</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.4.9</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Now exists a default function clause for table lookup of - a table constraint. This causes a nice error instead of a - crash. Did also remove some obsolete funs ({Mod,Fun}) in - generated code.</p> - <p>Own Id: OTP-5783</p> - </item> - <item> - <p>ASN1-compiler failed to derive a value out of an external - reference in some certain cases, when compiling specs so - that the spec with the reference was compiled before the - spec with the defined value.</p> - <p>Own Id: OTP-5812 Aux Id: seq10133 </p> - </item> - <item> - <p>The documentation of how records of embedded types are - named is extended and made clearer by examples and rules. - The section "Naming of Records in .hrl Files" in the - User's Guide is added.</p> - <p>Own Id: OTP-5831 Aux Id: seq10133 </p> - </item> - <item> - <p>The compiler failed to give right name to record/function - of a parameterized type that was referenced through - another instance of a parameterized type in another - module. The fault occurred when modules were compiled in a - certain order. Now the compiler resolves the name - correctly.</p> - <p>Own Id: OTP-5832 Aux Id: seq10133 </p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.4.8</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The dynamic sort of SET OF values now correctly handles - values encoded in the "ber_bin, der, optimize" mode, the - value of a SET OF is a list of binaries.</p> - <p>Own Id: OTP-5687</p> - </item> - <item> - <p>Bad code was generated for an INTEGER with value-range. If - the value that was encoded had a lower bound with - negative value it caused a crash. This bug is now - removed.</p> - <p>Own Id: OTP-5688 Aux Id: seq10049 </p> - </item> - <item> - <p>Compiler now handles wrong include paths by returning an - error if a referenced module is not available.</p> - <p>Own Id: OTP-5689</p> - </item> - <item> - <p>The bug causing a runtime error when encoding a type - defined by: <c>BIT STRING {a(1),b(2)}</c> with the value - [] in <c>per_bin</c> mode is now removed.</p> - <p>Own Id: OTP-5710 Aux Id: seq10066 </p> - </item> - </list> - </section> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Better handling of filename paths</p> - <p>Own Id: OTP-5701</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.4.7</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Effective constraint for <c>per</c> now corrected. For - instance <c>INTEGER (0|15..269)</c> didn't work properly.</p> - <p>Own Id: OTP-5477 Aux Id: OTP-5511 </p> - </item> - <item> - <p>Adjusted compiler so that functions in generated code - only are exported once.</p> - <p>Own Id: OTP-5509</p> - </item> - <item> - <p>Fixed the compiler failure when handling a value range - constraint with an extension mark that had the Lower - bound and/or Upper bound values as an external reference - to a defined value.</p> - <p>Own Id: OTP-5511 Aux Id: OTP-5466 </p> - </item> - <item> - <p>Removed sorting of elements for SEQUENCE OF. It shall - only be done in SET OF.</p> - <p>Own Id: OTP-5602</p> - </item> - <item> - <p>Corrected code that generated code causing badarith - warning.</p> - <p>Own Id: OTP-5616</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.4.6</title> - - <section> - <title>Known Bugs and Problems</title> - <list type="bulleted"> - <item> - <p>Compiler now correctly crashes when compiling bad values. - Failed for instance on INTEGER value that was a reference - to a defined value. Also solved problem with a union - constraint on an INTEGER.</p> - <p>Own Id: OTP-5457</p> - </item> - <item> - <p>Additional coverage of object set syntax.</p> - <p>Own Id: OTP-5466</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.4.5</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>A bug due to representation of open_type values is now - fixed. It could cause problem if one used the EXTERNAL - type.</p> - <p>Own Id: OTP-5302</p> - </item> - <item> - <p>Due to an internal error the same code could have been - generated more than one time. This happened for the - exclusive decode functionality.</p> - <p>Own Id: OTP-5378</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.4.4</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Empty objects caused problems. There was trouble when an - object set referenced imported objects that in turn - referenced imported types. Lacked support of - SelectionType in object. All these have been attended.</p> - <p>Own Id: OTP-5240</p> - </item> - </list> - </section> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Now it is possible to inline asn1 run-time functionality - in the module generated by the asn1 compiler. Thus, it - will be only one module doing all encoding/decoding.</p> - <p>Own Id: OTP-5243</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.4.3</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>A class that was referenced in two steps caused a - compiler failure. It is now corrected.</p> - <p>Own Id: OTP-5103</p> - </item> - </list> - </section> - - <section> - <title>Improvements and new features</title> - <list type="bulleted"> - <item> - <p>Optionally make it possible to get the un-decoded rest along with - the return value. Compile with option <em>undec_rest</em>.</p> - <p>Own Id: OTP-5104</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.4.2</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>An error due to unchecked referenced imported type resulted - in missing tag in some table constraint cases. This error is - now corrected. Error occurred during decode in - <c>ber_bin optimized</c> version.</p> - <p>Own Id: OTP-5022</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.4.1</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>When a referenced value in another module in turn referenced a - defined value the compilation crashed. This is due to the new - routines for compilation, that external references are resolved - during compilation, and not by the order in which modules are - compiled. This error is now corrected.</p> - <p>Own Id: OTP-4970</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.4</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>Functionality for parameterized class is added. Parsing failures on - WithSyntax spec is corrected.</p> - <p>Own Id: OTP-4893</p> - </item> - <item> - <p>The failure due to Parameterized Type when parameter is an object - set is corrected.</p> - <p>Own Id: OTP-4894</p> - <p>Aux Id: OTP-4893</p> - </item> - <item> - <p>Object Identifier values with two components and the first was a - value reference failed due to parsing conflicts. Now it is - corrected.</p> - <p>Own Id: OTP-4895</p> - </item> - <item> - <p>The erroneous comparison of file name and asn1 module name could - cause compilation failure. The situation for this failure is rare, - it requires that other processes modifies the compiled file during - the compilation procedure. It is now fixed.</p> - <p>Own Id: OTP-4944</p> - <p>Aux Id: seq8429</p> - </item> - <item> - <p>Selective decode was ignored when exclusive decode spec in asn1 - configfile was missing. Selective decode failed when the selected - type was the top type. These bugs are now removed.</p> - <p>Own Id: OTP-4953</p> - <p>Aux Id: seq8436</p> - </item> - <item> - <p>The test interface asn1ct:test/1,2,3 and asn1ct:value/2 failed for - open type and EXTERNAL. The bug is now removed.</p> - <p>Own Id: OTP-4955</p> - <p>Aux Id: seq8438)</p> - </item> - <item> - <p>Two equal functions were generated for two components referencing - the same type when they were picked by the action "parts". The bug - is now fixed.</p> - <p>Own Id: OTP-4957</p> - <p>Aux Id: seq8434</p> - </item> - </list> - </section> - - <section> - <title>Improvements and new features</title> - <list type="bulleted"> - <item> - <p>INTEGER with named number list and ENUMERATED can now be sub - constrained with names from the names list.</p> - <p>Own Id: OTP-4917</p> - </item> - <item> - <p>Now there is support for SelectionType (X 680 section 29)</p> - <p>Own Id: OTP-4918</p> - </item> - <item> - <p>The compiler now resolves circular dependencies. When asn1 specs - IMPORTS from each other so that there are circular dependencies.</p> - <p>Own Id: OTP-4919</p> - </item> - <item> - <p>Now is the asn1 type UTF8String supported. For user instructions - see documentation.</p> - <p>Own Id: OTP-4965</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.3.1</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The <c>{internal_error,...,{ unrecognized_type,...}}</c> - error occurring for a SET type when compiling with options - <c>[ber_bin,optimize,der]</c> is now corrected.</p> - <p>Own Id: OTP-4866</p> - </item> - <item> - <p>False encode of BIT STRING in PER (per_bin,optimize) is fixed. The error occurred when there was a type like BIT STRING (SIZE(C)) and C > 16.</p> - <p>Own Id: OTP-4869</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.3</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>Functionality to handle parameterized object sets have been added.</p> - <p>Own Id: OTP-4832</p> - </item> - <item> - <p>Bug causing duplicated function definitions using exclusive decode is removed.</p> - <p>Own Id: OTP-4833)</p> - </item> - <item> - <p>The race condition when loading asn1 driver is solved.</p> - <p>Own Id: OTP-4835</p> - </item> - </list> - </section> - - <section> - <title>Improvements and new features</title> - <list type="bulleted"> - <item> - <p>A specialized decode, <em>selective decode</em> is now available. It decodes a chosen internal sub-type of a constructed type.</p> - <p>Own Id: OTP-4856)</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.2.2</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>Release of Asn1 1.4.2.1 on R7B, The functionality is the same, but - the layer between the driver and the asn1 erlang code is different.</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.2.1</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>ObjectDescriptor does now work as part of a sequence, set or choice.</p> - <p>Own Id: OTP-4773</p> - </item> - <item> - <p>When a SEQUENCE that have extension mark was decoded inside a - SEQUENCE OF it could cause decode error due to a failure in - restbytes2. It is now corrected.</p> - <p>Own Id: OTP-4791)</p> - </item> - <item> - <p>Now the bug is fixed that caused the compiler crash on an untagged - optional open type.</p> - <p>Own Id: OTP-4792</p> - </item> - <item> - <p>The earlier exit caused by bad in-data is now fixed so it will - return an {error,Reason} tuple.</p> - return an {error,Reason} tuple.</p> - <p>Own Id: OTP-4797</p> - </item> - <item> - <p>Open type encoded with indefinite length is now correct decoded.</p> - <p>Own Id: OTP-4798</p> - </item> - <item> - <p>Now is absent optional open types handled correctly.</p> - <p>Own Id: OTP-4799</p> - </item> - <item> - <p>Now is the necessary functions available for sorting in run-time of - SET and SET OF components.</p> - <p>Own Id: OTP-4809</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.2</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>When a component in a SEQUENCE is a CHOICE (or reference to a CHOICE) - and the SEQUENCE's component and one of the alternatives in the CHOICE - have identical names, an error may occur if one doesn't use the - 'optimized' versions of the compiler. In the older versions (<c>ber, ber_bin, per, per_bin</c>) one could optionally apply a value of a - component as <c>{ComponentName,Value}</c>, and the generated code - chooses the second element of the tuple. However, a value of a CHOICE - must be applied as a tuple: <c>{AlternativeName,Value}</c>. Thus, - in the rare case described above and if the value to the SEQUENCE's - component is not in a tuple notation the - <c>{AlternativeName,Value}</c> will be peeled off in the SEQUENCE - and the value fed to the CHOICE will only be the <c>Value</c> - part of <c>{AlternativeName,Value}</c>, and the encoder crashes. - The best way to avoid this is to use the optimized version of the - compiler where the unnecessary tuple notation - <c>{ComponentName,Value}</c> no longer is allowed. Since it isn't - possible to solve this bug in the compiler.</p> - <p>Own Id: OTP-4693</p> - </item> - </list> - </section> - - <section> - <title>Improvements and new features</title> - <list type="bulleted"> - <item> - <p>Exclusive decode is enabled by a compiler option and a configuration - file. It makes it possible to leave parts of an ASN.1 encoded message - un-decoded.</p> - <p>Own Id: OTP-4744</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.1.1</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>The documentation about how extensibility is handled is now corrected.</p> - <p>Own Id: OTP-4663</p> - </item> - <item> - <p>Function in object now calls the exported function</p> - <p>Own Id: OTP-4665</p> - </item> - <item> - <p>Now is tags for ObjectClassFieldType analyzed correctly.</p> - <p>Own Id: OTP-4666</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4.1</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>Now is the Default value for an ENUMERATED returned as the name from - the NamedList when decoding.</p> - <p>Own Id: OTP-4633</p> - </item> - <item> - <p>It was an internal failure when permitted alphabet constraint existed - together with for instance a size constraint. E.g. when a - referenced type is constrained by a size constraint and the defined - type in turn is constrained by a permitted alphabet constraint.</p> - <p>Own Id: OTP-4559</p> - </item> - <item> - <p>Record is generated in hrl file for a CHOICE with extension mark - that has an internal SEQUENCE/SET definition.</p> - <p>Own Id: OTP-4560</p> - </item> - <item> - <p>Now is the length of a SEQUENCE/SET OF correctly encoded/decoded (PER).</p> - <p>Own Id: OTP-4590</p> - </item> - <item> - <p>The problem with unordered decoded terms when a component is a - ObjectClassFieldType has been solved.</p> - <p>Own Id: OTP-4591</p> - </item> - </list> - </section> - - <section> - <title>Improvements and new features</title> - <list type="bulleted"> - <item> - <p>More complex definitions with TableConstraints where the SimpleTable - and ComponentRelation are on different levels is now fully - supported.</p> - <p>Own Id: OTP-4631</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.4</title> - - <section> - <title>Fixed errors and malfunctions</title> - </section> - - <section> - <title>Improvements and new features</title> - <list type="bulleted"> - <item> - <p>Each generated .erl file have now a function info/0 that returns - information about the used compiler version and options.</p> - <p>Own Id: OTP-4373</p> - </item> - <item> - <p>When compiling an ASN.1 module the compiler generates an Erlang module - that is compiled by the Erlang compiler. Earlier it was not possible to - add options to the final step, the Erlang compilation. By adding any - option that is not recognized as a specific ASN.1 option it will be - passed to the final step like: <c>erlc +debug_info Mymodule.asn</c> or - <c>asn1ct:compile('Mymodule',[debug_info])</c>.</p> - <p>Own Id: OTP-4491</p> - </item> - <item> - <p>Earlier one couldn't multi file compile modules that had different - tagdefault, which now is possible. Equal Type/Value names in different - modules are resolved by renaming (concatenate type name and module - name): If two types with the same name T exist in module A and module B - they will get the new names TA and TB.</p> - <p>(Own Id: OTP-4492)</p> - <p>Aux Id: OTP-3983</p> - </item> - <item> - <p>BER: Encode/decode of data have been significantly improved. By use of - the compiler options <c>ber_bin</c> and <c>optimize</c>, - optimized code will be generated and the optimized run-time module will - be used.</p> - <p>Own Id: OTP-4493</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.3.3.1</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>Proper length encoding and padding implemented for a <c>BIT STRING</c> with - NamedNumberList and size constraint as value range. This functionality - didn't work in the rare occasion when the NamedNumberList is shorter - than the lower bound of the constraint.As in this example: - <c>TestS ::= BIT STRING {a (0),b (1)} (SIZE (3..8))</c></p> - <p>(Own Id: OTP-4353)</p> - </item> - <item> - <p>Bug in compiler, when an <c>OBJECT IDENTIFIER</c> value consisting of - two identifiers (Defined values or Name form identifiers) was falsely - interpreted causing a compiling error is now corrected.</p> - <p>(Own Id: OTP-4354)</p> - </item> - <item> - <p>Internal error in check phase that caused crash on - <c>ObjectClassFieldType</c> in ber_bin is corrected.</p> - <p>(Own Id: OTP-4390)</p> - </item> - <item> - <p>Tags for open types are handled according to <c>x.680 30.6c</c>, i.e. - open types shall not be tagged <c>IMPLICIT.</c></p> - <p>(Own Id: OTP-4395)</p> - <p>(Aux Id: OTP-4390)</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.3.3</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>Now gives the compiler an appropriate error report when exported - undefined types are detected.</p> - <p>(Own Id: OTP-4129)</p> - </item> - <item> - <p>The type <c>ObjectDescriptor</c> is now supported, previously the - implementation of encode/decode for this rarely used type was - incomplete.</p> - <p>(Own Id: OTP-4161)</p> - <p>(Aux Id: seq7165)</p> - </item> - <item> - <p>In case of per and compact_bit_string the rightmost byte were erroneous - truncated when the rightmost bits of that byte were zeros. This is now - corrected.</p> - <p>(Own Id: OTP-4200)</p> - </item> - <item> - <p>Bad match of return-value from decode_length in skipvalue/3 has now been - fixed.</p> - <p>(Own Id: OTP-4232)</p> - </item> - <item> - <p>Now is decode of ENUMERATED handled correctly, when tagged EXPLICIT.</p> - <p>(Own Id: OTP-4234)</p> - </item> - <item> - <p>The compiler now parses and handles the ValueFromObject construct.</p> - <p>(Own Id: OTP-4242)</p> - </item> - <item> - <p>Now does the compiler handle the case when the object set in simple - table and componentrelation constraints is of a CLASS without a UNIQUE - field. In this case is the octets, which is assumed to be encoded, - encoded as an open type.</p> - <p>(Own Id: OTP-4248)</p> - <p>(Aux Id: OTP-4242)</p> - </item> - <item> - <p>Compiler handles objects in AdditionalElementSetSpec in ObjectSetSpec, - i.e. the objects that are referred to after the ellipses in an object set.</p> - <p>(Own Id: OTP-4275)</p> - </item> - <item> - <p>Now are values with a component of type CHOICE encoded with indefinite - length correctly decoded.</p> - <p>(Own Id: OTP-4358)</p> - </item> - </list> - </section> - - <section> - <title>Improvements and new features</title> - <list type="bulleted"> - <item> - <p>The language constructs (from the old 1988 standard) <c>ANY</c> - and <c>ANY DEFINED BY</c> are now implemented.</p> - <p>(Own Id: OTP-2741)</p> - <p>(Aux Id: seq 1188)</p> - </item> - <item> - <p>Now it is checked in run-time if a <c>OBJECT IDENTIFIER</c> value is invalid</p> - <p>(Own Id: OTP-4235)</p> - </item> - <item> - <p>The ASN.1 types EXTERNAL,EMBEDDED PDV and CHARACTER STRING now have full support in the compiler.</p> - <p>(Own Id: OTP-4247)</p> - </item> - <item> - <p>A driver in C does the final job (complete) of the PER encoding when - files are compiled with <c>per_bin</c> and <c>optimize</c> flags. - It gives significant faster encoding for PER.</p> - <p>(Own Id: OTP-4355)</p> - </item> - <item> - <p>Encode and decode of PER encoding has been made faster by moving - analysis done in run-time to compile-time. These optimizations are - available by compiling ASN.1 files with options <c>per_bin</c> and - <c>optimize</c>.</p> - <p>(Own Id: OTP-4381)</p> - <p>(Aux Id: OTP-4355)</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.3.2</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>Now does the compiler check values (including referenced values), and - formats the value so it is suitable to use as input to encoding - functions.</p> - <p>(Own Id: OTP-3277)</p> - <p>(Aux Id: OTP-4103)</p> - </item> - <item> - <p>Unnecessary external function calls in generated code are now generated - as internal function calls.</p> - <p>(Own Id: OTP-4073)</p> - </item> - </list> - </section> - - <section> - <title>Improvements and new features</title> - <list type="bulleted"> - <item> - <p>Now is Information Objects supported in BER encoding.</p> - <p>(Own Id: OTP-3980)</p> - <p>(Aux Id: OTP-3979 OTP-3978)</p> - <p></p> - </item> - <item> - <p>PER: A new option <c>per_bin</c> is now supported. When used the - generated encode/decode functions use binaries and the bit syntax to - get better performance than the old <c>per</c> variant which used - lists. All values input to encode and returned from decode are - compatible between <c>per</c> and <c>per_bin</c> except for - open types which are represented as binaries with per_bin and octet - lists with per. We recommend that you use per_bin instead of per from - now on, the use of binaries will be the default in coming versions and - all improvements and optimizations for PER will be concentrated to that - solution.</p> - <p>(Own Id: OTP-4094)</p> - <p></p> - </item> - <item> - <p>Support for DER implemented. Used by flag +der when compiling. Include - the full BER encoding plus: sorting of SET components, sorting of - encoded elements in SET OF, full check of default values in SET and - SEQUENCE. See new documentation on DER in user_guide sections 1.3.1; - 1.4.11; 1.4.12; 1.4.14; 1.4.16 and 1.10, in the reference manual for - asn1ct.</p> - <p>(Own Id: OTP-4103)</p> - <p></p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.3.1</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>Do not generate record in .hrl file for SET types</p> - <p>Own Id: OTP-4025</p> - </item> - <item> - <p>Fixed internal error when using BIT STRINGs with Named Number List in combination with <c>compact_bit_string</c> and <c>ber_bin</c> options.</p> - <p>Own Id: OTP-4026</p> - <p>Aux Id: OTP-3982</p> - </item> - <item> - <p>The atom 'com' can now be used in ENUMERATED as an EnumerationItem.</p> - <p>Own Id: OTP-4037</p> - <p>Aux Id: Seq 7036</p> - </item> - <item> - <p>ber: Now it is possible (again) to encode data format "{Type,Value}" in a SEQUENCE OF RequestParameter, when RequestParameter is of type ENUMERATED. The {Type,Value} - notation is not recommended for use, it is redundant and exist only for very ancient backwards compatibility reasons. The "feature" might be removed in forthcoming versions.</p> - <p>Own Id: OTP-4057</p> - <p>Aux Id: Seq 7066</p> - </item> - <item> - <p>A bug in the parser, that caused failure on COMPONENTS OF is now removed.</p> - <p>Own Id: OTP-4058</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.3</title> - - <section> - <title>Known problems</title> - <list type="bulleted"> - <item> - <p>The compiler will now check that a value referenced by name - does exist.</p> - <p>Own Id: OTP-3277</p> - </item> - <item> - <p>BER:Decode of a type T ::= SEQUENCE OF C fails if C is encoded with indefinite length. - This is know corrected.</p> - <p>Own Id: OTP-3811</p> - <p>Aux Id: seq5040</p> - </item> - </list> - </section> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>The new parser handles imports when one import ends with FROM, a modulename and a reference to a objectidentifier followed by imports from other modules.</p> - <p>Own Id: OTP-3463</p> - </item> - <item> - <p>The compiler did not check that a name mentioned as EXPORTED - actually is defined within the module. - This is now corrected.</p> - <p>Own Id: OTP-3659</p> - </item> - <item> - <p>Removed bug caused by use of nested indefinite length</p> - <p>Own Id: OTP-3994</p> - </item> - </list> - </section> - - <section> - <title>Improvements and new features</title> - <list type="bulleted"> - <item> - <p>Now supporting most common use of parameterization according to X.683</p> - <p>(Own Id: OTP-3978)</p> - </item> - <item> - <p>PER: Now supporting most common use of Information Objects according to X.681. A new parser has been implemented. The error messages due to syntax errors are slightly different than previous. TableConstraint part of X.682 now also supported.</p> - <p>Own Id: OTP-3979</p> - </item> - <item> - <p>New compiler option added: <c>ber_bin</c>. The compiler generates code with new bit syntax. Run time functions uses bit syntax when feasible. Higher encoding/decoding performance in most cases. Se also comments for Asn1 1.2.9.3.</p> - <p>Own Id: OTP-3981</p> - </item> - <item> - <p>A more compact format of BIT STRING in Erlang is now available by use of the compiler option <c>compact_bit_string</c>. It is much faster when large BIT STRINGs are used.</p> - <p>Own Id: OTP-3982</p> - </item> - <item> - <p>Now possible to merge many ASN.1 input files to one Erlang file by use of a configuration file that lists the ASN.1 files.</p> - <p>Own Id: OTP-3983</p> - </item> - <item> - <p>New documentation in <em>User's Guide</em> in section:</p> - <p>3.1: New compile-time functions and options are described.</p> - <p>4.6: New compact format of BIT STRING is described.</p> - <p>4.8: Additional comments on character strings.</p> - <p>7: New section describing ASN.1 Information Objects.</p> - <p>8: New section describing Parameterization.</p> - <p><em>Reference Manual/asn1ct</em> New compile options are described.</p> - <p>Own Id: OTP-3984</p> - <p>Aux Id: OTP-3978, OTP-3979, OTP-3981, OTP-3982, OTP-3983</p> - </item> - <item> - <p>Added the functionality to invoke ASN1Mod:encode (and decode).</p> - <p>Own Id: OTP-3985</p> - </item> - <item> - <p>Performance improvements by removing not necessary use of apply when calling asn1rt:encode. Also other general improvements.</p> - <p>Own Id: OTP-3988</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.2.9.6</title> - - <section> - <title>Known problems</title> - <list type="bulleted"> - <item> - <p>The compiler does not check that an exported name actually exists in the ASN.1 module.</p> - <p>Own Id: OTP-3659</p> - </item> - <item> - <p>The compiler does not check that a value referenced by name does exist.</p> - <p>Own Id: OTP-3277</p> - </item> - <item> - <p>BER: The compiler does not take the extensions into account when checking if - the tags are unique in a SEQUENCE or SET.</p> - <p>Own Id: OTP-3304</p> - </item> - </list> - </section> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>PER: Trailing zeroes in a BIT STRING declared without named bits - should not be removed in the encodings.</p> - <p>Own Id: OTP-3830</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.2.9.5</title> - - <section> - <title>Known problems</title> - <p>Same as for 1.2.9.3.</p> - </section> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>PER: Constraints are not propagated when types are - referring to each other. Example:</p> - <code type="none"> - - TBCD-STRING ::= OCTET STRING - - LAI ::= TBCD-STRING (SIZE(3)) </code> - <p>The size constraint is not passed on during encode,decode - resulting in wrong encoding for PER , it is - coded with a length determinant which should not be there - when the length is fixed. For BER this does not matter because the constraints does - not affect the encodings.</p> - <p>Own Id: OTP-3713</p> - </item> - <item> - <p>The generated code gets wrong if there are several ENUMERATED fields in a SEQUENCE or SET, this is now corrected.</p> - <p>Own Id: OTP-3796</p> - </item> - <item> - <p>BER:Decode of a type T ::= SEQUENCE OF C fails if C is encoded with indefinite length. - This is know corrected.</p> - <p>Own Id: OTP-3811</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.2.9.3</title> - - <section> - <title>Known problems</title> - <list type="bulleted"> - <item> - <p>The compiler does not check that an exported name actually exists in the ASN.1 module.</p> - <p>Own Id: OTP-3659</p> - </item> - <item> - <p>The compiler does not check that a value referenced by name does exist.</p> - <p>Own Id: OTP-3277</p> - </item> - <item> - <p>BER: The compiler does not take the extensions into account when checking if - the tags are unique in a SEQUENCE or SET.</p> - <p>Own Id: OTP-3304</p> - </item> - </list> - </section> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>This version supports soft upgrade from versions 1.2.6 1.2.7.</p> - </item> - <item> - <p>In an ENUMERATED type like this:</p> - <code type="none"> -\011\011T ::= ENUMERATED { blue, green} </code> - <p>The symbols was encoded/decoded with the wrong values, i.e in - reverse order. This is now corrected.</p> - <p>Own Id: OTP-3700</p> - </item> - <item> - <p>PER: OCTET STRING with Size constrained to a single value i.e fixed size - was treated wrong during encode and decode. This is now corrected.</p> - <p>Own Id: OTP-3701</p> - </item> - </list> - </section> - - <section> - <title>Improvements and new features</title> - <list type="bulleted"> - <item> - <p>There is now a new compiler option <c>ber_bin</c> available that can be used to - generate encode/decode functions for BER that uses the new "bit-syntax" to - make the functions more efficient. The <c>ber_bin</c> option is used - as an alternative to the <c>ber</c> and <c>per</c> options.</p> - <p>The encode function then produces a - possibly nested list of binaries and integer lists. The decode function does - in this case require a single binary as input instead of a list. - The modules generated with this option require that you have an R7A or later - system, otherwise they will not compile and the runtime module asn1rt_ber_bin - can not be executed.</p> - <p>The ber_bin option is not officially supported in this version (will be - in a later version) but is provided for those who want to try it. - It should be significantly faster at decode and is slightly faster at encode. - Exactly how performance differs between this binary approach and the - list approach depends highly on the type of input. - Another thing worth noting is that both approaches still have a lot of - solutions in common which can be improved a lot to gain even better - performance.</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.2.9.2</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>BER: Encode/decode of extension components did not work properly. This is now corrected.</p> - <p>Own Id: OTP-3395</p> - <p>Aux Id: </p> - <p>PER:The encode/decode of NULL as an open type has been corrected. An open type must always have a length of at least 1 byte even if the contained - value (e.g NULL) encodes to nothing.</p> - <p>Own Id: OTP-3496</p> - <p>Aux Id: </p> - </item> - <item> - <p>BER:In the current implementation extension components of a SEQUENCE are required - to be present when they are specified as mandatory. This is an error, all extension - components are "optional" even if they are not specified to have the OPTIONAL or - DEFAULT property. This is now corrected.</p> - <p>Own Id: OTP-3278</p> - </item> - </list> - </section> - - <section> - <title>Improvements and new features</title> - <list type="bulleted"> - <item> - <p>The ASN.1 language feature <c>COMPONENTS OF</c> is now implemented.</p> - <p>Own Id: OTP-2515</p> - </item> - <item> - <p>The encoding and decoding of ENUMERATED and - INTEGER with NamedNumbers is made more efficient and thus - faster in runtime.</p> - <p>Own Id: OTP-3464</p> - <p>Aux Id:</p> - </item> - <item> - <p>Added support for encode/decode of open type which is - constrained to a specific type. Previously the value of - an open type had to be a list of octets, but now the Erlang - representation of the specific type used in the constraint - is used both as input to encode and as output from decode.</p> - <p>Own Id: OTP-3569</p> - <p>Aux Id: </p> - </item> - <item> - <p>PER: GeneralString, GraphicalString etc. i.e all strings - that are not so called "known-multiplier character - string types" are now supported by the runtime - encode/decode functions.</p> - <p>Own Id: OTP-3573</p> - <p>Aux Id:</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.2.6</title> - - <section> - <title>Known problems</title> - <list type="bulleted"> - <item> - <p>The ASN.1 language feature <c>COMPONENTS OF</c> is not implemented.</p> - <p>Own Id: OTP-2515</p> - </item> - <item> - <p>The compiler does not check that a value referenced by name does exist.</p> - <p>Own Id: OTP-3277</p> - </item> - <item> - <p>BER:In the current implementation extension components of a SEQUENCE are required - to be present when they are specified as mandatory. This is an error, all extension - components are "optional" even if they are not specified to have the OPTIONAL or - DEFAULT property.</p> - <p>Own Id: OTP-3278</p> - </item> - <item> - <p>BER: The compiler does not take the extensions into account when checking if - the tags are unique in a SEQUENCE or SET.</p> - <p>Own Id: OTP-3304</p> - </item> - </list> - </section> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>This version supports soft upgrade from versions 1.1.1, 1.1.5 and 1.1.6. - Two new runtime modules <c>asn1rt_ber_v1</c> and - <c>asn1rt_per_v1</c> are delivered together with the old ones. This makes - it possible to continue running applications with modules generated with the - previous version of the asn1 compiler while modules generated by this version - will use the new runtime modules. Note that it is only advice-able to continue - running old generates if they are working perfectly and have no need - for the corrections made in this version of the asn1 application.</p> - </item> - <item> - <p>BER: SEQUENCEs encoded with indefinite length was not correctly decoded. - This in now corrected.</p> - <p>Own Id: OTP-3352</p> - <p>Aux Id: Seq 4100</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.2.4</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>The compiler now detects multiple definitions of values and types and reports this as - an error. Previously this was detected when the generated Erlang module was compiled.</p> - <p>Own Id: OTP-3105</p> - </item> - <item> - <p>BER: An error regarding encoding of <c>ENUMERATED</c> present in asn1-1.1.1 - is corrected. The new version 1.1.2 of asn1 containing this correction is - delivered as a "patch".</p> - <p>Own Id: OTP-3169</p> - </item> - <item> - <p>BER: Decoding of <c>SEQUENCE OF</c> and <c>SET OF</c> with indefinite length is corrected. - The correction was first delivered in version 1.1.2.</p> - <p>Own Id: OTP-3170</p> - </item> - <item> - <p>BER: Encoding and decoding of <c>ENUMERATED</c> - with extensionmark - "..." did not work (crashed with a runtime error). This - has now been corrected. If an unknown enumerated value is - decoded (for an extensible enumerated type) - it is returned as <c>{asn1_enum,Value}</c> where - <c>Value</c> is an integer. Enumerated values in this format - are also accepted by the encoder. - ASN.1 modules containing - <c>ENUMERATED</c> with extensionmark should be - recompiled with the corrected - version of the compiler. The BER runtime functions are also - corrected. - Note that this correction has already been delivered as a - bugfix for R4B (OTP-2951).</p> - <p>Own Id: OTP-3202</p> - <p>Aux Id: Seq3745</p> - </item> - <item> - <p>BER: The primitive/constructed bit in the tag byte of an encoding - is not correct when it comes to user defined tags. - For example in </p> - <code type="none"> - T ::= [2] SEQUENCE { a BOOLEAN} </code> - <p>the tag 2 does not get the constructed bit set which it should. - This is now corrected.</p> - <p>Own Id: OTP-3241</p> - </item> - <item> - <p>The decoder can now detect if there are unexpected bytes - remaining when all components of a sequence are decoded. - The decoder will then return <c>{error,{asn1{unexpected,Bytes}}}</c></p> - <p>Own Id: OTP-3270</p> - </item> - <item> - <p>Values of type <c>OBJECT IDENTIFIER</c> was sometimes returned as an Erlang list - (ASN.1 constants) and sometimes as a tuple (from the decode functions). This is now - changed so that <c>OBJECT IDENTIFIER</c> values always are represented as an Erlang - tuple.</p> - <p>Own Id: OTP-3280</p> - </item> - <item> - <p>PER:The encode/decode functions could not handle integers with - a range greater than 16#7ffffff. This limit is now removed.</p> - <p>Own Id: OTP-3287</p> - </item> - <item> - <p>PER: The encoding/decoding of the length for a SET OF/SEQUENCE OF - was wrong if there was a size constraint. This is now corrected.</p> - <p>Own Id: OTP-3291</p> - </item> - <item> - <p>PER: Encoding of a constrained INTEGER (range > 16 k) was wrong for - the value 0. This is now corrected.</p> - <p>Own Id: OTP-3306</p> - </item> - </list> - </section> - - <section> - <title>Improvements and new features</title> - <list type="bulleted"> - <item> - <p>The ASN.1 module name and the filename where the ASN.1 - specification resides must match each other (has always been the - case). This is now checked by the compiler. The check requires that - the names match in a case or case insensitive way depending on the - characteristics for the current system.</p> - <p>Own Id: OTP-1843</p> - </item> - <item> - <p>PER: Encode/decode of an extension value (i.e not within the root set) for - <c>ENUMERATED</c> did not work properly. This is now corrected. - If an unknown enumerated value is - decoded (for an extensible enumerated type) - it is returned as <c>{asn1_enum,Value}</c> where - <c>Value</c> is an integer. Enumerated values in this format - are also accepted by the encoder (if the value is >= the number of known - extension values).</p> - <p>Own Id: OTP-2930</p> - </item> - <item> - <p>Unnecessary printouts from the compiler are removed. - The compiler version and the compiler options are now - printed to stdout.</p> - <p>Own Id: OTP-3276</p> - </item> - <item> - <p>In order to better suite the use of ASN.1 in embedded systems only - the modules needed in runtime are now listed in the <c>.app</c> file.</p> - <p>Own Id: OTP-3279</p> - </item> - <item> - <p>The compiler now supports extensionmarker in constraint specifications. - Example:</p> - <code type="none"> -INTEGER (0..10, ...) </code> - <p>In previous version this was reported as a syntax error.</p> - <p>Own Id: OTP-3281</p> - </item> - <item> - <p>A very limited part of ITU-T recommendation X.681 - Abstract Syntax Notation One (ASN.1): Information - object specification is now implemented. Specifically \011 - TYPE IDENTIFIER is recognized by the compiler.</p> - <p>Own Id: OTP-3325</p> - </item> - <item> - <p>Parameterization of ASN.1 specifications (ITU-T X.683) is now - supported to a limited extent.</p> - <p>Own Id: OTP-3326</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.1.3.1</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>BER Encoding and decoding of <c>ENUMERATED</c> - with extensionmark - "..." did not work (crashed with a runtime error). This - has now been corrected. If an unknown enumerated value is - decoded (for an extensible enumerated type) - it is returned as <c>{asn1_enum,Value}</c> where - <c>Value</c> is an integer. Enumerated values in this format - are also accepted by the encoder. - ASN.1 modules containing - <c>ENUMERATED</c> with extensionmark should be - recompiled with the corrected - version of the compiler. The BER runtime functions are also - corrected. - Note that this correction has already been delivered as a - bug-fix for R4B (OTP-2951).</p> - <p>Own Id: OTP-3202</p> - <p>Aux Id: Seq3745</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.1.1</title> - - <section> - <title>Known problems</title> - <list type="bulleted"> - <item> - <p>The syntactic construct <c>COMPONENTS OF</c> is not - implemented.</p> - <p>Own Id: OTP-2515</p> - </item> - <item> - <p><c>ANY</c> and <c>ANY DEFINED BY</c> are currently not - supported.</p> - <p>Own Id: OTP-2741</p> - <p>Aux Id: seq 1188</p> - </item> - <item> - <p>Multiple definitions of the same Type or Value is not detected - by the compiler. The error occurs when the generated Erlang - module is compiled.</p> - <p>Own Id: OTP-3105</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.1</title> - - <section> - <title>Known problems</title> - <list type="bulleted"> - <item> - <p>The primitive/constructed bit in the tag byte of an encoding - is not correct when it comes to user defined tags. - For example in</p> - <code type="none"> - T ::= [2] SEQUENCE { a BOOLEAN} </code> - <p>the tag 2 does not get the constructed bit set which it should. - This is now corrected.</p> - <p>Own Id: OTP-3241</p> - </item> - </list> - </section> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>The BER decoder failed to decode certain nested data types - where <c>IMPLICIT</c> tags where involved. - This is now corrected.</p> - <p>Own Id: OTP-2719</p> - <p>Aux Id: seq 1148</p> - </item> - <item> - <p>The handling of types with extension marker "..." is corrected. - Earlier each SEQUENCE and SET with an extension marker got an - extra field named <c>asn1_EXT</c> in the generated record. - This was a mistake and that field is now removed (concerns - both BER and BER).</p> - <p>Own Id: OTP-2724</p> - <p>Aux Id: seq 1148, OTP-2719</p> - </item> - <item> - <p>The decoder (both BER and PER) could not handle unnamed - bits of a <c>BIT STRING</c> if the type had any - named bits declared. This is now corrected and the unnamed - bits are returned as <c>{bit,Pos}</c> where Pos is the bit - position. The <c>{bit,Pos}</c> can be used as input to the - encoder too.</p> - <p>Own Id: OTP-2725</p> - <p>Aux Id: seq 1148,OTP-2719,OTP-2724</p> - </item> - <item> - <p>The functions <c>asn1rt:decode</c> and <c>asn1ct:decode</c> - did not always return <c>{ok,Result}</c> or - <c>{error,Reason}</c> as documented. This is now corrected.</p> - <p>Own Id: OTP-2730</p> - <p>Aux Id: seq 1158</p> - </item> - <item> - <p>The compiler did not accept CHOICE types as components - of a SEQUENCE or SET when - the modules tag default was IMPLICIT. - Example:</p> - <code type="none"> -C ::= CHOICE { ......} -A ::= SEQUENCE { -a [1] C, -- This was not accepted -..... </code> - <p>This was an error - caused by a misinterpretation of the ASN.1 standard. This - is now corrected.</p> - <p>Own Id: OTP-2731</p> - <p>Aux Id: seq 1163</p> - </item> - <item> - <p>When decoding a SEQUENCE A which contains an OPTIONAL component - b which is a SEQUENCE with mandatory components, the decoder - does not detect as an error that a mandatory component of b - is missing. The same error could occur also in other cases - with nested types and optional components of SEQUENCE or SET. - This is now corrected.</p> - <p>Own Id: OTP-2738</p> - <p>Aux Id: seq 1183</p> - </item> - <item> - <p>BER Encoding and decoding of <c>ENUMERATED</c> - with extensionmark - "..." did not work (crashed with a runtime error). This - has now been corrected. If an unknown enumerated value is - decoded (for an extensible enumerated type) - it is returned as <c>{asn1_enum,Value}</c> where - <c>Value</c> is an integer. Enumerated values in this format - are also accepted by the encoder. - ASN.1 modules containing - <c>ENUMERATED</c> with extensionmark should be - recompiled with the corrected - version of the compiler. The BER runtime functions are also - corrected.</p> - <p>Own Id: OTP-2951</p> - <p>Aux Id: Seq 1446 OTP-2929</p> - </item> - <item> - <p>The compiler does now accept all valid value notations - for the OBJECT IDENTIFIER type. The generated code for - those values is also corrected.</p> - <p>Own Id: OTP-3059</p> - </item> - </list> - </section> - - <section> - <title>Improvements and new features</title> - <list type="bulleted"> - <item> - <p>The code generated for BER is significantly enhanced resulting - in less code and around 300% better performance in runtime - for the encoding of complex ASN.1 values. The performance of - decoding is unchanged.</p> - <p>Own Id: OTP-2806</p> - </item> - </list> - </section> - </section> - - <section> - <title>Asn1 1.0.3</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>The <c>asn1.app</c> file is corrected.</p> - <p>Own Id: OTP-2640</p> - </item> - <item> - <p>The encoding of integers in BER did not comply with the - standard for all values. The values was not encoded - in the minimum number of octets as required. This is - now corrected in the runtime module <c>asn1rt_ber</c>.</p> - <p>Own Id: OTP-2666</p> - </item> - </list> - </section> - - <section> - <title>Improvements and new features</title> - <list type="bulleted"> - <item> - <p>The compiler now generates explicit exports directives for - all generated - functions that should be exported (instead of -compile(export_all)). - This eliminates the warnings from the Erlang compiler when - compiling the - generated file.</p> - <p>Own Id: OTP-1845</p> - </item> - </list> - </section> - </section> - - <section> - <title>R3B02 (Asn1 1.0.2)</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>The decoding of a BER encoded SEQUENCE with optional component - of type SEQUENCE (also with optional components) could result - in an error or wrong result if the tags are equal.</p> - <p>Own Id: OTP-2226</p> - </item> - <item> - <p>The encoding of (PER) SEQUENCE with extensionmark was wrong. - This is now corrected.</p> - <p>Own Id: OTP-2349</p> - </item> - </list> - </section> - </section> - - <section> - <title>R3A (Asn1 0.9)</title> - - <section> - <title>Fixed errors and malfunctions</title> - <list type="bulleted"> - <item> - <p>The asn1 compiler now detects the use of an implicit tag before <c>CHOICE</c> as an error (in accordance with the standard)</p> - <p>Own Id: OTP-1844</p> - </item> - <item> - <p>An OPTIONAL CHOICE embedded in SEQUENCE when BER coding - caused an error when generating decode code. This is now - corrected.</p> - <p>Own Id: OTP-1857</p> - <p>Aux Id: OTP-1848</p> - </item> - </list> - </section> - </section> - - <section> - <title>1 ASN1 0.8.1</title> - <p>This is the first release of the ASN1 application. This version is - released for beta-testing. Some functionality will be added until the - 1.0 version is released. See the release notes for the latest version - for the exact details about new features. A list of missing features - and restrictions can be found in the chapter below.</p> - - <section> - <title>1.1 Missing features and other restrictions</title> - <p></p> - <list type="bulleted"> - <item> - <p>The encoding rules BER and PER (aligned) is supported. <em>PER (unaligned) IS NOT SUPPORTED</em>.</p> - </item> - <item> - <p>NOT SUPPORTED types <c>ANY</c> and <c>ANY DEFINED BY</c> - (is not in the standard any more).</p> - </item> - <item> - <p>NOT SUPPORTED types <c>EXTERNAL</c> and <c>EMBEDDED-PDV</c>. </p> - </item> - <item> - <p>NOT SUPPORTED type <c>REAL</c> (planned to be implemented). </p> - </item> - <item> - <p>The code generation support for value definitions in the ASN.1 notation is very limited - (planned to be enhanced).</p> - </item> - <item> - <p>The support for constraints is limited to:</p> - </item> - </list> - <list type="bulleted"> - <item> - <p>SizeConstraint SIZE(X)</p> - </item> - <item> - <p>SingleValue (1)</p> - </item> - <item> - <p>ValueRange (X..Y)</p> - </item> - <item> - <p>PermittedAlpabet FROM (but not for BMPString and UniversalString when generating PER).</p> - </item> - <item> - <p>Complex expressions in constraints is not supported (planned to be extended).</p> - </item> - <item> - <p>The current version of the compiler has very limited error checking:</p> - </item> - <item> - <p>Stops at first syntax error.</p> - </item> - <item> - <p>Does not stop when a reference to an undefined type is found , - but prints an error message. Compilation of the generated - Erlang module will then fail.</p> - </item> - <item> - <p>A whole number of other semantical controls is currently - missing. This means that the compiler will give little - or bad help to detect what's wrong with an ASN.1 - specification, but will mostly work very well when the - ASN.1 specification is correct.</p> - </item> - </list> - <list type="bulleted"> - <item> - <p>The maximum INTEGER supported in this version is a - signed 64 bit integer. This limitation is probably quite - reasonable. (Planned to be extended).</p> - </item> - <item> - <p>Only AUTOMATIC TAGS supported for PER.</p> - </item> - <item> - <p>Only EXPLICIT and IMPLICIT TAGS supported for BER.</p> - </item> - <item> - <p>The compiler supports decoding of BER-data with indefinite - length but it is not possible to produce data with indefinite - length with the encoder.</p> - </item> - </list> - </section> - </section> -</chapter> - diff --git a/lib/asn1/doc/src/part_notes.xml b/lib/asn1/doc/src/part_notes.xml deleted file mode 100644 index b0a6887aa5..0000000000 --- a/lib/asn1/doc/src/part_notes.xml +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="latin1" ?> -<!DOCTYPE part SYSTEM "part.dtd"> - -<part xmlns:xi="http://www.w3.org/2001/XInclude"> - <header> - <copyright> - <year>2004</year><year>2009</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - </legalnotice> - - <title>Asn1 Release Notes</title> - <prepared>Ingela Anderton Andin</prepared> - <docno></docno> - <date>>2004-09-07</date> - <rev></rev> - <file>part_notes.sgml</file> - </header> - <description> - <p>The <em>Asn1</em> application - contains modules with compile-time and run-time support for ASN.1.</p> - <p>There are also release notes for - <url href="notes_history.html">older versions</url>.</p> - </description> - <xi:include href="notes.xml"/> -</part> - diff --git a/lib/asn1/doc/src/warning.gif b/lib/asn1/doc/src/warning.gif Binary files differdeleted file mode 100644 index 96af52360e..0000000000 --- a/lib/asn1/doc/src/warning.gif +++ /dev/null diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl index 90d25d87b2..497c4fa07b 100644 --- a/lib/compiler/src/beam_asm.erl +++ b/lib/compiler/src/beam_asm.erl @@ -150,7 +150,7 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, Abst, SourceFile, Opts) -> %% Create IFF chunk. Chunks = case member(slim, Opts) of - true -> [Essentials,AttrChunk,CompileChunk,AbstChunk]; + true -> [Essentials,AttrChunk,AbstChunk]; false -> [Essentials,LocChunk,AttrChunk,CompileChunk,AbstChunk] end, build_form(<<"BEAM">>, Chunks). diff --git a/lib/compiler/src/beam_bool.erl b/lib/compiler/src/beam_bool.erl index d8c201a194..dcc6ad4c7c 100644 --- a/lib/compiler/src/beam_bool.erl +++ b/lib/compiler/src/beam_bool.erl @@ -123,6 +123,12 @@ bopt_block(Reg, Fail, OldIs, [{block,Bl0}|Acc0], St0) -> throw:mixed -> failed; + %% There was a reference to a boolean expression + %% from inside a protected block (try/catch), to + %% a boolean expression outside. + throw:protected_barrier -> + failed; + %% The 'xor' operator was used. We currently don't %% find it worthwile to translate 'xor' operators %% (the code would be clumsy). @@ -167,7 +173,7 @@ bopt_block(Reg, Fail, OldIs, [{block,Bl0}|Acc0], St0) -> %% whether the optimized code is guaranteed to work in the same %% way as the original code. %% -%% Throws an exception if the optmization is not safe. +%% Throw an exception if the optimization is not safe. %% ensure_opt_safe(Bl, NewCode, OldIs, Fail, PreceedingCode, St) -> %% Here are the conditions that must be true for the @@ -184,10 +190,10 @@ ensure_opt_safe(Bl, NewCode, OldIs, Fail, PreceedingCode, St) -> %% by the code that follows. %% %% 3. Any register that is assigned a value in the optimized - %% code must be UNUSED or KILLED in the following code. - %% (Possible future improvement: Registers that are known - %% to be assigned the SAME value in the original and optimized - %% code don't need to be unused in the following code.) + %% code must be UNUSED or KILLED in the following code + %% (because the register might be assigned the wrong value, + %% and even if the value is right it might no longer be + %% assigned on *all* paths leading to its use). InitInPreceeding = initialized_regs(PreceedingCode), @@ -304,6 +310,8 @@ dst_regs([{set,[D],_,{bif,_,{f,_}}}|Is], Acc) -> dst_regs(Is, [D|Acc]); dst_regs([{set,[D],_,{alloc,_,{gc_bif,_,{f,_}}}}|Is], Acc) -> dst_regs(Is, [D|Acc]); +dst_regs([{set,[D],_,move}|Is], Acc) -> + dst_regs(Is, [D|Acc]); dst_regs([_|Is], Acc) -> dst_regs(Is, Acc); dst_regs([], Acc) -> ordsets:from_list(Acc). @@ -414,11 +422,10 @@ bopt_good_args([A|As], Regs) -> bopt_good_args([], _) -> ok. bopt_good_arg({Tag,_}=X, Regs) when Tag =:= x; Tag =:= tmp -> - case gb_trees:get(X, Regs) of - any -> ok; - _Other -> - %%io:format("not any: ~p: ~p\n", [X,_Other]), - throw(mixed) + case gb_trees:lookup(X, Regs) of + {value,any} -> ok; + {value,_} -> throw(mixed); + none -> throw(protected_barrier) end; bopt_good_arg(_, _) -> ok. diff --git a/lib/compiler/test/andor_SUITE.erl b/lib/compiler/test/andor_SUITE.erl index 34609a49f2..a460d54239 100644 --- a/lib/compiler/test/andor_SUITE.erl +++ b/lib/compiler/test/andor_SUITE.erl @@ -20,13 +20,14 @@ -export([all/1, t_case/1,t_and_or/1,t_andalso/1,t_orelse/1,inside/1,overlap/1, - combined/1,in_case/1]). + combined/1,in_case/1,before_and_inside_if/1]). -include("test_server.hrl"). all(suite) -> test_lib:recompile(?MODULE), - [t_case,t_and_or,t_andalso,t_orelse,inside,overlap,combined,in_case]. + [t_case,t_and_or,t_andalso,t_orelse,inside,overlap,combined,in_case, + before_and_inside_if]. t_case(Config) when is_list(Config) -> %% We test boolean cases almost but not quite like cases @@ -380,6 +381,65 @@ in_case_1_guard(LenUp, LenDw, LenN, Rotation, Count) -> false -> loop end. +before_and_inside_if(Config) when is_list(Config) -> + ?line no = before_and_inside_if([a], [b], delete), + ?line no = before_and_inside_if([a], [b], x), + ?line no = before_and_inside_if([a], [], delete), + ?line no = before_and_inside_if([a], [], x), + ?line no = before_and_inside_if([], [], delete), + ?line yes = before_and_inside_if([], [], x), + ?line yes = before_and_inside_if([], [b], delete), + ?line yes = before_and_inside_if([], [b], x), + + ?line {ch1,ch2} = before_and_inside_if_2([a], [b], blah), + ?line {ch1,ch2} = before_and_inside_if_2([a], [b], xx), + ?line {ch1,ch2} = before_and_inside_if_2([a], [], blah), + ?line {ch1,ch2} = before_and_inside_if_2([a], [], xx), + ?line {no,no} = before_and_inside_if_2([], [b], blah), + ?line {no,no} = before_and_inside_if_2([], [b], xx), + ?line {ch1,no} = before_and_inside_if_2([], [], blah), + ?line {no,ch2} = before_and_inside_if_2([], [], xx), + ok. + +%% Thanks to Simon Cornish and Kostis Sagonas. +%% Used to crash beam_bool. +before_and_inside_if(XDo1, XDo2, Do3) -> + Do1 = (XDo1 =/= []), + Do2 = (XDo2 =/= []), + if + %% This expression occurs in a try/catch (protected) + %% block, which cannot refer to variables outside of + %% the block that are boolean expressions. + Do1 =:= true; + Do1 =:= false, Do2 =:= false, Do3 =:= delete -> + no; + true -> + yes + end. + +%% Thanks to Simon Cornish. +%% Used to generate code that would not set {y,0} on +%% all paths before its use (and therefore fail +%% validation by the beam_validator). +before_and_inside_if_2(XDo1, XDo2, Do3) -> + Do1 = (XDo1 =/= []), + Do2 = (XDo2 =/= []), + CH1 = if Do1 == true; + Do1 == false,Do2==false,Do3 == blah -> + ch1; + true -> + no + end, + CH2 = if Do1 == true; + Do1 == false,Do2==false,Do3 == xx -> + ch2; + true -> + no + end, + {CH1,CH2}. + +%% Utilities. + check(V1, V0) -> if V1 /= V0 -> io:fwrite("error: ~w.\n", [V1]), @@ -393,5 +453,3 @@ echo(X) -> X. id(I) -> I. - - diff --git a/lib/compiler/test/compilation_SUITE_data/on_load.erl b/lib/compiler/test/compilation_SUITE_data/on_load.erl index 92bcf74624..e9b5ec7f34 100644 --- a/lib/compiler/test/compilation_SUITE_data/on_load.erl +++ b/lib/compiler/test/compilation_SUITE_data/on_load.erl @@ -12,7 +12,7 @@ do_on_load() -> local_function(), - true. + ok. local_function() -> ok. diff --git a/lib/cosEvent/doc/src/Makefile b/lib/cosEvent/doc/src/Makefile index 5136c7cfb5..4b76a64b7d 100644 --- a/lib/cosEvent/doc/src/Makefile +++ b/lib/cosEvent/doc/src/Makefile @@ -65,6 +65,9 @@ XML_CHAPTER_FILES = \ BOOK_FILES = book.xml +XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \ + $(XML_PART_FILES) $(XML_CHAPTER_FILES) + TECHNICAL_DESCR_FILES = GIF_FILES = \ diff --git a/lib/cosEvent/doc/src/notes.xml b/lib/cosEvent/doc/src/notes.xml index afd1247b42..8cd7b9dd48 100644 --- a/lib/cosEvent/doc/src/notes.xml +++ b/lib/cosEvent/doc/src/notes.xml @@ -33,6 +33,20 @@ </header> <section> + <title>cosEvent 2.1.8</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The documentation EIX file was not generated.</p> + <p>Own id: OTP-8355 Aux Id:</p> + </item> + </list> + </section> + </section> + + <section> <title>cosEvent 2.1.7</title> <section> diff --git a/lib/cosEvent/vsn.mk b/lib/cosEvent/vsn.mk index 953e5fc8c9..7c908d1c5d 100644 --- a/lib/cosEvent/vsn.mk +++ b/lib/cosEvent/vsn.mk @@ -1,7 +1,9 @@ -COSEVENT_VSN = 2.1.7 +COSEVENT_VSN = 2.1.8 -TICKETS = OTP-8201 +TICKETS = OTP-8355 + +TICKETS_2.1.7 = OTP-8201 TICKETS_2.1.6 = OTP-7987 diff --git a/lib/cosEventDomain/doc/src/Makefile b/lib/cosEventDomain/doc/src/Makefile index 465b726ad1..6a0d3c353a 100644 --- a/lib/cosEventDomain/doc/src/Makefile +++ b/lib/cosEventDomain/doc/src/Makefile @@ -62,6 +62,9 @@ XML_CHAPTER_FILES = \ BOOK_FILES = book.xml +XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \ + $(XML_PART_FILES) $(XML_CHAPTER_FILES) + TECHNICAL_DESCR_FILES = GIF_FILES = \ diff --git a/lib/cosEventDomain/doc/src/ch_event_domain_service.xml b/lib/cosEventDomain/doc/src/ch_event_domain_service.xml index 62378cac91..39ac915b38 100644 --- a/lib/cosEventDomain/doc/src/ch_event_domain_service.xml +++ b/lib/cosEventDomain/doc/src/ch_event_domain_service.xml @@ -97,9 +97,9 @@ ID2 = 'CosEventDomainAdmin_EventDomain':add_channel(ED, Ch2), %% To connect them, we must first define a connection struct: C1 = #'CosEventDomainAdmin_Connection'{supplier_id=ID1, -\011\011\011\011 consumer_id=ID2, -\011\011\011\011 ctype='STRUCTURED_EVENT', -\011\011\011\011 notification_style='Pull'}, + consumer_id=ID2, + ctype='STRUCTURED_EVENT', + notification_style='Pull'}, %% Connect them: 'CosEventDomainAdmin_EventDomain':add_connection(ED, C1), diff --git a/lib/cosEventDomain/doc/src/notes.xml b/lib/cosEventDomain/doc/src/notes.xml index fdfb21c046..0ad42948af 100644 --- a/lib/cosEventDomain/doc/src/notes.xml +++ b/lib/cosEventDomain/doc/src/notes.xml @@ -32,6 +32,24 @@ </header> <section> + <title>cosEventDomain 1.1.8</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Removed superfluous VT in the documentation.</p> + <p>Own id: OTP-8353 Aux Id:</p> + </item> + <item> + <p>The documentation EIX file was not generated.</p> + <p>Own id: OTP-8355 Aux Id:</p> + </item> + </list> + </section> + </section> + + <section> <title>cosEventDomain 1.1.7</title> <section> diff --git a/lib/cosEventDomain/vsn.mk b/lib/cosEventDomain/vsn.mk index 81c0b49143..483b130819 100644 --- a/lib/cosEventDomain/vsn.mk +++ b/lib/cosEventDomain/vsn.mk @@ -1,7 +1,10 @@ -COSEVENTDOMAIN_VSN = 1.1.7 +COSEVENTDOMAIN_VSN = 1.1.8 -TICKETS = OTP-8201 +TICKETS = OTP-8353 \ + OTP-8355 + +TICKETS_1.1.7 = OTP-8201 TICKETS_1.1.6 = OTP-7987 diff --git a/lib/cosFileTransfer/doc/src/Makefile b/lib/cosFileTransfer/doc/src/Makefile index 7769d5ef8c..2286db43ff 100644 --- a/lib/cosFileTransfer/doc/src/Makefile +++ b/lib/cosFileTransfer/doc/src/Makefile @@ -65,6 +65,9 @@ XML_CHAPTER_FILES = \ BOOK_FILES = book.xml +XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \ + $(XML_PART_FILES) $(XML_CHAPTER_FILES) + TECHNICAL_DESCR_FILES = GIF_FILES = \ diff --git a/lib/cosFileTransfer/doc/src/notes.xml b/lib/cosFileTransfer/doc/src/notes.xml index e3b7e4819a..5bb2ea68c4 100644 --- a/lib/cosFileTransfer/doc/src/notes.xml +++ b/lib/cosFileTransfer/doc/src/notes.xml @@ -31,6 +31,20 @@ </header> <section> + <title>cosFileTransfer 1.1.10</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The documentation EIX file was not generated.</p> + <p>Own id: OTP-8355 Aux Id:</p> + </item> + </list> + </section> + </section> + + <section> <title>cosFileTransfer 1.1.9</title> <section> diff --git a/lib/cosFileTransfer/vsn.mk b/lib/cosFileTransfer/vsn.mk index dd92b53904..88786178fb 100644 --- a/lib/cosFileTransfer/vsn.mk +++ b/lib/cosFileTransfer/vsn.mk @@ -1,9 +1,11 @@ -COSFILETRANSFER_VSN = 1.1.9 +COSFILETRANSFER_VSN = 1.1.10 TICKETS = \ - OTP-8201 + OTP-8355 +TICKETS_1.1.9 = OTP-8201 + TICKETS_1.1.8 = OTP-7987 TICKETS_1.1.7 = OTP-7837 diff --git a/lib/cosNotification/doc/src/Makefile b/lib/cosNotification/doc/src/Makefile index 6abcf0ef1d..bfdd2f1f8c 100644 --- a/lib/cosNotification/doc/src/Makefile +++ b/lib/cosNotification/doc/src/Makefile @@ -91,6 +91,9 @@ XML_CHAPTER_FILES = \ BOOK_FILES = book.xml +XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \ + $(XML_PART_FILES) $(XML_CHAPTER_FILES) + TECHNICAL_DESCR_FILES = GIF_FILES = \ diff --git a/lib/cosNotification/doc/src/ch_BNF.xml b/lib/cosNotification/doc/src/ch_BNF.xml index 545280a1f4..73e91e3cac 100644 --- a/lib/cosNotification/doc/src/ch_BNF.xml +++ b/lib/cosNotification/doc/src/ch_BNF.xml @@ -181,7 +181,7 @@ FilterID = 'CosNotifyChannelAdmin_ConsumerAdmin': /* Character set issues */ <Ident> :=<Leader> <FollowSeq> - | \\ < Leader> <FollowSeq> + | \ < Leader> <FollowSeq> <FollowSeq> := /* <empty> */ | <FollowSeq> <Follow> @@ -215,8 +215,8 @@ FilterID = 'CosNotifyChannelAdmin_ConsumerAdmin': | <Other> | <Special> -<Special> := \\\\ - | \\' +<Special> := \\ + | \' <Leader> := <Alpha> diff --git a/lib/cosNotification/doc/src/ch_example.xml b/lib/cosNotification/doc/src/ch_example.xml index 8cb12bd241..14c0e5c6fd 100644 --- a/lib/cosNotification/doc/src/ch_example.xml +++ b/lib/cosNotification/doc/src/ch_example.xml @@ -124,7 +124,7 @@ ChFac = cosNotificationApp:start_factory([]), {AdminSupplier, ASID}= 'CosNotifyChannelAdmin_EventChannel':new_for_suppliers(Ch, 'OR_OP'), {AdminConsumer, ACID}= -\011'CosNotifyChannelAdmin_EventChannel':new_for_consumers(Ch,'OR_OP'), + 'CosNotifyChannelAdmin_EventChannel':new_for_consumers(Ch,'OR_OP'), %% Use the corresponding Admin object to get access to wanted Proxies diff --git a/lib/cosNotification/doc/src/notes.xml b/lib/cosNotification/doc/src/notes.xml index c66be87c7c..29879e95fb 100644 --- a/lib/cosNotification/doc/src/notes.xml +++ b/lib/cosNotification/doc/src/notes.xml @@ -32,6 +32,28 @@ </header> <section> + <title>cosNotification 1.1.13</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Removed superfluous VT in the documentation.</p> + <p>Own id: OTP-8353 Aux Id:</p> + </item> + <item> + <p>Removed superfluous backslash in the documentation.</p> + <p>Own id: OTP-8354 Aux Id:</p> + </item> + <item> + <p>The documentation EIX file was not generated.</p> + <p>Own id: OTP-8355 Aux Id:</p> + </item> + </list> + </section> + </section> + + <section> <title>cosNotification 1.1.12</title> <section> diff --git a/lib/cosNotification/vsn.mk b/lib/cosNotification/vsn.mk index 65f9812f31..fed10ee195 100644 --- a/lib/cosNotification/vsn.mk +++ b/lib/cosNotification/vsn.mk @@ -1,6 +1,10 @@ -COSNOTIFICATION_VSN = 1.1.12 +COSNOTIFICATION_VSN = 1.1.13 -TICKETS = OTP-8201 +TICKETS = OTP-8353 \ + OTP-8354 \ + OTP-8355 + +TICKETS_1.1.12 = OTP-8201 TICKETS_1.1.11 = OTP-7987 diff --git a/lib/cosProperty/doc/src/Makefile b/lib/cosProperty/doc/src/Makefile index 126e05ef53..baf995d35e 100644 --- a/lib/cosProperty/doc/src/Makefile +++ b/lib/cosProperty/doc/src/Makefile @@ -67,6 +67,9 @@ XML_CHAPTER_FILES = \ BOOK_FILES = book.xml +XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \ + $(XML_PART_FILES) $(XML_CHAPTER_FILES) + TECHNICAL_DESCR_FILES = GIF_FILES = \ diff --git a/lib/cosProperty/doc/src/notes.xml b/lib/cosProperty/doc/src/notes.xml index be3a8d0f5e..e80c90849f 100644 --- a/lib/cosProperty/doc/src/notes.xml +++ b/lib/cosProperty/doc/src/notes.xml @@ -32,6 +32,20 @@ </header> <section> + <title>cosProperty 1.1.11</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The documentation EIX file was not generated.</p> + <p>Own id: OTP-8355 Aux Id:</p> + </item> + </list> + </section> + </section> + + <section> <title>cosProperty 1.1.10</title> <section> diff --git a/lib/cosProperty/vsn.mk b/lib/cosProperty/vsn.mk index 0e55352e42..c221e6fa4a 100644 --- a/lib/cosProperty/vsn.mk +++ b/lib/cosProperty/vsn.mk @@ -1,6 +1,8 @@ -COSPROPERTY_VSN = 1.1.10 +COSPROPERTY_VSN = 1.1.11 -TICKETS = OTP-8201 +TICKETS = OTP-8355 + +TICKETS_1.1.10 = OTP-8201 TICKETS_1.1.9 = OTP-7987 diff --git a/lib/cosTime/doc/src/Makefile b/lib/cosTime/doc/src/Makefile index 568e2cd4cc..83abc5e7c2 100644 --- a/lib/cosTime/doc/src/Makefile +++ b/lib/cosTime/doc/src/Makefile @@ -64,6 +64,9 @@ XML_CHAPTER_FILES = \ BOOK_FILES = book.xml +XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \ + $(XML_PART_FILES) $(XML_CHAPTER_FILES) + TECHNICAL_DESCR_FILES = GIF_FILES = \ diff --git a/lib/cosTime/doc/src/notes.xml b/lib/cosTime/doc/src/notes.xml index afa10980e8..9f23a8633c 100644 --- a/lib/cosTime/doc/src/notes.xml +++ b/lib/cosTime/doc/src/notes.xml @@ -33,6 +33,20 @@ </header> <section> + <title>cosTime 1.1.8</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The documentation EIX file was not generated.</p> + <p>Own id: OTP-8355 Aux Id:</p> + </item> + </list> + </section> + </section> + + <section> <title>cosTime 1.1.7</title> <section> diff --git a/lib/cosTime/vsn.mk b/lib/cosTime/vsn.mk index ac5e99a0f1..db51bf39b9 100644 --- a/lib/cosTime/vsn.mk +++ b/lib/cosTime/vsn.mk @@ -1,6 +1,8 @@ -COSTIME_VSN = 1.1.7 +COSTIME_VSN = 1.1.8 -TICKETS = OTP-8201 +TICKETS = OTP-8355 + +TICKETS_1.1.7 = OTP-8201 TICKETS_1.1.6 = OTP-7987 diff --git a/lib/cosTransactions/doc/src/Makefile b/lib/cosTransactions/doc/src/Makefile index eab52d3dc9..1af9ed24b7 100644 --- a/lib/cosTransactions/doc/src/Makefile +++ b/lib/cosTransactions/doc/src/Makefile @@ -68,6 +68,9 @@ XML_CHAPTER_FILES = \ BOOK_FILES = book.xml +XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \ + $(XML_PART_FILES) $(XML_CHAPTER_FILES) + TECHNICAL_DESCR_FILES = GIF_FILES = \ diff --git a/lib/cosTransactions/doc/src/notes.xml b/lib/cosTransactions/doc/src/notes.xml index 953382ef87..41a754b034 100644 --- a/lib/cosTransactions/doc/src/notes.xml +++ b/lib/cosTransactions/doc/src/notes.xml @@ -33,6 +33,20 @@ </header> <section> + <title>cosTransactions 1.2.9</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The documentation EIX file was not generated.</p> + <p>Own id: OTP-8355 Aux Id:</p> + </item> + </list> + </section> + </section> + + <section> <title>cosTransactions 1.2.8</title> <section> diff --git a/lib/cosTransactions/vsn.mk b/lib/cosTransactions/vsn.mk index 404a9ed7af..81e360ac2f 100644 --- a/lib/cosTransactions/vsn.mk +++ b/lib/cosTransactions/vsn.mk @@ -1,6 +1,8 @@ -COSTRANSACTIONS_VSN = 1.2.8 +COSTRANSACTIONS_VSN = 1.2.9 -TICKETS = OTP-8201 +TICKETS = OTP-8355 + +TICKETS_1.2.8 = OTP-8201 TICKETS_1.2.7 = OTP-7987 diff --git a/lib/crypto/c_src/crypto_drv.c b/lib/crypto/c_src/crypto_drv.c index 241c4ec733..5b6d750dde 100644 --- a/lib/crypto/c_src/crypto_drv.c +++ b/lib/crypto/c_src/crypto_drv.c @@ -233,6 +233,11 @@ static ErlDrvEntry crypto_driver_entry = { #define DRV_BF_CFB64_ENCRYPT 59 #define DRV_BF_CFB64_DECRYPT 60 +#define DRV_BF_ECB_ENCRYPT 61 +#define DRV_BF_ECB_DECRYPT 62 +#define DRV_BF_OFB64_ENCRYPT 63 +#define DRV_BF_CBC_ENCRYPT 64 +#define DRV_BF_CBC_DECRYPT 65 /* #define DRV_CBC_IDEA_ENCRYPT 34 */ /* #define DRV_CBC_IDEA_DECRYPT 35 */ @@ -533,6 +538,79 @@ static int crypto_control(ErlDrvData drv_data, unsigned int command, char *buf, (command == DRV_CBC_DES_ENCRYPT)); return dlen; + case DRV_BF_ECB_ENCRYPT: + case DRV_BF_ECB_DECRYPT: + { + /* buf = klen[4] key data */ + int bf_direction; + const unsigned char *ukey; + const unsigned char *bf_dbuf; /* blowfish input data */ + BF_KEY bf_key; /* blowfish key 8 */ + + klen = get_int32(buf); + ukey = (unsigned char *) buf + 4; + bf_dbuf = ukey + klen; + dlen = len - 4 - klen; + if (dlen < 0) return -1; + BF_set_key(&bf_key, klen, ukey); + bin = return_binary(rbuf,rlen,dlen); + if (bin==NULL) return -1; + bf_direction = command == DRV_BF_ECB_ENCRYPT ? BF_ENCRYPT : BF_DECRYPT; + BF_ecb_encrypt(bf_dbuf, bin, &bf_key, bf_direction); + return dlen; + } + + case DRV_BF_CBC_ENCRYPT: + case DRV_BF_CBC_DECRYPT: + { + /* buf = klen[4] key ivec[8] data */ + unsigned char *ukey; + unsigned char* ivec; + unsigned char bf_tkey[8]; /* blowfish ivec */ + int bf_direction; + const unsigned char *bf_dbuf; /* blowfish input data */ + BF_KEY bf_key; /* blowfish key 8 */ + + klen = get_int32(buf); + ukey = (unsigned char *)buf + 4; + ivec = ukey + klen; + bf_dbuf = ivec + 8; + dlen = len - 4 - klen - 8; + if (dlen < 0) return -1; + BF_set_key(&bf_key, klen, ukey); + memcpy(bf_tkey, ivec, 8); + bin = return_binary(rbuf,rlen,dlen); + if (bin==NULL) return -1; + bf_direction = command == DRV_BF_CBC_ENCRYPT ? BF_ENCRYPT : BF_DECRYPT; + BF_cbc_encrypt(bf_dbuf, bin, dlen, &bf_key, bf_tkey, bf_direction); + return dlen; + } + + case DRV_BF_OFB64_ENCRYPT: + { + /* buf = klen[4] key ivec[8] data */ + unsigned char *ukey; + unsigned char* ivec; + unsigned char bf_tkey[8]; /* blowfish ivec */ + int bf_n; /* blowfish ivec pos */ + const unsigned char *bf_dbuf; /* blowfish input data */ + BF_KEY bf_key; /* blowfish key 8 */ + + klen = get_int32(buf); + ukey = (unsigned char *)buf + 4; + ivec = ukey + klen; + bf_dbuf = ivec + 8; + dlen = len - 4 - klen - 8; + if (dlen < 0) return -1; + BF_set_key(&bf_key, klen, ukey); + memcpy(bf_tkey, ivec, 8); + bin = return_binary(rbuf,rlen,dlen); + if (bin==NULL) return -1; + bf_n = 0; + BF_ofb64_encrypt(bf_dbuf, bin, dlen, &bf_key, bf_tkey, &bf_n); + return dlen; + } + case DRV_BF_CFB64_ENCRYPT: case DRV_BF_CFB64_DECRYPT: { diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index 42ba523c8c..cfc6996332 100644 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -337,6 +337,53 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]> <c>Key3</c>, and <c>IVec</c> must be 64 bits (8 bytes).</p> </desc> </func> + + <func> + <name>blowfish_ecb_encrypt(Key, Text) -> Cipher</name> + <fsummary>Encrypt the first 64 bits of <c>Text</c> using Blowfish in ECB mode</fsummary> + <type> + <v>Key = Text = iolist() | binary()</v> + <v>IVec = Cipher = binary()</v> + </type> + <desc> + <p>Encrypts the first 64 bits of <c>Text</c> using Blowfish in ECB mode. <c>Key</c> is the Blowfish key. The length of <c>Text</c> must be at least 64 bits (8 bytes).</p> + </desc> + <name>blowfish_ecb_decrypt(Key, Text) -> Cipher</name> + <fsummary>Decrypt the first 64 bits of <c>Text</c> using Blowfish in ECB mode</fsummary> + <type> + <v>Key = Text = iolist() | binary()</v> + <v>IVec = Cipher = binary()</v> + </type> + <desc> + <p>Decrypts the first 64 bits of <c>Text</c> using Blowfish in ECB mode. <c>Key</c> is the Blowfish key. The length of <c>Text</c> must be at least 64 bits (8 bytes).</p> + </desc> + </func> + + <func> + <name>blowfish_cbc_encrypt(Key, Text) -> Cipher</name> + <fsummary>Encrypt <c>Text</c> using Blowfish in CBC mode</fsummary> + <type> + <v>Key = Text = iolist() | binary()</v> + <v>IVec = Cipher = binary()</v> + </type> + <desc> + <p>Encrypts <c>Text</c> using Blowfish in CBC mode. <c>Key</c> is the Blowfish key, and <c>IVec</c> is an + arbitrary initializing vector. The length of <c>IVec</c> + must be 64 bits (8 bytes). The length of <c>Text</c> must be a multiple of 64 bits (8 bytes).</p> + </desc> + <name>blowfish_cbc_decrypt(Key, Text) -> Cipher</name> + <fsummary>Decrypt <c>Text</c> using Blowfish in CBC mode</fsummary> + <type> + <v>Key = Text = iolist() | binary()</v> + <v>IVec = Cipher = binary()</v> + </type> + <desc> + <p>Decrypts <c>Text</c> using Blowfish in CBC mode. <c>Key</c> is the Blowfish key, and <c>IVec</c> is an + arbitrary initializing vector. The length of <c>IVec</c> + must be 64 bits (8 bytes). The length of <c>Text</c> must be a multiple 64 bits (8 bytes).</p> + </desc> + </func> + <func> <name>blowfish_cfb64_encrypt(Key, IVec, Text) -> Cipher</name> <fsummary>Encrypt <c>Text</c>using Blowfish in CFB mode with 64 @@ -367,6 +414,23 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]> must be 64 bits (8 bytes).</p> </desc> </func> + + <func> + <name>blowfish_ofb64_encrypt(Key, IVec, Text) -> Cipher</name> + <fsummary>Encrypt <c>Text</c>using Blowfish in OFB mode with 64 + bit feedback</fsummary> + <type> + <v>Key = Text = iolist() | binary()</v> + <v>IVec = Cipher = binary()</v> + </type> + <desc> + <p>Encrypts <c>Text</c> using Blowfish in OFB mode with 64 bit + feedback. <c>Key</c> is the Blowfish key, and <c>IVec</c> is an + arbitrary initializing vector. The length of <c>IVec</c> + must be 64 bits (8 bytes).</p> + </desc> + </func> + <func> <name>aes_cfb_128_encrypt(Key, IVec, Text) -> Cipher</name> <name>aes_cbc_128_encrypt(Key, IVec, Text) -> Cipher</name> diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 5189677dd0..fa33bad2e0 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -30,7 +30,10 @@ -export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac_96/2]). -export([des_cbc_encrypt/3, des_cbc_decrypt/3, des_cbc_ivec/1]). -export([des3_cbc_encrypt/5, des3_cbc_decrypt/5]). --export([blowfish_cfb64_encrypt/3,blowfish_cfb64_decrypt/3]). +-export([blowfish_ecb_encrypt/2, blowfish_ecb_decrypt/2]). +-export([blowfish_cbc_encrypt/3, blowfish_cbc_decrypt/3]). +-export([blowfish_cfb64_encrypt/3, blowfish_cfb64_decrypt/3]). +-export([blowfish_ofb64_encrypt/3]). -export([des_ede3_cbc_encrypt/5, des_ede3_cbc_decrypt/5]). -export([aes_cfb_128_encrypt/3, aes_cfb_128_decrypt/3]). -export([exor/2]). @@ -115,6 +118,11 @@ -define(BF_CFB64_ENCRYPT, 59). -define(BF_CFB64_DECRYPT, 60). +-define(BF_ECB_ENCRYPT, 61). +-define(BF_ECB_DECRYPT, 62). +-define(BF_OFB64_ENCRYPT, 63). +-define(BF_CBC_ENCRYPT, 64). +-define(BF_CBC_DECRYPT, 65). %% -define(IDEA_CBC_ENCRYPT, 34). %% -define(IDEA_CBC_DECRYPT, 35). @@ -303,12 +311,27 @@ des_ede3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) -> %% %% Blowfish %% +blowfish_ecb_encrypt(Key, Data) when byte_size(Data) >= 8 -> + control_bin(?BF_ECB_ENCRYPT, Key, list_to_binary([Data])). + +blowfish_ecb_decrypt(Key, Data) when byte_size(Data) >= 8 -> + control_bin(?BF_ECB_DECRYPT, Key, list_to_binary([Data])). + +blowfish_cbc_encrypt(Key, IVec, Data) when byte_size(Data) rem 8 =:= 0 -> + control_bin(?BF_CBC_ENCRYPT, Key, list_to_binary([IVec, Data])). + +blowfish_cbc_decrypt(Key, IVec, Data) when byte_size(Data) rem 8 =:= 0 -> + control_bin(?BF_CBC_DECRYPT, Key, list_to_binary([IVec, Data])). + blowfish_cfb64_encrypt(Key, IVec, Data) when byte_size(IVec) =:= 8 -> control_bin(?BF_CFB64_ENCRYPT, Key, list_to_binary([IVec, Data])). blowfish_cfb64_decrypt(Key, IVec, Data) when byte_size(IVec) =:= 8 -> control_bin(?BF_CFB64_DECRYPT, Key, list_to_binary([IVec, Data])). +blowfish_ofb64_encrypt(Key, IVec, Data) when byte_size(IVec) =:= 8 -> + control_bin(?BF_OFB64_ENCRYPT, Key, list_to_binary([IVec, Data])). + %% %% AES in cipher feedback mode (CFB) %% diff --git a/lib/crypto/test/Makefile b/lib/crypto/test/Makefile new file mode 100644 index 0000000000..e728875027 --- /dev/null +++ b/lib/crypto/test/Makefile @@ -0,0 +1,83 @@ +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +MODULES = \ + blowfish_SUITE \ + crypto_SUITE + +ERL_FILES= $(MODULES:%=%.erl) + +TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) + +SOURCE = $(ERL_FILES) $(HRL_FILES) + +EMAKEFILE=Emakefile + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/crypto_test + + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- +ERL_MAKE_FLAGS += +ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include + +EBIN = . +MAKE_EMAKE = $(wildcard $(ERL_TOP)/make/make_emakefile) + + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +# Backward compatibility, for R9B and earlier. + +ifeq ($(MAKE_EMAKE),) + +RELTEST_FILES = $(SOURCE) $(TARGET_FILES) +TEST_TARGET = tests + +tests debug opt: $(TARGET_FILES) + +else + +RELTEST_FILES = $(EMAKEFILE) $(SOURCE) +TEST_TARGET = make_emakefile + + +tests debug opt: make_emakefile + erl $(ERL_MAKE_FLAGS) -make + +make_emakefile: + $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) \ + $(MODULES) > $(EMAKEFILE) + +endif +clean: + rm -f $(EMAKEFILE) + rm -f $(TARGET_FILES) $(GEN_FILES) + rm -f core + +docs: + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: + +release_tests_spec: $(TEST_TARGET) + $(INSTALL_DIR) $(RELSYSDIR) + $(INSTALL_DATA) crypto.spec $(RELTEST_FILES) $(RELSYSDIR) + chmod -f -R u+w $(RELSYSDIR) + +release_docs_spec: + diff --git a/lib/crypto/test/blowfish_SUITE.erl b/lib/crypto/test/blowfish_SUITE.erl new file mode 100644 index 0000000000..d4cc167ea9 --- /dev/null +++ b/lib/crypto/test/blowfish_SUITE.erl @@ -0,0 +1,210 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(blowfish_SUITE). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("test_server.hrl"). +-include("test_server_line.hrl"). + +-define(TIMEOUT, 120000). % 2 min + +-define(KEY, to_bin("0123456789ABCDEFF0E1D2C3B4A59687")). +-define(IVEC, to_bin("FEDCBA9876543210")). +%% "7654321 Now is the time for " (includes trailing '\0') +-define(DATA, to_bin("37363534333231204E6F77206973207468652074696D6520666F722000")). +-define(DATA_PADDED, to_bin("37363534333231204E6F77206973207468652074696D6520666F722000000000")). + +%% Test server callback functions +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config) -> Config +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Initialization before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + crypto:start(), + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config) -> _ +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Cleanup after the whole suite +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + crypto:stop(). + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config) -> Config +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Description: Initialization before each test case +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% Description: Initialization before each test case +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config0) -> + Config = lists:keydelete(watchdog, 1, Config0), + Dog = test_server:timetrap(?TIMEOUT), + [{watchdog, Dog} | Config]. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config) -> _ +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Cleanup after each test case +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, Config) -> + Dog = ?config(watchdog, Config), + case Dog of + undefined -> + ok; + _ -> + test_server:timetrap_cancel(Dog) + end. + +%%-------------------------------------------------------------------- +%% Function: all(Clause) -> TestCases +%% Clause - atom() - suite | doc +%% TestCases - [Case] +%% Case - atom() +%% Name of a test case. +%% Description: Returns a list of all test cases in this test suite +%%-------------------------------------------------------------------- +all(doc) -> + ["Test Blowfish functionality"]; + +all(suite) -> + [ecb, + cbc, + cfb64, + ofb64 + ]. + +%% Test cases start here. +%%-------------------------------------------------------------------- + +ecb_test(KeyBytes, ClearBytes, CipherBytes) -> + {Key, Clear, Cipher} = + {to_bin(KeyBytes), to_bin(ClearBytes), to_bin(CipherBytes)}, + crypto:blowfish_ecb_encrypt(Key, Clear) =:= Cipher. + +ecb(doc) -> + "Test that ECB mode is OK"; +ecb(suite) -> + []; +ecb(Config) when is_list(Config) -> + true = ecb_test("0000000000000000", "0000000000000000", "4EF997456198DD78"), + true = ecb_test("FFFFFFFFFFFFFFFF", "FFFFFFFFFFFFFFFF", "51866FD5B85ECB8A"), + true = ecb_test("3000000000000000", "1000000000000001", "7D856F9A613063F2"), + true = ecb_test("1111111111111111", "1111111111111111", "2466DD878B963C9D"), + true = ecb_test("0123456789ABCDEF", "1111111111111111", "61F9C3802281B096"), + true = ecb_test("1111111111111111", "0123456789ABCDEF", "7D0CC630AFDA1EC7"), + true = ecb_test("0000000000000000", "0000000000000000", "4EF997456198DD78"), + true = ecb_test("FEDCBA9876543210", "0123456789ABCDEF", "0ACEAB0FC6A0A28D"), + true = ecb_test("7CA110454A1A6E57", "01A1D6D039776742", "59C68245EB05282B"), + true = ecb_test("0131D9619DC1376E", "5CD54CA83DEF57DA", "B1B8CC0B250F09A0"), + true = ecb_test("07A1133E4A0B2686", "0248D43806F67172", "1730E5778BEA1DA4"), + true = ecb_test("3849674C2602319E", "51454B582DDF440A", "A25E7856CF2651EB"), + true = ecb_test("04B915BA43FEB5B6", "42FD443059577FA2", "353882B109CE8F1A"), + true = ecb_test("0113B970FD34F2CE", "059B5E0851CF143A", "48F4D0884C379918"), + true = ecb_test("0170F175468FB5E6", "0756D8E0774761D2", "432193B78951FC98"), + true = ecb_test("43297FAD38E373FE", "762514B829BF486A", "13F04154D69D1AE5"), + true = ecb_test("07A7137045DA2A16", "3BDD119049372802", "2EEDDA93FFD39C79"), + true = ecb_test("04689104C2FD3B2F", "26955F6835AF609A", "D887E0393C2DA6E3"), + true = ecb_test("37D06BB516CB7546", "164D5E404F275232", "5F99D04F5B163969"), + true = ecb_test("1F08260D1AC2465E", "6B056E18759F5CCA", "4A057A3B24D3977B"), + true = ecb_test("584023641ABA6176", "004BD6EF09176062", "452031C1E4FADA8E"), + true = ecb_test("025816164629B007", "480D39006EE762F2", "7555AE39F59B87BD"), + true = ecb_test("49793EBC79B3258F", "437540C8698F3CFA", "53C55F9CB49FC019"), + true = ecb_test("4FB05E1515AB73A7", "072D43A077075292", "7A8E7BFA937E89A3"), + true = ecb_test("49E95D6D4CA229BF", "02FE55778117F12A", "CF9C5D7A4986ADB5"), + true = ecb_test("018310DC409B26D6", "1D9D5C5018F728C2", "D1ABB290658BC778"), + true = ecb_test("1C587F1C13924FEF", "305532286D6F295A", "55CB3774D13EF201"), + true = ecb_test("0101010101010101", "0123456789ABCDEF", "FA34EC4847B268B2"), + true = ecb_test("1F1F1F1F0E0E0E0E", "0123456789ABCDEF", "A790795108EA3CAE"), + true = ecb_test("E0FEE0FEF1FEF1FE", "0123456789ABCDEF", "C39E072D9FAC631D"), + true = ecb_test("0000000000000000", "FFFFFFFFFFFFFFFF", "014933E0CDAFF6E4"), + true = ecb_test("FFFFFFFFFFFFFFFF", "0000000000000000", "F21E9A77B71C49BC"), + true = ecb_test("0123456789ABCDEF", "0000000000000000", "245946885754369A"), + true = ecb_test("FEDCBA9876543210", "FFFFFFFFFFFFFFFF", "6B5C5A9C5D9E0A5A"), + ok. + +cbc(doc) -> + "Test that CBC mode is OK"; +cbc(suite) -> + []; +cbc(Config) when is_list(Config) -> + true = crypto:blowfish_cbc_encrypt(?KEY, ?IVEC, ?DATA_PADDED) =:= + to_bin("6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC"), + ok. + +cfb64(doc) -> + "Test that CFB64 mode is OK"; +cfb64(suite) -> + []; +cfb64(Config) when is_list(Config) -> + true = crypto:blowfish_cfb64_encrypt(?KEY, ?IVEC, ?DATA) =:= + to_bin("E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3"), + ok. + +ofb64(doc) -> + "Test that OFB64 mode is OK"; +ofb64(suite) -> + []; +ofb64(Config) when is_list(Config) -> + true = crypto:blowfish_ofb64_encrypt(?KEY, ?IVEC, ?DATA) =:= + to_bin("E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA"), + ok. + +%% Helper functions + +%% Convert a hexadecimal string to a binary. +-spec(to_bin(L::string()) -> binary()). +to_bin(L) -> + to_bin(L, []). + +%% @spec dehex(char()) -> integer() +%% @doc Convert a hex digit to its integer value. +-spec(dehex(char()) -> integer()). +dehex(C) when C >= $0, C =< $9 -> + C - $0; +dehex(C) when C >= $a, C =< $f -> + C - $a + 10; +dehex(C) when C >= $A, C =< $F -> + C - $A + 10. + +-spec(to_bin(L::string(), list()) -> binary()). +to_bin([], Acc) -> + iolist_to_binary(lists:reverse(Acc)); +to_bin([C1, C2 | Rest], Acc) -> + to_bin(Rest, [(dehex(C1) bsl 4) bor dehex(C2) | Acc]). diff --git a/lib/crypto/test/crypto.spec b/lib/crypto/test/crypto.spec new file mode 100644 index 0000000000..7ba5696189 --- /dev/null +++ b/lib/crypto/test/crypto.spec @@ -0,0 +1,2 @@ +{topcase, {dir, "../crypto_test"}}. + diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl new file mode 100644 index 0000000000..290ef19160 --- /dev/null +++ b/lib/crypto/test/crypto_SUITE.erl @@ -0,0 +1,1110 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(crypto_SUITE). + +-include("test_server.hrl"). +-include("test_server_line.hrl"). + +-export([all/1, + init_per_testcase/2, + fin_per_testcase/2, + info/1, + link_test/1, + md5/1, + md5_update/1, + md4/1, + md4_update/1, + sha/1, + sha_update/1, + sha256/1, + sha256_update/1, + sha512/1, + sha512_update/1, + md5_mac/1, + md5_mac_io/1, + des_cbc/1, + des_cbc_iter/1, + aes_cfb/1, + aes_cbc/1, + aes_cbc_iter/1, + mod_exp_test/1, + rand_uniform_test/1, + rsa_verify_test/1, + dsa_verify_test/1, + rsa_sign_test/1, + dsa_sign_test/1, + rsa_encrypt_decrypt/1, + dh/1, + exor_test/1, + rc4_test/1, + blowfish_cfb64/1, + smp/1, + cleanup/1]). + +-export([hexstr2bin/1]). + +all(suite) -> + [link_test, + {conf,info,[md5, + md5_update, + md4, + md4_update, + md5_mac, + md5_mac_io, + sha, + sha_update, +%% sha256, +%% sha256_update, +%% sha512, +%% sha512_update, + des_cbc, + aes_cfb, + aes_cbc, + aes_cbc_iter, + des_cbc_iter, + rand_uniform_test, + rsa_verify_test, + dsa_verify_test, + rsa_sign_test, + dsa_sign_test, + rsa_encrypt_decrypt, + dh, + exor_test, + rc4_test, + mod_exp_test, + blowfish_cfb64, + smp], + cleanup}]. + +init_per_testcase(_Name,Config) -> + io:format("init_per_testcase\n"), + ?line crypto:start(), + Config. + +fin_per_testcase(_Name,Config) -> + io:format("fin_per_testcase\n"), + ?line crypto:stop(), + Config. + +%% +%% +link_test(doc) -> + ["Test that the library is statically linked to libcrypto.a."]; +link_test(suite) -> + []; +link_test(Config) when is_list(Config) -> + ?line case os:type() of + {unix,darwin} -> {skipped,"Darwin cannot link statically"}; + {unix,_} -> link_test_1(); + _ -> {skip,"Only runs on Unix"} + end. + +link_test_1() -> + ?line CryptoPriv = code:priv_dir(crypto), + ?line Wc = filename:join([CryptoPriv,"lib","crypto_drv.*"]), + ?line case filelib:wildcard(Wc) of + [] -> {skip,"Didn't find the crypto driver"}; + [Drv] -> link_test_2(Drv) + end. + +link_test_2(Drv) -> + case ldd_program() of + none -> + {skip,"No ldd-like program found"}; + Ldd -> + Cmd = Ldd ++ " " ++ Drv, + Libs = os:cmd(Cmd), + io:format("~p\n", [Libs]), + case string:str(Libs, "libcrypto") of + 0 -> ok; + _ -> + case ?t:is_commercial() of + true -> + ?t:fail({libcrypto,not_statically_linked}); + false -> + {comment,"Not statically linked (OK for open-source platform)"} + end + end + end. + +ldd_program() -> + case os:find_executable("ldd") of + false -> + case os:type() of + {unix,darwin} -> + case os:find_executable("otool") of + false -> none; + Otool -> Otool ++ " -L" + end + end; + Ldd when is_list(Ldd) -> Ldd + end. + +%% +%% +info(doc) -> + ["Call the info function."]; +info(suite) -> + []; +info(Config) when is_list(Config) -> + case {code:lib_dir(crypto),?t:is_commercial()} of + {{error,bad_name},false} -> + {skip,"Missing crypto application"}; + {_,_} -> + ?line crypto:start(), + ?line crypto:info(), + ?line InfoLib = crypto:info_lib(), + ?line [_|_] = InfoLib, + F = fun([{Name,VerN,VerS}|T],Me) -> + ?line true = is_binary(Name), + ?line true = is_integer(VerN), + ?line true = is_binary(VerS), + Me(T,Me); + ([],_) -> + ok + end, + ?line F(InfoLib,F), + ?line crypto:stop() + end. + +cleanup(doc) -> + ["Cleanup (dummy)."]; +cleanup(suite) -> + []; +cleanup(Config) when is_list(Config) -> + Config. + +%% +%% +md5(doc) -> + ["Generate MD5 message digests and check the result. Examples are " + "from RFC-1321."]; +md5(suite) -> + []; +md5(Config) when is_list(Config) -> + ?line m(crypto:md5(""), + hexstr2bin("d41d8cd98f00b204e9800998ecf8427e")), + ?line m(crypto:md5("a"), + hexstr2bin("0cc175b9c0f1b6a831c399e269772661")), + ?line m(crypto:md5("abc"), + hexstr2bin("900150983cd24fb0d6963f7d28e17f72")), + ?line m(crypto:md5("message digest"), + hexstr2bin("f96b697d7cb7938d525a2f31aaf161d0")), + ?line m(crypto:md5("abcdefghijklmnopqrstuvwxyz"), + hexstr2bin("c3fcd3d76192e4007dfb496cca67e13b")), + ?line m(crypto:md5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789"), + hexstr2bin("d174ab98d277d9f5a5611c2c9f419d9f")), + ?line m(crypto:md5("12345678901234567890123456789012345678901234567890" + "123456789012345678901234567890"), + hexstr2bin("57edf4a22be3c955ac49da2e2107b67a")). + +%% +%% +md5_update(doc) -> + ["Generate MD5 message using md5_init, md5_update, and md5_final, and" + "check the result. Examples are from RFC-1321."]; +md5_update(suite) -> + []; +md5_update(Config) when is_list(Config) -> + ?line Ctx = crypto:md5_init(), + ?line Ctx1 = crypto:md5_update(Ctx, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"), + ?line Ctx2 = crypto:md5_update(Ctx1, "abcdefghijklmnopqrstuvwxyz" + "0123456789"), + ?line m(crypto:md5_final(Ctx2), + hexstr2bin("d174ab98d277d9f5a5611c2c9f419d9f")). + +%% +%% +md4(doc) -> + ["Generate MD4 message digests and check the result. Examples are " + "from RFC-1321."]; +md4(suite) -> + []; +md4(Config) when is_list(Config) -> + ?line m(crypto:md4(""), + hexstr2bin("31d6cfe0d16ae931b73c59d7e0c089c0")), + ?line m(crypto:md4("a"), + hexstr2bin("bde52cb31de33e46245e05fbdbd6fb24")), + ?line m(crypto:md4("abc"), + hexstr2bin("a448017aaf21d8525fc10ae87aa6729d")), + ?line m(crypto:md4("message digest"), + hexstr2bin("d9130a8164549fe818874806e1c7014b")), + ?line m(crypto:md4("abcdefghijklmnopqrstuvwxyz"), + hexstr2bin("d79e1c308aa5bbcdeea8ed63df412da9")), + ?line m(crypto:md4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789"), + hexstr2bin("043f8582f241db351ce627e153e7f0e4")), + ?line m(crypto:md4("12345678901234567890123456789012345678901234567890" + "123456789012345678901234567890"), + hexstr2bin("e33b4ddc9c38f2199c3e7b164fcc0536")). + +%% +%% +md4_update(doc) -> + ["Generate MD5 message using md5_init, md5_update, and md5_final, and" + "check the result. Examples are from RFC-1321."]; +md4_update(suite) -> + []; +md4_update(Config) when is_list(Config) -> + ?line Ctx = crypto:md4_init(), + ?line Ctx1 = crypto:md4_update(Ctx, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"), + ?line Ctx2 = crypto:md4_update(Ctx1, "abcdefghijklmnopqrstuvwxyz" + "0123456789"), + ?line m(crypto:md4_final(Ctx2), + hexstr2bin("043f8582f241db351ce627e153e7f0e4")). + +%% +%% +sha(doc) -> + ["Generate SHA message digests and check the result. Examples are " + "from FIPS-180-1."]; +sha(suite) -> + []; +sha(Config) when is_list(Config) -> + ?line m(crypto:sha("abc"), + hexstr2bin("A9993E364706816ABA3E25717850C26C9CD0D89D")), + ?line m(crypto:sha("abcdbcdecdefdefgefghfghighijhijkijkljklmklm" + "nlmnomnopnopq"), + hexstr2bin("84983E441C3BD26EBAAE4AA1F95129E5E54670F1")). + + +%% +%% +sha_update(doc) -> + ["Generate SHA message digests by using sha_init, sha_update, and" + "sha_final, and check the result. Examples are from FIPS-180-1."]; +sha_update(suite) -> + []; +sha_update(Config) when is_list(Config) -> + ?line Ctx = crypto:sha_init(), + ?line Ctx1 = crypto:sha_update(Ctx, "abcdbcdecdefdefgefghfghighi"), + ?line Ctx2 = crypto:sha_update(Ctx1, "jhijkijkljklmklmnlmnomnopnopq"), + ?line m(crypto:sha_final(Ctx2), + hexstr2bin("84983E441C3BD26EBAAE4AA1F95129E5E54670F1")). + +%% +%% +sha256(doc) -> + ["Generate SHA-256 message digests and check the result. Examples are " + "from rfc-4634."]; +sha256(suite) -> + []; +sha256(Config) when is_list(Config) -> + ?line m(crypto:sha256("abc"), + hexstr2bin("BA7816BF8F01CFEA4141" + "40DE5DAE2223B00361A396177A9CB410FF61F20015AD")), + ?line m(crypto:sha256("abcdbcdecdefdefgefghfghighijhijkijkljklmklm" + "nlmnomnopnopq"), + hexstr2bin("248D6A61D20638B8" + "E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1")). + +%% +%% +sha256_update(doc) -> + ["Generate SHA256 message digests by using sha256_init, sha256_update, and" + "sha256_final, and check the result. Examples are from rfc-4634."]; +sha256_update(suite) -> + []; +sha256_update(Config) when is_list(Config) -> + ?line Ctx = crypto:sha256_init(), + ?line Ctx1 = crypto:sha256_update(Ctx, "abcdbcdecdefdefgefghfghighi"), + ?line Ctx2 = crypto:sha256_update(Ctx1, "jhijkijkljklmklmnlmnomnopnopq"), + ?line m(crypto:sha256_final(Ctx2), + hexstr2bin("248D6A61D20638B8" + "E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1")). + + +%% +%% +sha512(doc) -> + ["Generate SHA-512 message digests and check the result. Examples are " + "from rfc-4634."]; +sha512(suite) -> + []; +sha512(Config) when is_list(Config) -> + ?line m(crypto:sha512("abc"), + hexstr2bin("DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA2" + "0A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD" + "454D4423643CE80E2A9AC94FA54CA49F")), + ?line m(crypto:sha512("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"), + hexstr2bin("8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA1" + "7299AEADB6889018501D289E4900F7E4331B99DEC4B5433A" + "C7D329EEB6DD26545E96E55B874BE909")). + +%% +%% +sha512_update(doc) -> + ["Generate SHA512 message digests by using sha512_init, sha512_update, and" + "sha512_final, and check the result. Examples are from rfc=4634."]; +sha512_update(suite) -> + []; +sha512_update(Config) when is_list(Config) -> + ?line Ctx = crypto:sha512_init(), + ?line Ctx1 = crypto:sha512_update(Ctx, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"), + ?line Ctx2 = crypto:sha512_update(Ctx1, "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"), + ?line m(crypto:sha512_final(Ctx2), + hexstr2bin("8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA1" + "7299AEADB6889018501D289E4900F7E4331B99DEC4B5433A" + "C7D329EEB6DD26545E96E55B874BE909")). + +%% +%% +md5_mac(doc) -> + ["Generate some HMACs, using MD5, and check the result. Examples are " + "from RFC-2104."]; +md5_mac(suite) -> + []; +md5_mac(Config) when is_list(Config) -> + ?line m(crypto:md5_mac(hexstr2bin("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), + "Hi There"), + hexstr2bin("9294727a3638bb1c13f48ef8158bfc9d")), + ?line m(crypto:md5_mac(list_to_binary("Jefe"), + "what do ya want for nothing?"), + hexstr2bin("750c783e6ab0b503eaa86e310a5db738")), + ?line m(crypto:md5_mac(hexstr2bin("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), + hexstr2bin("DDDDDDDDDDDDDDDDDDDD" + "DDDDDDDDDDDDDDDDDDDD" + "DDDDDDDDDDDDDDDDDDDD" + "DDDDDDDDDDDDDDDDDDDD" + "DDDDDDDDDDDDDDDDDDDD")), + hexstr2bin("56be34521d144c88dbb8c733f0e8b3f6")). + +%% +%% +md5_mac_io(doc) -> + ["Generate some HMACs, using MD5, with Key an IO-list, and check the " + "result. Examples are from RFC-2104."]; +md5_mac_io(suite) -> + []; +md5_mac_io(Config) when is_list(Config) -> + ?line Key1 = hexstr2bin("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), + ?line {B11, B12} = split_binary(Key1, 4), + ?line Key11 = [B11,binary_to_list(B12)], + ?line m(crypto:md5_mac(Key11, "Hi There"), + hexstr2bin("9294727a3638bb1c13f48ef8158bfc9d")). + +%% +%% +des_cbc(doc) -> + "Encrypt and decrypt according to CBC DES. and check the result. " + "Example are from FIPS-81."; +des_cbc(suite) -> + []; +des_cbc(Config) when is_list(Config) -> + ?line Key = hexstr2bin("0123456789abcdef"), + ?line IVec = hexstr2bin("1234567890abcdef"), + ?line Plain = "Now is the time for all ", + ?line Cipher = crypto:des_cbc_encrypt(Key, IVec, Plain), + ?line m(Cipher, hexstr2bin("e5c7cdde872bf27c43e934008c389c" + "0f683788499a7c05f6")), + ?line m(list_to_binary(Plain), + crypto:des_cbc_decrypt(Key, IVec, Cipher)), + ?line Plain2 = "7654321 Now is the time for " ++ [0, 0, 0, 0], + ?line Cipher2 = crypto:des_cbc_encrypt(Key, IVec, Plain2), + ?line m(Cipher2, hexstr2bin("b9916b8ee4c3da64b4f44e3cbefb9" + "9484521388fa59ae67d58d2e77e86062733")), + ?line m(list_to_binary(Plain2), + crypto:des_cbc_decrypt(Key, IVec, Cipher2)). + +%% +%% +des_cbc_iter(doc) -> + "Encrypt and decrypt according to CBC DES in two steps, and " + "check the result. Example are from FIPS-81."; +des_cbc_iter(suite) -> + []; +des_cbc_iter(Config) when is_list(Config) -> + ?line Key = hexstr2bin("0123456789abcdef"), + ?line IVec = hexstr2bin("1234567890abcdef"), + ?line Plain1 = "Now is the time ", + ?line Plain2 = "for all ", + ?line Cipher1 = crypto:des_cbc_encrypt(Key, IVec, Plain1), + ?line IVec2 = crypto:des_cbc_ivec(Cipher1), + ?line Cipher2 = crypto:des_cbc_encrypt(Key, IVec2, Plain2), + ?line Cipher = concat_binary([Cipher1, Cipher2]), + ?line m(Cipher, hexstr2bin("e5c7cdde872bf27c43e934008c389c" + "0f683788499a7c05f6")). + +%% +%% +aes_cfb(doc) -> + "Encrypt and decrypt according to AES CFB 128 bit and check " + "the result. Example are from NIST SP 800-38A."; + +aes_cfb(suite) -> + []; +aes_cfb(Config) when is_list(Config) -> + +%% Sample data from NIST Spec.Publ. 800-38A +%% F.3.13 CFB128-AES128.Encrypt +%% Key 2b7e151628aed2a6abf7158809cf4f3c +%% IV 000102030405060708090a0b0c0d0e0f +%% Segment #1 +%% Input Block 000102030405060708090a0b0c0d0e0f +%% Output Block 50fe67cc996d32b6da0937e99bafec60 +%% Plaintext 6bc1bee22e409f96e93d7e117393172a +%% Ciphertext 3b3fd92eb72dad20333449f8e83cfb4a +%% Segment #2 +%% Input Block 3b3fd92eb72dad20333449f8e83cfb4a +%% Output Block 668bcf60beb005a35354a201dab36bda +%% Plaintext ae2d8a571e03ac9c9eb76fac45af8e51 +%% Ciphertext c8a64537a0b3a93fcde3cdad9f1ce58b +%% Segment #3 +%% Input Block c8a64537a0b3a93fcde3cdad9f1ce58b +%% Output Block 16bd032100975551547b4de89daea630 +%% Plaintext 30c81c46a35ce411e5fbc1191a0a52ef +%% Ciphertext 26751f67a3cbb140b1808cf187a4f4df +%% Segment #4 +%% Input Block 26751f67a3cbb140b1808cf187a4f4df +%% Output Block 36d42170a312871947ef8714799bc5f6 +%% Plaintext f69f2445df4f9b17ad2b417be66c3710 +%% Ciphertext c04b05357c5d1c0eeac4c66f9ff7f2e6 + + ?line Key = hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"), + ?line IVec = hexstr2bin("000102030405060708090a0b0c0d0e0f"), + ?line Plain = hexstr2bin("6bc1bee22e409f96e93d7e117393172a"), + ?line Cipher = crypto:aes_cfb_128_encrypt(Key, IVec, Plain), + ?line m(Cipher, hexstr2bin("3b3fd92eb72dad20333449f8e83cfb4a")), + ?line m(Plain, + crypto:aes_cfb_128_decrypt(Key, IVec, Cipher)). + +%% +%% +aes_cbc(doc) -> + "Encrypt and decrypt according to AES CBC 128 bit. and check the result. " + "Example are from NIST SP 800-38A."; + +aes_cbc(suite) -> + []; +aes_cbc(Config) when is_list(Config) -> + +%% Sample data from NIST Spec.Publ. 800-38A +%% F.2.1 CBC-AES128.Encrypt +%% Key 2b7e151628aed2a6abf7158809cf4f3c +%% IV 000102030405060708090a0b0c0d0e0f +%% Block #1 +%% Plaintext 6bc1bee22e409f96e93d7e117393172a +%% Input Block 6bc0bce12a459991e134741a7f9e1925 +%% Output Block 7649abac8119b246cee98e9b12e9197d +%% Ciphertext 7649abac8119b246cee98e9b12e9197d +%% Block #2 +%% Plaintext ae2d8a571e03ac9c9eb76fac45af8e51 +%% Input Block d86421fb9f1a1eda505ee1375746972c +%% Output Block 5086cb9b507219ee95db113a917678b2 +%% Ciphertext 5086cb9b507219ee95db113a917678b2 +%% Block #3 +%% Plaintext 30c81c46a35ce411e5fbc1191a0a52ef +%% Input Block 604ed7ddf32efdff7020d0238b7c2a5d +%% Output Block 73bed6b8e3c1743b7116e69e22229516 +%% Ciphertext 73bed6b8e3c1743b7116e69e22229516 +%% Block #4 +%% Plaintext f69f2445df4f9b17ad2b417be66c3710 +%% Input Block 8521f2fd3c8eef2cdc3da7e5c44ea206 +%% Output Block 3ff1caa1681fac09120eca307586e1a7 +%% Ciphertext 3ff1caa1681fac09120eca307586e1a7 +%% +%% F.2.2 CBC-AES128.Decrypt +%% Key 2b7e151628aed2a6abf7158809cf4f3c +%% IV 000102030405060708090a0b0c0d0e0f + %% Block #1 +%% Ciphertext 7649abac8119b246cee98e9b12e9197d +%% Input Block 7649abac8119b246cee98e9b12e9197d +%% Output Block 6bc0bce12a459991e134741a7f9e1925 +%% Plaintext 6bc1bee22e409f96e93d7e117393172a +%% Block #2 +%% Ciphertext 5086cb9b507219ee95db113a917678b2 +%% Input Block 5086cb9b507219ee95db113a917678b2 +%% Output Block d86421fb9f1a1eda505ee1375746972c +%% Plaintext ae2d8a571e03ac9c9eb76fac45af8e51 +%% Block #3 +%% Ciphertext 73bed6b8e3c1743b7116e69e22229516 +%% Input Block 73bed6b8e3c1743b7116e69e22229516 +%% Output Block 604ed7ddf32efdff7020d0238b7c2a5d +%% Plaintext 30c81c46a35ce411e5fbc1191a0a52ef +%% Block #4 +%% Ciphertext 3ff1caa1681fac09120eca307586e1a7 +%% Input Block 3ff1caa1681fac09120eca307586e1a7 +%% Output Block 8521f2fd3c8eef2cdc3da7e5c44ea206 +%% Plaintext f69f2445df4f9b17ad2b417be66c3710 + + ?line Key = hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"), + ?line IVec = hexstr2bin("000102030405060708090a0b0c0d0e0f"), + ?line Plain = hexstr2bin("6bc1bee22e409f96e93d7e117393172a"), + ?line Cipher = crypto:aes_cbc_128_encrypt(Key, IVec, Plain), + ?line m(Cipher, hexstr2bin("7649abac8119b246cee98e9b12e9197d")), + ?line m(Plain, + crypto:aes_cbc_128_decrypt(Key, IVec, Cipher)). + +aes_cbc_iter(doc) -> + "Encrypt and decrypt according to CBC AES in steps"; +aes_cbc_iter(suite) -> []; +aes_cbc_iter(Config) when is_list(Config) -> + Key = list_to_binary(lists:seq(255,256-16*17,-17)), + IVec = list_to_binary(lists:seq(1,16*7,7)), + Plain = <<"One, two, three o'clock, four o'clock, rock" + "Five, six, seven o'clock, eight o'clock, rock" + "Nine, ten, eleven o'clock, twelve o'clock, rock" + "We're gonna rock around the clock tonight">>, + ?line 0 = size(Plain) rem 16, + + ?line Cipher = crypto:aes_cbc_128_encrypt(Key, IVec, Plain), + ?line Plain = crypto:aes_cbc_128_decrypt(Key, IVec, Cipher), + + ?line Cipher = aes_cbc_encrypt_iter(Key,IVec,Plain,<<>>), + ?line Plain = aes_cbc_decrypt_iter(Key,IVec,Cipher,<<>>), + ok. + +aes_cbc_encrypt_iter(_,_,<<>>, Acc) -> + Acc; +aes_cbc_encrypt_iter(Key,IVec,Data, Acc) -> + Bytes = 16 * (1 + size(Data) div (16*3)), + <<Chunk:Bytes/binary, Rest/binary>> = Data, + %%io:format("encrypt iter Chunk=~p Rest=~p\n",[Chunk,Rest]), + ?line Cipher = crypto:aes_cbc_128_encrypt(Key, IVec, Chunk), + ?line IVec2 = crypto:aes_cbc_ivec(Cipher), + aes_cbc_encrypt_iter(Key,IVec2,Rest, <<Acc/binary, Cipher/binary>>). + +aes_cbc_decrypt_iter(_,_,<<>>, Acc) -> + Acc; +aes_cbc_decrypt_iter(Key,IVec,Data, Acc) -> + Bytes = 16 * (1 + size(Data) div (16*5)), + <<Chunk:Bytes/binary, Rest/binary>> = Data, + %%io:format("decrypt iter Chunk=~p Rest=~p\n",[Chunk,Rest]), + ?line Plain = crypto:aes_cbc_128_decrypt(Key, IVec, Chunk), + ?line IVec2 = crypto:aes_cbc_ivec(Chunk), + aes_cbc_decrypt_iter(Key,IVec2,Rest, <<Acc/binary, Plain/binary>>). + + +%% +%% +mod_exp_test(doc) -> + "mod_exp testing (A ^ M % P with bignums)"; +mod_exp_test(suite) -> + []; +mod_exp_test(Config) when is_list(Config) -> + mod_exp_aux_test(2, 5, 10, 8). + +mod_exp_aux_test(_, _, _, 0) -> + ok; +mod_exp_aux_test(B, E, M, N) -> + ?line R1 = crypto:mod_exp(B, E, M), + ?line R2 = ipow(B, E, M), + ?line m(R1, R2), + ?line mod_exp_aux_test(B, E*E+1, M*M+1, N-1). + +%% +%% +rand_uniform_test(doc) -> + "rand_uniform and random_bytes testing"; +rand_uniform_test(suite) -> + []; +rand_uniform_test(Config) when is_list(Config) -> + rand_uniform_aux_test(10), + ?line 10 = size(crypto:rand_bytes(10)). + +rand_uniform_aux_test(0) -> + ok; +rand_uniform_aux_test(N) -> + ?line L = N*1000, + ?line H = N*100000+1, + ?line R1 = crypto:rand_uniform(L, H), + ?line t(R1 >= L), + ?line t(R1 < H), + ?line rand_uniform_aux_test(N-1). + +%% +%% +%% +%% +rsa_verify_test(doc) -> + "rsa_verify testing (A ^ M % P with bignums)"; +rsa_verify_test(suite) -> + []; +rsa_verify_test(Config) when is_list(Config) -> + ?line H = <<178,28,54,104,36,80,144,66,140,201,135,17,36,97,114,124, + 194,164,172,147>>, + ?line SigBlob = <<153,44,121,71,132,1,192,159,78,33,29,62,153,64,191,70, + 208,239,166,208,220,167,49,111,128,67,91,253,24,63,194,241, + 97,157,135,226,121,162,150,156,60,49,236,90,151,67,239,23, + 92,103,89,254,17,165,78,181,64,128,13,210,86,111,209,76, + 115,34,107,227,151,47,80,185,143,85,202,55,245,163,226,26, + 139,104,196,6,96,82,108,197,13,0,12,70,153,109,107,180, + 130,246,156,182,56,96,31,220,227,218,136,211,252,43,8,14, + 145,155,191,206,72,194,80,52,54,206,53,27,6,188,195,29>>, + ?line BadSigBlob = <<153,44,121,71,132,1,192,159,78,33,29,62,153,64,191,70, + 208,239,166,208,220,167,49,111,128,67,91,253,24,63,194,241, + 97,157,135,226,121,162,150,156,60,49,236,90,151,67,239,23, + 92,103,89,254,17,165,78,181,64,128,13,210,86,111,209,76, + 115,107,34,227,151,47,80,185,143,85,202,55,245,163,226,26, + 139,104,196,6,96,82,108,197,13,0,12,70,153,109,107,180, + 130,246,156,182,56,96,31,220,227,218,136,211,252,43,8,14, + 145,155,191,206,72,194,80,52,54,206,53,27,6,188,195,29>>, + ?line E = <<35>>, + ?line N = <<0,199,209,142,191,86,92,148,103,37,250,217,175,169,109,10, + 130,139,34,237,174,90,97,118,7,185,57,137,252,236,177,193, + 228,16,62,29,153,144,64,207,152,240,152,206,136,89,64,6, + 3,187,89,57,241,219,88,215,75,70,120,20,145,229,37,1, + 67,138,204,17,39,231,249,239,116,142,169,99,149,41,65,123, + 26,225,133,0,41,85,77,181,35,100,162,223,92,220,207,50, + 63,168,193,171,174,199,23,214,201,63,157,76,125,6,54,73, + 76,89,40,33,147,208,189,76,98,24,61,8,10,110,165,119,165>>, + ?line Nbad = <<0,199,209,142,191,86,92,148,103,37,250,217,175,169,109,10, + 130,139,34,237,174,90,97,118,7,185,57,137,252,236,177,193, + 228,16,62,29,153,144,64,207,152,240,152,206,136,89,64,6, + 3,187,89,57,241,219,88,215,75,70,120,20,145,229,37,1, + 67,138,204,17,39,231,249,239,116,142,169,99,149,41,65,123, + 26,225,133,0,41,85,77,181,35,100,162,223,92,220,207,50, + 63,168,193,171,174,199,23,214,201,63,157,76,125,6,54,73, + 76,89,40,33,147,189,208,76,98,24,61,8,10,110,165,119,165>>, + ?line Ebad = <<77>>, + ?line m(crypto:rsa_verify(sized_binary(H), sized_binary(SigBlob), + [sized_binary(E), sized_binary(N)]), true), + ?line m(crypto:rsa_verify(sized_binary(H), sized_binary(SigBlob), + [sized_binary(Ebad), sized_binary(N)]), false), + ?line m(crypto:rsa_verify(sized_binary(H), sized_binary(SigBlob), + [sized_binary(E), sized_binary(Nbad)]), false), + ?line m(crypto:rsa_verify(sized_binary(H), sized_binary(BadSigBlob), + [sized_binary(E), sized_binary(N)]), false). + +%% +%% +dsa_verify_test(doc) -> + "dsa_verify testing (A ^ M % P with bignums)"; +dsa_verify_test(suite) -> + []; +dsa_verify_test(Config) when is_list(Config) -> + ?line Msg = <<48,130,2,245,160,3,2,1,2,2,1,1,48,9,6,7,42,134,72,206,56,4,3,48, + 58,49,11,48,9,6,3,85,4,6,19,2,85,83,49,26,48,24,6,3,85,4,10,19,17, + 84,101,115,116,32,67,101,114,116,105,102,105,99,97,116,101,115,49, + 15,48,13,6,3,85,4,3,19,6,68,83,65,32,67,65,48,30,23,13,48,49,48, + 52,49,57,49,52,53,55,50,48,90,23,13,49,49,48,52,49,57,49,52,53,55, + 50,48,90,48,93,49,11,48,9,6,3,85,4,6,19,2,85,83,49,26,48,24,6,3, + 85,4,10,19,17,84,101,115,116,32,67,101,114,116,105,102,105,99,97, + 116,101,115,49,50,48,48,6,3,85,4,3,19,41,86,97,108,105,100,32,68, + 83,65,32,83,105,103,110,97,116,117,114,101,115,32,69,69,32,67,101, + 114,116,105,102,105,99,97,116,101,32,84,101,115,116,52,48,130,1, + 182,48,130,1,43,6,7,42,134,72,206,56,4,1,48,130,1,30,2,129,129,0, + 228,139,175,64,140,21,215,61,124,238,3,150,18,104,193,32,5,232,23, + 202,158,116,101,75,154,84,151,42,120,51,218,165,197,114,234,52, + 179,148,104,66,213,27,253,119,240,168,66,158,100,147,144,182,194, + 2,49,70,19,122,3,105,204,152,45,86,157,94,35,95,40,191,173,127,15, + 208,105,149,98,92,26,7,42,94,140,115,73,126,253,18,34,142,85,229, + 86,233,174,114,41,150,135,8,39,215,119,67,240,134,184,9,10,27,20, + 165,230,3,230,69,121,77,233,250,83,95,193,9,189,126,197,195,2,21, + 0,128,63,228,252,243,76,229,62,203,15,23,10,42,84,108,208,103,108, + 13,59,2,129,128,102,212,22,138,32,173,254,209,50,159,165,127,167, + 179,208,234,119,63,235,108,162,228,41,216,216,188,33,221,154,247, + 204,229,180,119,77,223,236,218,162,140,156,117,18,90,31,254,102, + 211,17,194,239,132,67,236,169,136,110,76,186,76,63,53,150,199,103, + 252,153,189,15,153,41,19,145,78,216,2,174,254,107,175,80,86,170, + 47,30,181,42,200,238,34,71,37,120,107,33,221,20,63,206,240,16,129, + 247,150,29,156,65,187,94,68,146,93,46,198,30,184,205,105,200,143, + 63,59,62,208,79,162,206,217,3,129,132,0,2,129,128,15,83,40,172,56, + 47,61,243,17,97,65,195,61,167,214,122,247,246,1,50,211,33,113,16, + 20,213,195,62,77,235,25,162,140,175,158,8,61,65,10,255,204,162,71, + 130,122,86,161,163,253,236,178,139,183,57,181,202,160,25,133,130, + 155,150,104,168,187,107,186,144,164,225,173,101,182,68,49,210,30, + 34,47,83,65,79,250,156,248,47,232,44,67,36,22,126,43,216,100,247, + 100,250,240,121,72,29,185,2,109,144,54,204,235,54,15,242,57,171, + 125,39,236,247,71,111,221,51,196,126,77,238,36,87,163,107,48,105, + 48,29,6,3,85,29,14,4,22,4,20,179,51,215,81,162,4,13,68,251,157,64, + 241,18,98,113,176,83,246,105,13,48,31,6,3,85,29,35,4,24,48,22,128, + 20,116,21,213,36,28,189,94,101,136,31,225,139,9,126,127,234,25,72, + 78,97,48,23,6,3,85,29,32,4,16,48,14,48,12,6,10,96,134,72,1,101,3, + 2,1,48,1,48,14,6,3,85,29,15,1,1,255,4,4,3,2,6,192>>, + + ?line SigBlob = <<48,45,2,21,0,140,167,200,210,153,212,64,155,249,33,146,104,243, + 39,38,9,115,162,89,24,2,20,76,254,31,128,187,48,128,215,216, + 112,198,78,118,160,217,157,180,246,64,234>>, + ?line P_p = 157224271412839155721795253728878055347359513988016145491388196653004661857517720927482198111104095793441029858267073789634147217022008635826863307553453131345099940951090826856271796188522037524757740796268675508118348391218066949174594918958269259937813776150149068811425194955973128428675945283593831134219, + ?line Q_p = 1181895316321540581845959276009400765315408342791, + ?line G_p = 143872196713149000950547166575757355261637863805587906227228163275557375159769599033632918292482002186641475268486598023281100659643528846513898847919251032731261718358900479488287933293278745715922865499005559197328388506945134386346185262919258658109015074718441639029135304654725637911172671711310801418648, + + ?line Key = 12603618348903387232593303690286336220738319446775939686476278478034365380027994899970214309288018488811754534229198764622077544117034174589418477472887827980332636062691833965078594576024299807057520016043084384987871640003684704483975314128362610573625803532737054022545217931847268776098203204571431581966, + + ValidKey = [crypto:mpint(P_p), + crypto:mpint(Q_p), + crypto:mpint(G_p), + crypto:mpint(Key) + ], + + ?line m(crypto:dss_verify(sized_binary(Msg), sized_binary(SigBlob), + ValidKey), true), + + BadMsg = one_bit_wrong(Msg), + ?line m(crypto:dss_verify(sized_binary(BadMsg), sized_binary(SigBlob), + ValidKey), false), + BadSig = one_bit_wrong(SigBlob), + ?line m(crypto:dss_verify(sized_binary(Msg), sized_binary(BadSig), + ValidKey), false), + SizeErr = size(SigBlob) - 13, + + BadArg = (catch crypto:dss_verify(sized_binary(Msg), <<SizeErr:32, SigBlob/binary>>, + ValidKey)), + ?line m(element(1,element(2,BadArg)), badarg), + + InValidKey = [crypto:mpint(P_p), + crypto:mpint(Q_p), + crypto:mpint(G_p), + crypto:mpint(Key+17) + ], + + ?line m(crypto:dss_verify(sized_binary(Msg), sized_binary(SigBlob), + InValidKey), false). + +one_bit_wrong(Bin) -> + Half = size(Bin) div 2, + <<First:Half/binary, Byte:8, Last/binary>> = Bin, + <<First/binary, (Byte+1):8, Last/binary>>. + + +%% +%% Sign tests + +rsa_sign_test(doc) -> + "rsa_sign testing"; +rsa_sign_test(suite) -> + []; +rsa_sign_test(Config) when is_list(Config) -> + PubEx = 65537, + PrivEx = 7531712708607620783801185371644749935066152052780368689827275932079815492940396744378735701395659435842364793962992309884847527234216715366607660219930945, + Mod = 7919488123861148172698919999061127847747888703039837999377650217570191053151807772962118671509138346758471459464133273114654252861270845708312601272799123, + Msg = <<"7896345786348756234 Hejsan Svejsan, erlang crypto debugger" + "09812312908312378623487263487623412039812 huagasd">>, + + PrivKey = [crypto:mpint(PubEx), crypto:mpint(Mod), crypto:mpint(PrivEx)], + PubKey = [crypto:mpint(PubEx), crypto:mpint(Mod)], + ?line Sig1 = crypto:rsa_sign(sized_binary(Msg), PrivKey), + ?line m(crypto:rsa_verify(sized_binary(Msg), sized_binary(Sig1),PubKey), true), + + ?line Sig2 = crypto:rsa_sign(md5, sized_binary(Msg), PrivKey), + ?line m(crypto:rsa_verify(md5, sized_binary(Msg), sized_binary(Sig2),PubKey), true), + + ?line m(Sig1 =:= Sig2, false), + ?line m(crypto:rsa_verify(md5, sized_binary(Msg), sized_binary(Sig1),PubKey), false), + ?line m(crypto:rsa_verify(sha, sized_binary(Msg), sized_binary(Sig1),PubKey), true), + + ok. + +dsa_sign_test(doc) -> + "dsa_sign testing"; +dsa_sign_test(suite) -> + []; +dsa_sign_test(Config) when is_list(Config) -> + Msg = <<"7896345786348756234 Hejsan Svejsan, erlang crypto debugger" + "09812312908312378623487263487623412039812 huagasd">>, + + PubKey = _Y = 25854665488880835237281628794585130313500176551981812527054397586638455298000483144002221850980183404910190346416063318160497344811383498859129095184158800144312512447497510551471331451396405348497845813002058423110442376886564659959543650802132345311573634832461635601376738282831340827591903548964194832978, + PrivKey = _X = 441502407453038284293378221372000880210588566361, + ParamP = 109799869232806890760655301608454668257695818999841877165019612946154359052535682480084145133201304812979481136659521529774182959764860329095546511521488413513097576425638476458000255392402120367876345280670101492199681798674053929238558140260669578407351853803102625390950534052428162468100618240968893110797, + ParamQ = 1349199015905534965792122312016505075413456283393, + ParamG = 18320614775012672475365915366944922415598782131828709277168615511695849821411624805195787607930033958243224786899641459701930253094446221381818858674389863050420226114787005820357372837321561754462061849169568607689530279303056075793886577588606958623645901271866346406773590024901668622321064384483571751669, + + Params = [crypto:mpint(ParamP), crypto:mpint(ParamQ), crypto:mpint(ParamG)], + ?line Sig1 = crypto:dss_sign(sized_binary(Msg), [Params, crypto:mpint(PrivKey)]), + + ?line m(crypto:dss_verify(sized_binary(Msg), sized_binary(Sig1), + [Params, crypto:mpint(PubKey)]), true), + + ?line m(crypto:dss_verify(sized_binary(one_bit_wrong(Msg)), sized_binary(Sig1), + [Params, crypto:mpint(PubKey)]), false), + + ?line m(crypto:dss_verify(sized_binary(Msg), sized_binary(one_bit_wrong(Sig1)), + [Params, crypto:mpint(PubKey)]), false), + + %%?line Bad = crypto:dss_sign(sized_binary(Msg), [Params, crypto:mpint(PubKey)]), + + ok. + + +rsa_encrypt_decrypt(doc) -> + ["Test rsa_public_encrypt and rsa_private_decrypt functions."]; +rsa_encrypt_decrypt(suite) -> []; +rsa_encrypt_decrypt(Config) when is_list(Config) -> + PubEx = 65537, + PrivEx = 7531712708607620783801185371644749935066152052780368689827275932079815492940396744378735701395659435842364793962992309884847527234216715366607660219930945, + Mod = 7919488123861148172698919999061127847747888703039837999377650217570191053151807772962118671509138346758471459464133273114654252861270845708312601272799123, + + PrivKey = [crypto:mpint(PubEx), crypto:mpint(Mod), crypto:mpint(PrivEx)], + PubKey = [crypto:mpint(PubEx), crypto:mpint(Mod)], + + Msg = <<"7896345786348 Asldi">>, + + ?line PKCS1 = crypto:rsa_public_encrypt(Msg, PubKey, rsa_pkcs1_padding), + ?line PKCS1Dec = crypto:rsa_private_decrypt(PKCS1, PrivKey, rsa_pkcs1_padding), + io:format("PKCS1Dec ~p~n",[PKCS1Dec]), + ?line Msg = PKCS1Dec, + + ?line OAEP = crypto:rsa_public_encrypt(Msg, PubKey, rsa_pkcs1_oaep_padding), + ?line Msg = crypto:rsa_private_decrypt(OAEP, PrivKey, rsa_pkcs1_oaep_padding), + + <<Msg2Len:32,_/binary>> = crypto:mpint(Mod), + Msg2 = list_to_binary(lists:duplicate(Msg2Len-1, $X)), + ?line NoPad = crypto:rsa_public_encrypt(Msg2, PubKey, rsa_no_padding), + ?line NoPadDec = crypto:rsa_private_decrypt(NoPad, PrivKey, rsa_no_padding), + ?line NoPadDec = Msg2, + + ShouldBeError = (catch crypto:rsa_public_encrypt(Msg, PubKey, rsa_no_padding)), + ?line {'EXIT', {encrypt_failed,_}} = ShouldBeError, + +%% ?line SSL = crypto:rsa_public_encrypt(Msg, PubKey, rsa_sslv23_padding), +%% ?line Msg = crypto:rsa_private_decrypt(SSL, PrivKey, rsa_sslv23_padding), + + ?line PKCS1_2 = crypto:rsa_private_encrypt(Msg, PrivKey, rsa_pkcs1_padding), + ?line PKCS1_2Dec = crypto:rsa_public_decrypt(PKCS1_2, PubKey, rsa_pkcs1_padding), + io:format("PKCS2Dec ~p~n",[PKCS1_2Dec]), + ?line Msg = PKCS1_2Dec, + + ?line PKCS1_3 = crypto:rsa_private_encrypt(Msg2, PrivKey, rsa_no_padding), + ?line PKCS1_3Dec = crypto:rsa_public_decrypt(PKCS1_3, PubKey, rsa_no_padding), + io:format("PKCS2Dec ~p~n",[PKCS1_3Dec]), + ?line Msg2 = PKCS1_3Dec, + + ?line {'EXIT', {encrypt_failed,_}} = + (catch crypto:rsa_private_encrypt(Msg, PrivKey, rsa_no_padding)), + + ok. + + +dh(doc) -> + ["Test dh (Diffie-Hellman) functions."]; +dh(suite) -> []; +dh(Config) when is_list(Config) -> + Self = self(), + GenP = fun() -> + %% Gen Param may take arbitrary long time to finish + %% That's not a bug in erlang crypto application. + ?line DHPs = crypto:dh_generate_parameters(512,2), + ?line ok = crypto:dh_check(DHPs), + Self ! {param, DHPs} + end, + Pid = spawn(GenP), + receive + {param, DHPs} -> + timer:sleep(100), + io:format("DHP ~p~n", [DHPs]), + ?line {Pub1,Priv1} = crypto:dh_generate_key(DHPs), + io:format("Key1:~n~p~n~p~n~n", [Pub1,Priv1]), + ?line {Pub2,Priv2} = crypto:dh_generate_key(DHPs), + io:format("Key2:~n~p~n~p~n~n", [Pub2,Priv2]), + ?line A = crypto:dh_compute_key(Pub1, Priv2, DHPs), + timer:sleep(100), %% Get another thread see if that triggers problem + ?line B = crypto:dh_compute_key(Pub2, Priv1, DHPs), + io:format("A ~p~n",[A]), + io:format("B ~p~n",[B]), + ?line A = B + after 50000 -> + io:format("Killing Param generation which took to long ~p~n",[Pid]), + exit(Pid, kill) + end. + +%% +%% +exor_test(doc) -> + ["Test the exor function."]; +exor_test(suite) -> + []; +exor_test(Config) when is_list(Config) -> + B = <<1, 2, 3, 4, 5, 6, 7, 8, 9, 10>>, + Z1 = zero_bin(B), + Z1 = crypto:exor(B, B), + B1 = crypto:rand_bytes(100), + B2 = crypto:rand_bytes(100), + Z2 = zero_bin(B1), + Z2 = crypto:exor(B1, B1), + Z2 = crypto:exor(B2, B2), + R = xor_bytes(B1, B2), + R = crypto:exor(B1, B2), + ok. + +%% +%% +rc4_test(doc) -> + ["Test rc4 encryption ."]; +rc4_test(suite) -> + []; +rc4_test(Config) when is_list(Config) -> + CT1 = <<"hej p� dig">>, + R1 = <<71,112,14,44,140,33,212,144,155,47>>, + K = "apaapa", + R1 = crypto:rc4_encrypt(K, CT1), + CT1 = crypto:rc4_encrypt(K, R1), + CT2 = lists:seq(0, 255), + R2 = crypto:rc4_encrypt(K, CT2), + CT2 = binary_to_list(crypto:rc4_encrypt(K, R2)), + ok. + +blowfish_cfb64(doc) -> ["Test Blowfish encrypt/decrypt."]; +blowfish_cfb64(suite) -> []; +blowfish_cfb64(Config) when is_list(Config) -> + Key = <<1,35,69,103,137,171,205,239,240,225,210,195,180,165,150,135>>, + + IVec = <<254,220,186,152,118,84,50,16>>, + Plain = <<"7654321 Now is the time for ">>, + Enc = <<231,50,20,162,130,33,57,202,242,110,207,109,46,185,231,110,61,163,222,4,209,81,114,0,81,157,87,166>>, + + Enc = crypto:blowfish_cfb64_encrypt(Key, IVec, Plain), + Plain = crypto:blowfish_cfb64_decrypt(Key, IVec, Enc), + + Key2 = <<"A2B4C">>, + IVec2 = <<"12345678">>, + Plain2 = <<"badger at my table....!">>, + Enc2 = <<173,76,128,155,70,81,79,228,4,162,188,92,119,53,144,89,93,236,28,164,176,16,138>>, + + Enc2 = crypto:blowfish_cfb64_encrypt(Key2, IVec2, Plain2), + Plain2 = crypto:blowfish_cfb64_decrypt(Key2, IVec2, Enc2). + + +smp(doc) -> "Check concurrent access to crypto driver"; +smp(suite) -> []; +smp(Config) -> + case erlang:system_info(smp_support) of + true -> + NumOfProcs = erlang:system_info(schedulers), + io:format("smp starting ~p workers\n",[NumOfProcs]), + Seeds = [random:uniform(9999) || _ <- lists:seq(1,NumOfProcs)], + Parent = self(), + Pids = [spawn_link(fun()-> worker(Seed,Config,Parent) end) + || Seed <- Seeds], + wait_pids(Pids); + + false -> + {skipped,"No smp support"} + end. + +worker(Seed, Config, Parent) -> + io:format("smp worker ~p, seed=~p~n",[self(),Seed]), + random:seed(Seed,Seed,Seed), + worker_loop(100, Config), + %%io:format("worker ~p done\n",[self()]), + Parent ! self(). + +worker_loop(0, _) -> + ok; +worker_loop(N, Config) -> + Funcs = { md5, md5_update, md5_mac, md5_mac_io, sha, sha_update, des_cbc, + aes_cfb, aes_cbc, des_cbc_iter, rand_uniform_test, + rsa_verify_test, exor_test, rc4_test, mod_exp_test }, + + F = element(random:uniform(size(Funcs)),Funcs), + %%io:format("worker ~p calling ~p\n",[self(),F]), + ?MODULE:F(Config), + worker_loop(N-1,Config). + +wait_pids([]) -> + ok; +wait_pids(Pids) -> + receive + Pid -> + ?line true = lists:member(Pid,Pids), + Others = lists:delete(Pid,Pids), + io:format("wait_pid got ~p, still waiting for ~p\n",[Pid,Others]), + wait_pids(Others) + end. + +%% +%% Help functions +%% + +% match +m(X, X) -> + ?line true. +t(true) -> + true. + +% hexstr2bin +hexstr2bin(S) -> + list_to_binary(hexstr2list(S)). + +hexstr2list([X,Y|T]) -> + [mkint(X)*16 + mkint(Y) | hexstr2list(T)]; +hexstr2list([]) -> + []. + +mkint(C) when $0 =< C, C =< $9 -> + C - $0; +mkint(C) when $A =< C, C =< $F -> + C - $A + 10; +mkint(C) when $a =< C, C =< $f -> + C - $a + 10. + +%% mod_exp in erlang (copied from jungerl's ssh_math.erl) +ipow(A, B, M) when M > 0, B >= 0 -> + if A == 1 -> + 1; + true -> + ipow(A, B, M, 1) + end. + +ipow(A, 1, M, Prod) -> + (A*Prod) rem M; +ipow(_A, 0, _M, Prod) -> + Prod; +ipow(A, B, M, Prod) -> + B1 = B bsr 1, + A1 = (A*A) rem M, + if B - B1 == B1 -> + ipow(A1, B1, M, Prod); + true -> + ipow(A1, B1, M, (A*Prod) rem M) + end. + +%% +%% Invert an element X mod P +%% Calculated as {1, {A,B}} = egcd(X,P), +%% 1 == P*A + X*B == X*B (mod P) i.e B is the inverse element +%% +%% X > 0, P > 0, X < P (P should be prime) +%% +%% invert(X,P) when X > 0, P > 0, X < P -> +%% I = inv(X,P,1,0), +%% if +%% I < 0 -> P + I; +%% true -> I +%% end. + +%% inv(0,_,_,Q) -> Q; +%% inv(X,P,R1,Q1) -> +%% D = P div X, +%% inv(P rem X, X, Q1 - D*R1, R1). + +sized_binary(Binary) when is_binary(Binary) -> + <<(size(Binary)):32/integer, Binary/binary>>; +sized_binary(List) -> + sized_binary(list_to_binary(List)). + +xor_bytes(Bin1, Bin2) when is_binary(Bin1), is_binary(Bin2) -> + L1 = binary_to_list(Bin1), + L2 = binary_to_list(Bin2), + list_to_binary(xor_bytes(L1, L2)); +xor_bytes(L1, L2) -> + xor_bytes(L1, L2, []). + +xor_bytes([], [], Acc) -> + lists:reverse(Acc); +xor_bytes([N1 | Tl1], [N2 | Tl2], Acc) -> + xor_bytes(Tl1, Tl2, [N1 bxor N2 | Acc]). + +zero_bin(N) when is_integer(N) -> + N8 = N * 8, + <<0:N8/integer>>; +zero_bin(B) when is_binary(B) -> + zero_bin(size(B)). diff --git a/lib/debugger/doc/src/Makefile b/lib/debugger/doc/src/Makefile index e6a1de2701..1c0bbaf9d2 100644 --- a/lib/debugger/doc/src/Makefile +++ b/lib/debugger/doc/src/Makefile @@ -39,7 +39,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) XML_APPLICATION_FILES = ref_man.xml XML_REF3_FILES = debugger.xml i.xml int.xml -XML_PART_FILES = part.xml part_notes.xml +XML_PART_FILES = part.xml XML_CHAPTER_FILES = debugger_chapter.xml notes.xml BOOK_FILES = book.xml diff --git a/lib/debugger/doc/src/part_notes.xml b/lib/debugger/doc/src/part_notes.xml deleted file mode 100644 index 60299bbb11..0000000000 --- a/lib/debugger/doc/src/part_notes.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="latin1" ?> -<!DOCTYPE part SYSTEM "part.dtd"> - -<part xmlns:xi="http://www.w3.org/2001/XInclude"> - <header> - <copyright> - <year>2004</year><year>2009</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - </legalnotice> - - <title>Debugger Release Notes</title> - <prepared></prepared> - <docno></docno> - <date>2004-09-07</date> - <rev>1.0</rev> - <file>part_notes.sgml</file> - </header> - <description> - <p><em>Debugger</em> is a graphical tool which can be used for - debugging and testing of Erlang programs. For example, breakpoints - can be set, code can be single stepped and variable values can be - displayed and changed.</p> - </description> - <xi:include href="notes.xml"> -</part> - - diff --git a/lib/debugger/doc/src/warning.gif b/lib/debugger/doc/src/warning.gif Binary files differdeleted file mode 100644 index 96af52360e..0000000000 --- a/lib/debugger/doc/src/warning.gif +++ /dev/null diff --git a/lib/debugger/src/dbg_ui_mon.erl b/lib/debugger/src/dbg_ui_mon.erl index 63cc9b66d1..8888075124 100644 --- a/lib/debugger/src/dbg_ui_mon.erl +++ b/lib/debugger/src/dbg_ui_mon.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% -module(dbg_ui_mon). @@ -429,8 +429,7 @@ gui_cmd('Back Trace Size...', State) -> %% Help Menu gui_cmd('Debugger', State) -> - HelpFile = filename:join([code:lib_dir(debugger), - "doc", "html", "part_frame.html"]), + HelpFile = filename:join([code:lib_dir(debugger), "doc", "html", "index.html"]), Window = dbg_ui_mon_win:get_window(State#state.win), tool_utils:open_help(Window, HelpFile), State; diff --git a/lib/debugger/src/dbg_wx_filedialog_win.erl b/lib/debugger/src/dbg_wx_filedialog_win.erl index d883438639..9687efa981 100644 --- a/lib/debugger/src/dbg_wx_filedialog_win.erl +++ b/lib/debugger/src/dbg_wx_filedialog_win.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2009-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% -module(dbg_wx_filedialog_win). @@ -375,7 +375,8 @@ show_completion(Wanted, State = #state{text=TC, win=Win, list=LC, completion=Com Start = length(Wanted), wxTextCtrl:setValue(TC, Path++"/"), wxTextCtrl:setInsertionPoint(TC, Start), - wxTextCtrl:setSelection(TC, Start, -1), + Last = wxTextCtrl:getLastPosition(TC), + wxTextCtrl:setSelection(TC, Start, Last), destroy_completion(Comp), wxWindow:setFocus(TC), State#state{ptext=Path, completion=undefined}; @@ -399,7 +400,7 @@ show_completion(Wanted, State = #state{text=TC, win=Win, list=LC, completion=Com LB = wxListBox:new(Temp, ?COMPLETION_WIN, [{style, ?wxLB_SINGLE}, {choices, Files}, {size, Size}]), - wxListBox:connect(LB, command_listbox_doubleclicked), + %% wxListBox:connect(LB, command_listbox_doubleclicked), wxListBox:connect(LB, command_listbox_selected), wxWindow:show(Temp), wxWindow:setFocus(TC), diff --git a/lib/debugger/src/dbg_wx_mon.erl b/lib/debugger/src/dbg_wx_mon.erl index d81069ec90..3f55c38d35 100644 --- a/lib/debugger/src/dbg_wx_mon.erl +++ b/lib/debugger/src/dbg_wx_mon.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -144,7 +144,7 @@ init2(CallingPid, Mode, SFile, GS) -> win = Win, focus = undefined, - coords = {0,0}, + coords = {20,20}, intdir = element(2, file:get_cwd()), pinfos = [], @@ -442,8 +442,7 @@ gui_cmd('Back Trace Size...', State) -> %% Help Menu gui_cmd('Debugger', State) -> - HelpFile = filename:join([code:lib_dir(debugger), - "doc", "html", "part_frame.html"]), + HelpFile = filename:join([code:lib_dir(debugger), "doc", "html", "index.html"]), Window = dbg_wx_mon_win:get_window(State#state.win), dbg_wx_win:open_help(Window, HelpFile), State; diff --git a/lib/debugger/src/dbg_wx_mon_win.erl b/lib/debugger/src/dbg_wx_mon_win.erl index dfb327fa6a..8ad4f4213f 100644 --- a/lib/debugger/src/dbg_wx_mon_win.erl +++ b/lib/debugger/src/dbg_wx_mon_win.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -104,7 +104,7 @@ create_win_batch(Title, Menus) -> Hlb = 200, Listbox = wxListBox:new(Panel, ?wxID_ANY, [{size,{?Wf,Hlb}}, {style,?wxLB_SINGLE}]), - wxSizer:add(LeftSz,Listbox,[{border, 3}]), + wxSizer:add(LeftSz,Listbox,[{proportion,1}, {border,3}]), wxListBox:connect(Listbox, command_listbox_doubleclicked), wxListBox:connect(Listbox, right_down), diff --git a/lib/debugger/src/dbg_wx_trace_win.erl b/lib/debugger/src/dbg_wx_trace_win.erl index 6e7a291493..3799acdc1b 100755 --- a/lib/debugger/src/dbg_wx_trace_win.erl +++ b/lib/debugger/src/dbg_wx_trace_win.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -571,7 +571,7 @@ update_bindings(#winInfo{bind=#sub{out=BA}}, Bs) -> wx:foldl(fun({Var,Val},Row) -> wxListCtrl:insertItem(BA, Row, ""), wxListCtrl:setItem(BA, Row, 0, dbg_wx_win:to_string(Var)), - wxListCtrl:setItem(BA, Row, 1, dbg_wx_win:to_string("~200p",[Val])), + wxListCtrl:setItem(BA, Row, 1, dbg_wx_win:to_string("~500P",[Val, 80])), Row+1 end, 0, Bs), put(bindings,Bs), diff --git a/lib/debugger/src/dbg_wx_win.erl b/lib/debugger/src/dbg_wx_win.erl index f029990aa4..faf3cc178f 100644 --- a/lib/debugger/src/dbg_wx_win.erl +++ b/lib/debugger/src/dbg_wx_win.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -75,7 +75,8 @@ create_menus(MB, [{Title,Items}|Ms], Win, Id0) -> Id = create_menu_item(Menu, Items, Win, Id0, true), wxMenuBar:append(MB,Menu,menu_name(Title,ignore)), create_menus(MB,Ms,Win,Id); -create_menus(_MB,[], _Win,Id) -> Id. +create_menus(_MB,[], _Win,Id) -> + Id. create_menu_item(Menu, [separator|Is], Win, Id,Connect) -> wxMenu:appendSeparator(Menu), @@ -102,10 +103,14 @@ create_menu_item(Menu, [{Name, _N, cascade, Items}|Is], Win, Id0,Connect) -> [{id,Id0},{lastId, Id-1},{callback,Filter}]), create_menu_item(Menu, Is, Win, Id, Connect); create_menu_item(Menu, [{Name,Pos}|Is], Win, Id, Connect) -> - Item = wxMenu:append(Menu, Id, menu_name(Name,Pos)), + MenuId = case lists:member(Name, ['Debugger']) of + true -> ?wxID_HELP; + _ -> Id + end, + Item = wxMenu:append(Menu, MenuId, menu_name(Name,Pos)), put(Name,Item), if Connect -> - wxMenu:connect(Win, command_menu_selected, [{id,Id},{userData, Name}]); + wxMenu:connect(Win, command_menu_selected, [{id,MenuId},{userData, Name}]); true -> ignore end, create_menu_item(Menu,Is,Win,Id+1, Connect); @@ -308,6 +313,8 @@ to_string(Format,Args) -> menu_name(Atom, N) when is_atom(Atom) -> menu_name(atom_to_list(Atom),N); +menu_name("Help", _) -> %% Mac needs this to be exactly this + "&Help"; menu_name(Str, Pos) when is_integer(Pos) -> {S1,S2} = lists:split(Pos,Str), S1 ++ [$&|S2]; diff --git a/lib/erl_docgen/priv/xsl/db_eix.xsl b/lib/erl_docgen/priv/xsl/db_eix.xsl new file mode 100644 index 0000000000..929272256a --- /dev/null +++ b/lib/erl_docgen/priv/xsl/db_eix.xsl @@ -0,0 +1,206 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + # + # %CopyrightBegin% + # + # Copyright Ericsson AB 2009. All Rights Reserved. + # + # The contents of this file are subject to the Erlang Public License, + # Version 1.1, (the "License"); you may not use this file except in + # compliance with the License. You should have received a copy of the + # Erlang Public License along with this software. If not, it can be + # retrieved online at http://www.erlang.org/. + # + # Software distributed under the License is distributed on an "AS IS" + # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + # the License for the specific language governing rights and limitations + # under the License. + # + # %CopyrightEnd% + + --> + +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:fn="http://www.w3.org/2005/02/xpath-functions"> + + <xsl:output method="text" encoding="UTF-8" indent="no"/> + + <!-- Book --> + <xsl:template match="/book"> + <xsl:text>%% %% Search data file for </xsl:text><xsl:value-of select="$appname"/><xsl:text> </xsl:text><xsl:value-of select="$appver"/> + <xsl:text> %% generated </xsl:text><xsl:value-of select="$gendate"/><xsl:text> %% </xsl:text> + <xsl:apply-templates select="applications"/> + <xsl:text>{notused, application, ["</xsl:text><xsl:value-of select="$appname"/><xsl:text>"]}. </xsl:text> + </xsl:template> + + <!-- Applications --> + <xsl:template match="applications"> + <xsl:apply-templates name="application"/> + </xsl:template> + + <!-- Reference Manual --> + + <!-- Application --> + <xsl:template match="application"> + <xsl:apply-templates select="erlref|cref|comref|fileref|appref"/> + </xsl:template> + + <!-- Erlref --> + <xsl:template match="erlref"> + <xsl:text>{"</xsl:text><xsl:value-of select="module"/><xsl:text>.html", {function, {"</xsl:text><xsl:value-of select="$appname"/> + <xsl:text>", "</xsl:text><xsl:value-of select="module"/><xsl:text>"}}, [ </xsl:text> + <xsl:apply-templates select="funcs"> + <xsl:with-param name="mod" select="module"/> + </xsl:apply-templates> + <xsl:text>]}. </xsl:text> + <xsl:text>{"</xsl:text><xsl:value-of select="module"/><xsl:text>.html", {module, "</xsl:text> + <xsl:value-of select="$appname"/><xsl:text>"}, ["</xsl:text><xsl:value-of select="module"/><xsl:text>"]}. </xsl:text> + </xsl:template> + + <!-- Cref --> + <xsl:template match="cref"> + <xsl:text>{"</xsl:text><xsl:value-of select="lib"/><xsl:text>.html", {function, {"</xsl:text><xsl:value-of select="$appname"/> + <xsl:text>", "</xsl:text><xsl:value-of select="lib"/><xsl:text>"}}, [ </xsl:text> + <xsl:apply-templates select="funcs"> + <xsl:with-param name="mod" select="lib"/> + </xsl:apply-templates> + <xsl:text>]}. </xsl:text> + <xsl:text>{"</xsl:text><xsl:value-of select="lib"/><xsl:text>.html", {clib, "</xsl:text> + <xsl:value-of select="$appname"/><xsl:text>"}, ["</xsl:text><xsl:value-of select="lib"/><xsl:text>"]}. </xsl:text> + </xsl:template> + + <!-- Comref --> + <xsl:template match="comref"> + <xsl:text>{"</xsl:text><xsl:value-of select="com"/><xsl:text>.html", {command, "</xsl:text> + <xsl:value-of select="$appname"/><xsl:text>"}, ["</xsl:text><xsl:value-of select="com"/><xsl:text>"]}. </xsl:text> + </xsl:template> + + <!-- Fileref --> + <xsl:template match="fileref"> + <xsl:text>{"</xsl:text><xsl:value-of select="file"/><xsl:text>.html", {file, "</xsl:text> + <xsl:value-of select="$appname"/><xsl:text>"}, ["</xsl:text><xsl:value-of select="file"/><xsl:text>"]}. </xsl:text> + </xsl:template> + + <!-- Appref --> + <xsl:template match="appref"> + <xsl:text>{"</xsl:text><xsl:value-of select="app"/><xsl:text>_app.html", {app, "</xsl:text> + <xsl:value-of select="$appname"/><xsl:text>"}, ["</xsl:text><xsl:value-of select="app"/><xsl:text>"]}. </xsl:text> + </xsl:template> + + + <!-- Funcs --> + <xsl:template match="funcs"> + <xsl:param name="mod"/> + <xsl:variable name="lastfuncsblock"> + <xsl:value-of select="position() = last()"/> + </xsl:variable> + <xsl:apply-templates select="func/name"> + <xsl:with-param name="mod" select="$mod"/> + <xsl:with-param name="lastfuncsblock" select="$lastfuncsblock"/> + </xsl:apply-templates> + </xsl:template> + + + + + <xsl:template match="name"> + <xsl:param name="mod"/> + <xsl:param name="lastfuncsblock"/> + + <xsl:variable name="tmpstring"> + <xsl:value-of select="substring-before(substring-after(., '('), '->')"/> + </xsl:variable> + <xsl:variable name="ustring"> + <xsl:choose> + <xsl:when test="string-length($tmpstring) > 0"> + <xsl:call-template name="remove-paren"> + <xsl:with-param name="string" select="$tmpstring"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="remove-paren"> + <xsl:with-param name="string" select="substring-after(., '(')"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="arity"> + <xsl:call-template name="calc-arity"> + <xsl:with-param name="string" select="substring-before($ustring, ')')"/> + <xsl:with-param name="no-of-pars" select="0"/> + </xsl:call-template> + </xsl:variable> + <xsl:variable name="fname"> + <xsl:choose> + <xsl:when test="ancestor::cref"> + <xsl:value-of select="substring-before(nametext, '(')"/> + </xsl:when> + <xsl:when test="ancestor::erlref"> + <xsl:value-of select="substring-before(., '(')"/> + </xsl:when> + </xsl:choose> + </xsl:variable> + <xsl:text> {"</xsl:text><xsl:value-of select="$fname"/> + <xsl:text>", "</xsl:text><xsl:value-of select="$fname"/> + <xsl:text>(</xsl:text><xsl:value-of select="normalize-space($tmpstring)"/> + <xsl:text>", "</xsl:text><xsl:value-of select="$fname"/> + <xsl:text>-</xsl:text><xsl:value-of select="$arity"/><xsl:text>"}</xsl:text> + + <xsl:choose> + <xsl:when test="($lastfuncsblock = 'true') and (position() = last())"> + <xsl:text> </xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>, </xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- Special templates to calculate the arity of functions --> + <xsl:template name="calc-arity"> + <xsl:param name="string"/> + <xsl:param name="no-of-pars"/> + <xsl:variable name="length"> + <xsl:value-of select="string-length($string)"/> + </xsl:variable> + <xsl:choose> + <xsl:when test="$length > 0"> + <xsl:call-template name="calc-arity"> + <xsl:with-param name="string" select="substring-after($string, ',')"/> + <xsl:with-param name="no-of-pars" select="$no-of-pars+1"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$no-of-pars"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="remove-paren"> + <xsl:param name="string"/> + <xsl:variable name="bstring"> + <xsl:value-of select="substring-before($string, '(')"/> + </xsl:variable> + <xsl:choose> + <xsl:when test="string-length($bstring) > 0"> + <xsl:variable name="astring"> + <xsl:value-of select="substring-after($string, ')')"/> + </xsl:variable> + <xsl:variable name="retstring"> + <xsl:call-template name="remove-paren"> + <xsl:with-param name="string" select="$astring"/> + </xsl:call-template> + </xsl:variable> + <xsl:value-of select="concat($bstring, $retstring)"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$string"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- default content handling --> + <xsl:template match="text()"/> + +</xsl:stylesheet> diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl index 3e6f762870..984655fc26 100644 --- a/lib/erl_docgen/priv/xsl/db_html.xsl +++ b/lib/erl_docgen/priv/xsl/db_html.xsl @@ -61,7 +61,7 @@ <xsl:value-of select="$copyright"/> <xsl:value-of select="/book/header/copyright/year[1]"/> <xsl:text>-</xsl:text> - <xsl:value-of select="substring-after(substring-after($gendate, ' '), ' ')"/> + <xsl:value-of select="substring-after(normalize-space(substring-after($gendate, ' ')), ' ')"/> <xsl:text> </xsl:text> <xsl:value-of select="/book/header/copyright/holder"/> </p> diff --git a/lib/erl_interface/configure.in b/lib/erl_interface/configure.in index 80b229c1c3..2f5b5673bb 100644 --- a/lib/erl_interface/configure.in +++ b/lib/erl_interface/configure.in @@ -100,11 +100,11 @@ if test "x$LD" = "x"; then fi AC_SUBST(LD) -AC_CHECK_SIZEOF(short, $erl_xcomp_short) -AC_CHECK_SIZEOF(int, $erl_xcomp_int) -AC_CHECK_SIZEOF(long, $erl_xcomp_long) -AC_CHECK_SIZEOF(void *, $erl_xcomp_void_p) -AC_CHECK_SIZEOF(long long, $erl_xcomp_long_long) +AC_CHECK_SIZEOF(short) +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(long) +AC_CHECK_SIZEOF(void *) +AC_CHECK_SIZEOF(long long) if test $ac_cv_sizeof_void_p = 8; then CFLAGS="$CFLAGS -DEI_64BIT" diff --git a/lib/erl_interface/doc/src/ei_connect.xml b/lib/erl_interface/doc/src/ei_connect.xml index 08e7b122c6..abf705f9e2 100644 --- a/lib/erl_interface/doc/src/ei_connect.xml +++ b/lib/erl_interface/doc/src/ei_connect.xml @@ -619,6 +619,16 @@ typedef struct { <p>These are convenience functions for some common name lookup functions.</p> </desc> </func> + <func> + <name><ret>int</ret><nametext>ei_get_tracelevel(void)</nametext></name> + <name><ret>void</ret><nametext>ei_set_tracelevel(int level)</nametext></name> + <fsummary>Get and set functions for tracing.</fsummary> + <desc> + <p>These functions are used to set tracing on the distribution. The levels are different verbosity levels. A higher level means more information. + See also Debug Information and <c><![CDATA[EI_TRACELEVEL]]></c> below. </p> + <p> <c><![CDATA[ei_set_tracelevel]]></c> and <c><![CDATA[ei_get_tracelevel]]></c> are not thread safe. </p> + </desc> + </func> </funcs> <section> @@ -634,6 +644,17 @@ typedef struct { <item>the environment variable <c><![CDATA[ERL_EPMD_PORT]]></c> is set correctly.</item> </list> + <p>The connection attempt can be traced by setting a tracelevel by either using + <c><![CDATA[ei_set_tracelevel]]></c> or by setting the environment variable <c><![CDATA[EI_TRACELEVEL]]></c>. + The different tracelevels has the following messages:</p> + <list> + <item>1: Verbose error messages</item> + <item>2: Above messages and verbose warning messages </item> + <item>3: Above messages and progress reports for connection handling</item> + <item>4: Above messages and progress reports for communication</item> + <item>5: Above messages and progress reports for data conversion</item> + </list> </section> + </cref> diff --git a/lib/erl_interface/include/ei.h b/lib/erl_interface/include/ei.h index 01272244e1..d1a697615a 100644 --- a/lib/erl_interface/include/ei.h +++ b/lib/erl_interface/include/ei.h @@ -339,7 +339,13 @@ const char *ei_thisalivename(const ei_cnode* ec); erlang_pid *ei_self(ei_cnode* ec); +/* + * settings + */ + void ei_set_compat_rel(unsigned rel); +void ei_set_tracelevel(int); +int ei_get_tracelevel(void); /* * We have erl_gethost*() so we include ei versions as well. diff --git a/lib/erl_interface/src/connect/ei_connect.c b/lib/erl_interface/src/connect/ei_connect.c index 9ac5a93c5a..d2d0a7e7c1 100644 --- a/lib/erl_interface/src/connect/ei_connect.c +++ b/lib/erl_interface/src/connect/ei_connect.c @@ -249,8 +249,22 @@ ei_cnode *ei_fd_to_cnode(int fd) return &sockinfo->cnode; } + +/*************************************************************************** + * Get/Set tracelevel + ***************************************************************************/ + +void ei_set_tracelevel(int level) { + ei_tracelevel = level; +} + +int ei_get_tracelevel(void) { + return ei_tracelevel; +} + + /*************************************************************************** - * XXXX + * Distversion ***************************************************************************/ int ei_distversion(int fd) @@ -1282,8 +1296,6 @@ error: return -1; } -/* FIXME fix the signed/unsigned mess..... */ - static int send_name_or_challenge(int fd, char *nodename, int f_chall, unsigned challenge, diff --git a/lib/erl_interface/src/decode/decode_skip.c b/lib/erl_interface/src/decode/decode_skip.c index 2fc68a3601..316b5bee98 100644 --- a/lib/erl_interface/src/decode/decode_skip.c +++ b/lib/erl_interface/src/decode/decode_skip.c @@ -80,6 +80,7 @@ int ei_skip_term(const char* buf, int* index) if (ei_decode_double(buf, index, NULL) < 0) return -1; break; case ERL_FUN_EXT: + case ERL_NEW_FUN_EXT: if (ei_decode_fun(buf, index, NULL) < 0) return -1; break; default: diff --git a/lib/erl_interface/src/misc/ei_internal.h b/lib/erl_interface/src/misc/ei_internal.h index 9f51d1f61b..f7805efebf 100644 --- a/lib/erl_interface/src/misc/ei_internal.h +++ b/lib/erl_interface/src/misc/ei_internal.h @@ -149,7 +149,7 @@ {if (ei_tracelevel >= 5) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \ ARG5,ARG6,ARG7);} -int ei_tracelevel; +extern int ei_tracelevel; void ei_trace_printf(const char *name, int level, const char *format, ...); diff --git a/lib/erl_interface/test/Makefile b/lib/erl_interface/test/Makefile new file mode 100644 index 0000000000..b7a1a4e4d8 --- /dev/null +++ b/lib/erl_interface/test/Makefile @@ -0,0 +1,78 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1997-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +MODULES= \ + ei_accept_SUITE \ + ei_connect_SUITE \ + ei_decode_SUITE \ + ei_decode_encode_SUITE \ + ei_encode_SUITE \ + ei_format_SUITE \ + ei_print_SUITE \ + ei_tmo_SUITE \ + erl_connect_SUITE \ + erl_eterm_SUITE \ + erl_ext_SUITE \ + erl_format_SUITE \ + erl_match_SUITE \ + port_call_SUITE \ + runner + +SPEC_FILES = \ + erl_interface.spec \ + erl_interface.dynspec \ + erl_interface.spec.vxworks + +ERL_FILES = $(MODULES:%=%.erl) + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/erl_interface_test + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +tests debug opt: + +clean: + +docs: + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: + +release_tests_spec: opt + $(INSTALL_DIR) $(RELSYSDIR) + $(INSTALL_DATA) $(SPEC_FILES) $(ERL_FILES) $(RELSYSDIR) + chmod -f -R u+w $(RELSYSDIR) + @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) + +release_docs_spec: diff --git a/lib/erl_interface/test/Makefile.src b/lib/erl_interface/test/Makefile.src new file mode 100644 index 0000000000..9c620bb8d9 --- /dev/null +++ b/lib/erl_interface/test/Makefile.src @@ -0,0 +1,71 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1997-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ + +LIBPATH = @erl_interface_libpath@ +LIBERL = $(LIBPATH)/@erl_interface_lib@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = $(LIBERL) $(LIBEI) +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../common + +ETERM_OBJS = eterm_test@obj@ eterm_test_decl@obj@ runner@obj@ +EXT_OBJS = ext_test@obj@ ext_test_decl@obj@ runner@obj@ +FORMAT_OBJS = format_test@obj@ format_test_decl@obj@ runner@obj@ +EI_FORMAT_OBJS = ei_format_test@obj@ ei_format_test_decl@obj@ ei_runner@obj@ +EI_PRINT_OBJS = ei_print_test@obj@ ei_print_test_decl@obj@ ei_runner@obj@ +EI_CONNECT_OBJS = ei_connect_test@obj@ ei_connect_test_decl@obj@ ei_runner@obj@ +EI_ACCEPT_OBJS = ei_accept_test@obj@ ei_accept_test_decl@obj@ ei_runner@obj@ +MATCH_OBJS = match_test@obj@ match_test_decl@obj@ runner@obj@ + +PROGS = eterm_test@exe@ format_test@exe@ print_term@exe@ match_test@exe@ ei_format_test@exe@ ei_print_test@exe@ ei_connect_test@exe@ ei_accept_test@exe@ + + +all: $(PROGS) + +eterm_test@exe@: $(ETERM_OBJS) $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o eterm_test $(ETERM_OBJS) $(LIBFLAGS) + +ext_test@exe@: $(EXT_OBJS) $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o ext_test $(EXT_OBJS) $(LIBFLAGS) + +format_test@exe@: $(FORMAT_OBJS) $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o format_test $(FORMAT_OBJS) $(LIBFLAGS) + +ei_format_test@exe@: $(EI_FORMAT_OBJS) $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o ei_format_test $(EI_FORMAT_OBJS) $(LIBFLAGS) + +ei_print_test@exe@: $(EI_PRINT_OBJS) $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o ei_print_test $(EI_PRINT_OBJS) $(LIBFLAGS) + +ei_connect_test@exe@: $(EI_CONNECT_OBJS) $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o ei_connect_test $(EI_CONNECT_OBJS) $(LIBFLAGS) + +ei_accept_test@exe@: $(EI_ACCEPT_OBJS) $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o ei_accept_test $(EI_ACCEPT_OBJS) $(LIBFLAGS) + +match_test@exe@: $(MATCH_OBJS) $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o match_test $(MATCH_OBJS) $(LIBFLGAS) + +print_term@exe@: print_term@obj@ $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o print_term print_term@obj@ $(LIBFLGAS) diff --git a/lib/erl_interface/test/README b/lib/erl_interface/test/README new file mode 100644 index 0000000000..e1af025ca3 --- /dev/null +++ b/lib/erl_interface/test/README @@ -0,0 +1,28 @@ + +One way to create a new suite, copy an old one +that is similar to a new one + + % setenv SIMILAR ei_xyz + % setenv NEW ei_abc + + % ct mkdir ${NEW}_SUITE_data + % ct mkelem ${NEW}_SUITE.erl + % cp ${SIMILAR}_SUITE.erl ${NEW}_SUITE.erl + % cp ${SIMILAR}_SUITE_data/* ${NEW}_SUITE_data/ + % chmod ug+rw ${NEW}_SUITE_data/* + % mv ${NEW}_SUITE_data/${SIMILAR}_test.c ${NEW}_SUITE_data/${NEW}_test.c + % ct mkelem ${NEW}_SUITE_data/* + +Now edit "${NEW}_SUITE.erl" and the files in "${NEW}_SUITE_data/". + +To use a test suite you build it and put the result outside +ClearCase. Then you create soft links to the ClearCase elements. + + % setenv SRC /clearcase/otp/erts/lib/erl_interface/test + % setenv DST /ldisk/test + % cd $SRC + % clearmake -V release TESTROOT=$DST + % foreach f (`find . -type f`) + foreach> \rm -f /ldisk/test/erl_interface_test/$f + foreach> ln -s $SRC/$f $DST/erl_interface_test/$f + foreach> end diff --git a/lib/erl_interface/test/all_SUITE_data/Makefile.first b/lib/erl_interface/test/all_SUITE_data/Makefile.first new file mode 100644 index 0000000000..b9ce689057 --- /dev/null +++ b/lib/erl_interface/test/all_SUITE_data/Makefile.first @@ -0,0 +1,20 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2003-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# +all: + erlc -W init_tc.erl diff --git a/lib/erl_interface/test/all_SUITE_data/Makefile.src b/lib/erl_interface/test/all_SUITE_data/Makefile.src new file mode 100644 index 0000000000..9be2360656 --- /dev/null +++ b/lib/erl_interface/test/all_SUITE_data/Makefile.src @@ -0,0 +1,45 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2003-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = .@DS@gccifier@exe@ -CC"$(CC0)" +CFLAGS0 = @CFLAGS@ -I@erl_interface_include@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ +EI_COMMON_OBJS = runner@obj@ ei_runner@obj@ +ALL_OBJS = gccifier@exe@ $(EI_COMMON_OBJS) + +CP=cp +CHMOD=chmod + +all: $(ALL_OBJS) + +@IFEQ@ (@erl_interface_cross_compile@, true) +gccifier@exe@: + $(CP) gccifier.sh gccifier@exe@ + $(CHMOD) a+x gccifier@exe@ +@ELSE@ +gccifier@exe@: gccifier.c + $(CC0) $(CFLAGS0) -o gccifier@exe@ gccifier.c +@ENDIF@ + +clean: + $(RM) $(EI_COMMON_OBJS) + $(RM) init_tc.beam + $(RM) gccifier@exe@ diff --git a/lib/erl_interface/test/all_SUITE_data/ei_runner.c b/lib/erl_interface/test/all_SUITE_data/ei_runner.c new file mode 100644 index 0000000000..205f911e38 --- /dev/null +++ b/lib/erl_interface/test/all_SUITE_data/ei_runner.c @@ -0,0 +1,400 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#ifndef __WIN32__ +#include <unistd.h> +#endif +#include <stdarg.h> + +#include "ei_runner.h" + +#ifndef __WIN32__ +#define _O_BINARY 0 +#define _setmode(fd, mode) +#endif + +#define HEADER_SIZE 4 + +static char* progname; /* Name of this program (from argv[0]). */ +static int fd_from_erl; /* File descriptor from Erlang. */ +static int fd_to_erl; /* File descriptor to Erlang. */ + +static int packet_loop(); +static void ensure_buf_big_enough(); +static int readn(); +static void reply(char* buf, unsigned size); +static void dump(); + +void +run_tests(char* argv0, TestCase test_cases[], unsigned number) +{ + int i; + int n; + char* packet; + + progname = argv0; + _setmode(0, _O_BINARY); + _setmode(1, _O_BINARY); + fd_from_erl = 0; + fd_to_erl = 1; + + packet = read_packet(&n); + + /* + * Dispatch to the appropriate test function. + */ + + i = packet[0] * 256 + packet[1]; + if (i >= number) { + fprintf(stderr, "%s: bad test case number %d", + progname, i); + free(packet); + exit(1); + } else { + (*test_cases[i])(); + free(packet); + } +} + + +/*********************************************************************** + * + * R e a d i n g p a c k e t s + * + ************************************************************************/ + +/* + * Reads an Erlang term. + * + * Only accepts 't' (term) or 'e' (end of test), + * exits program on error + * returns 1 on 'e', 0 on 't' + */ +int get_bin_term(ei_x_buff* x, ei_term* term) +{ + int len, version; + + ei_x_free(x); + x->buff = read_packet(&len); + x->buffsz = len; + x->index = 0; + switch (x->buff[x->index++]) { + case 'e': + return 1; + case 't': + if (ei_decode_version(x->buff, &x->index, &version) < 0 + || ei_decode_ei_term(x->buff, &x->index, term) < 0) { + fail("Failed to decode term"); + exit(0); + } + return 0; + default: + fprintf(stderr, "Garbage received: "); + dump(x->buff, len, 16); + putc('\n', stderr); + fail("C program received garbage"); + exit(1); + } +} + + +/* + * Reads a packet from Erlang. The packet must be a standard {packet, 2} + * packet. This function aborts if any error is detected (including EOF). + * + * Returns: The number of bytes in the packet. + */ + +char *read_packet(int *len) +{ + + unsigned char* io_buf = NULL; /* Buffer for file i/o. */ + int i; + unsigned char header[HEADER_SIZE]; + unsigned packet_length; /* Length of current packet. */ + int bytes_read; + + /* + * Read the packet header. + */ + + bytes_read = readn(fd_from_erl, header, HEADER_SIZE); + + if (bytes_read == 0) { + fprintf(stderr, "%s: Unexpected end of file\n", progname); + exit(1); + } + if (bytes_read != HEADER_SIZE) { + fprintf(stderr, "%s: Failed to read packet header\n", progname); + exit(1); + } + + /* + * Get the length of this packet. + */ + + packet_length = 0; + + for (i = 0; i < HEADER_SIZE; i++) + packet_length = (packet_length << 8) | header[i]; + + if (len) *len=packet_length; /* report length only if caller requested it */ + + if ((io_buf = (char *) malloc(packet_length)) == NULL) { + fprintf(stderr, "%s: insufficient memory for i/o buffer of size %d\n", + progname, packet_length); + exit(1); + } + + /* + * Read the packet itself. + */ + + bytes_read = readn(fd_from_erl, io_buf, packet_length); + if (bytes_read != packet_length) { + fprintf(stderr, "%s: couldn't read packet of length %d\r\n", + progname, packet_length); + free(io_buf); + exit(1); + } + + return io_buf; +} + + +/*********************************************************************** + * S e n d i n g r e p l i e s + * + * The functions below send various types of replies back to Erlang. + * Each reply start with a letter indicating the type of reply. + * + * Reply Translated to on Erlang side + * ----- ---------------------------- + * [$b|Bytes] {bytes, Bytes} + * [$e] eot + * [$f] test_server:fail() + * [$f|Reason] test_server:fail(Reason) + * [$t|EncodedTerm] {term, Term} + * [$N] 'NULL' + * [$m|Message] io:format("~s", [Message]) (otherwise ignored) + * + ***********************************************************************/ + +/* + * This function reports the outcome of a test fail. It is useful if + * you implement a test case entirely in C code. + * + * If the ok argument is zero, a [$f] reply will be sent to the + * Erlang side (causing test_server:fail() to be called); otherwise, + * the atom 'eot' will be sent to Erlang. + * + * If you need to provide more details on a failure, use the fail() function. + */ + +void +do_report(file, line, ok) + char* file; + int line; + int ok; /* Zero if failed; non-zero otherwise. */ +{ + char reason; + /*unsigned long ab; + unsigned long fb;*/ + + reason = ok ? 'e' : 'f'; + + if (!ok) { + do_fail(file, line, "Generic failure"); + } else { + /* release all unallocated blocks */ + /*erl_eterm_release();*/ + /* check mem usage stats */ + /*erl_eterm_statistics(&ab, &fb);*/ + /*if ((ab == 0) && (fb == 0) ) {*/ + reply(&reason, 1); + /*} + else { + char sbuf[128]; + + sprintf(sbuf, "still %lu terms allocated," + " %lu on freelist at end of test", ab, fb); + do_fail(file, line, sbuf); + }*/ + } +} + + +/* + * This function causes a call to test_server:fail(Reason) on the + * Erlang side. + */ + +void do_fail(char* file, int line, char* reason) +{ + char sbuf[2048]; + + sbuf[0] = 'f'; + sprintf(sbuf+1, "%s, line %d: %s", file, line, reason); + reply(sbuf, 1+strlen(sbuf+1)); +} + +/* + * This function sends a message to the Erlang side. + * The message will be written to the test servers log file, + * but will otherwise be completly ignored. + */ + +void message(char* format, ...) +{ + va_list ap; + char sbuf[1024]; + + sbuf[0] = 'm'; + va_start(ap, format); + vsprintf(sbuf+1, format, ap); + va_end(ap); + + reply(sbuf, 1+strlen(sbuf+1)); +} + +/* + * This function sends the given binary term to the Erlang side, + * where it will be received as {term, Term} (prefix 't'). + */ +void send_bin_term(ei_x_buff* x) +{ + ei_x_buff x2; + ei_x_new(&x2); + x2.buff[x2.index++] = 't'; + ei_x_append(&x2, x); + reply(x2.buff, x2.index); + ei_x_free(&x2); +} + +/* + * This function sends a raw buffer of data to the + * Erlang side, where it will be received as {bytes, Bytes} (prefix 'b'). + */ +void send_buffer(char* buf, int size) +{ + char* send_buf; + + send_buf = (char *) malloc(size+1); + send_buf[0] = 'b'; + memcpy(send_buf+1, buf, size); + reply(send_buf, size+1); + free(send_buf); +} + +/*********************************************************************** + * + * P r i v a t e h e l p e r s + * + ***********************************************************************/ + +/* + * Sends a packet back to Erlang. + */ +static void reply(char* reply_buf, unsigned size) +{ + int n; /* Temporary to hold size. */ + int i; /* Loop counter. */ + char* buf; + + + buf = (char *) malloc(size+HEADER_SIZE); + memcpy(buf+HEADER_SIZE, reply_buf, size); + + /* + * Fill the header starting with the least significant byte. + */ + n = size; + for (i = HEADER_SIZE-1; i >= 0; i--) { + buf[i] = (char) n; /* Store least significant byte. */ + n = n >> 8; + } + + size += HEADER_SIZE; + write(fd_to_erl, buf, size); + free(buf); +} + + +/* + * Reads len number of bytes. + */ + +static int +readn(fd, buf, len) + int fd; /* File descriptor to read from. */ + unsigned char *buf; /* Store in this buffer. */ + int len; /* Number of bytes to read. */ +{ + int n; /* Byte count in last read call. */ + int sofar = 0; /* Bytes read so far. */ + + do { + if ((n = read(fd, buf+sofar, len-sofar)) <= 0) + /* error or EOF in read */ + return(n); + sofar += n; + } while (sofar < len); + return sofar; +} + +void +dump(buf, sz, max) + unsigned char* buf; + int sz; + int max; +{ + int i, imax; + char comma[5] = ","; + + if (!sz) + return; + if (sz > max) + imax = max; + else + imax = sz; + + for (i=0; i<imax; i++) { + if (i == imax-1) { + if (sz > max) + strcpy(comma, ",..."); + else + comma[0] = 0; + } + if (isdigit(buf[i])) + fprintf(stderr, "%u%s", (int)(buf[i]), comma); + else { + if (isalpha(buf[i])) { + fprintf(stderr, "%c%s", buf[i], comma); + } + else + fprintf(stderr, "%u%s", (int)(buf[i]), comma); + } + } +} + diff --git a/lib/erl_interface/test/all_SUITE_data/ei_runner.h b/lib/erl_interface/test/all_SUITE_data/ei_runner.h new file mode 100644 index 0000000000..96d6a1cbf7 --- /dev/null +++ b/lib/erl_interface/test/all_SUITE_data/ei_runner.h @@ -0,0 +1,61 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#include "ei.h" + +typedef void (*TestCase)(void); + +#define TESTCASE(name) void name(void) +#define ASIZE(a) (sizeof(a)/sizeof(a[0])) + +void run_tests(char* argv0, TestCase cases[], unsigned number); + +#ifndef _MSC_VER +# define ll(val) (val##LL) +#else /* assume gcc or C99 */ +# define ll(val) (val##i64) +#endif + +#ifndef _MSC_VER +# define ull(val) (val##LL) +#else /* assume gcc or C99 */ +# define ull(val) (val##i64) +#endif + +/* + * Reading. + */ + +int get_bin_term(ei_x_buff* x, ei_term* term); +char *read_packet(int *len); + +/* + * Sending replies. + */ + +#define fail(reason) do_fail(__FILE__, __LINE__, reason) +#define report(ok) do_report(__FILE__, __LINE__, ok) + +void do_report(char* file, int line, int ok); +void do_fail(char* file, int line, char* reason); +void send_buffer(char* buf, int size); +void message(char* format, ...); + +void send_bin_term(ei_x_buff* x); + diff --git a/lib/erl_interface/test/all_SUITE_data/gccifier.c b/lib/erl_interface/test/all_SUITE_data/gccifier.c new file mode 100644 index 0000000000..9f556fc4ed --- /dev/null +++ b/lib/erl_interface/test/all_SUITE_data/gccifier.c @@ -0,0 +1,317 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2005-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ + +/* + * A compiler wrapper that translate (some) gcc command line arguments + * to the Visual C++ compiler and (of course) the gcc compiler. It also + * makes some changes in the command line arguments when debug compiling. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> + + +#if !defined(__WIN32__) +#define USE_EXEC +#include <unistd.h> +#endif + + +#ifdef __WIN32__ +#define EOL "\r\n" +#else +#define EOL "\n" +#endif + +#define ARGS_INCR 20 + +static char *prog; + +typedef struct { + char **vec; + int no; + int ix; + int chars; +} args_t; + +static void +enomem(void) +{ + fprintf(stderr, "%s: Out of memory%s", prog, EOL); + exit(1); +} + +static void +save_arg(args_t *args, char *arg1, ...) +{ + char *carg; + va_list argp; + + va_start(argp, arg1); + carg = arg1; + while (carg) { + if (args->no <= args->ix) { + args->vec = (char **) (args->no + ? realloc((void *) args->vec, + (sizeof(char *) + *(args->no + ARGS_INCR + 1))) + : malloc((sizeof(char *) + *(args->no + ARGS_INCR + 1)))); + if (!args->vec) + enomem(); + args->no += ARGS_INCR; + } + args->vec[args->ix++] = carg; + args->chars += strlen(carg); + carg = va_arg(argp, char *); + } + args->vec[args->ix++] = " "; + args->chars++; + va_end(argp); +} + +static int +is_prefix(char *prfx, char **str) +{ + int i; + for (i = 0; prfx[i] && (*str)[i]; i++) { + if (prfx[i] != (*str)[i]) + return 0; + } + if (!prfx[i]) { + *str = &(*str)[i]; + return 1; + } + return 0; +} + +static void +cpy(char **dst, char *src) +{ + int i; + for (i = 0; src[i]; i++) + (*dst)[i] = src[i]; + *dst = &(*dst)[i]; +} + +typedef enum { + STDLIB_NONE, + STDLIB_MD, + STDLIB_ML, + STDLIB_MT +} stdlib_t; + +int +main(int argc, char *argv[]) +{ + int res; + int i; + size_t cmd_len; + char *cmd; + char *cmd_end; + char *cc = NULL; + args_t args = {0}; + int is_debug = 0; + int is_purify = 0; + int is_quantify = 0; + int is_purecov = 0; +#ifdef __WIN32__ + int is_shared = 0; + stdlib_t stdlib = STDLIB_NONE; + char *shared_flag = ""; + char *stdlib_flag = ""; + int have_link_args = 0; + args_t link_args = {0}; + +#define CHECK_FIRST_LINK_ARG \ + if (!have_link_args) { \ + save_arg(&link_args, "-link", NULL); \ + have_link_args = 1; \ + } +#else /* #ifdef __WIN32__ */ +#define CHECK_FIRST_LINK_ARG +#endif /* #ifdef __WIN32__ */ + + prog = argv[0]; + + + for (i = 1; i < argc; i++) { + char *arg = argv[i]; + if (is_prefix("-CC", &arg)) { + cc = arg; + } + else if (is_prefix("-O", &arg)) { + if (!is_debug) + save_arg(&args, argv[i], NULL); + } + else if (strcmp("-DDEBUG", arg) == 0) { + save_arg(&args, arg, NULL); +#ifdef __WIN32__ + set_debug: +#endif + if (!is_debug) { + int j; + is_debug = 1; +#ifdef __WIN32__ + save_arg(&args, "-Z7", NULL); + CHECK_FIRST_LINK_ARG; + save_arg(&link_args, "-debug", NULL); + save_arg(&link_args, "-pdb:none", NULL); +#endif + for (j = 0; j < args.ix; j++) { + char *tmp_arg = args.vec[j]; + if (is_prefix("-O", &tmp_arg)) + args.vec[j] = ""; + } + } + } + else if (strcmp("-DPURIFY", arg) == 0) { + save_arg(&args, arg, NULL); + is_purify = 1; + } + else if (strcmp("-DQUANTIFY", arg) == 0) { + save_arg(&args, arg, NULL); + is_quantify = 1; + } + else if (strcmp("-DPURECOV", arg) == 0) { + save_arg(&args, arg, NULL); + is_purecov = 1; + } +#ifdef __WIN32__ + else if (strcmp("-g", arg) == 0) { + goto set_debug; + } + else if (strcmp("-MD", arg) == 0) + stdlib = STDLIB_MD; + else if (strcmp("-MDd", arg) == 0) { + stdlib = STDLIB_MD; + goto set_debug; + } + else if (strcmp("-ML", arg) == 0) + stdlib = STDLIB_ML; + else if (strcmp("-MLd", arg) == 0) { + stdlib = STDLIB_ML; + goto set_debug; + } + else if (strcmp("-MT", arg) == 0) + stdlib = STDLIB_MT; + else if (strcmp("-MTd", arg) == 0) { + stdlib = STDLIB_MT; + goto set_debug; + } + else if (strcmp("-shared", arg) == 0 || strcmp("-LD", arg) == 0) + is_shared = 1; + else if (strcmp("-LDd", arg) == 0) { + is_shared = 1; + goto set_debug; + } + else if (strcmp("-Wall", arg) == 0) { + save_arg(&args, "-W3", NULL); + } + else if (is_prefix("-L", &arg)) { + CHECK_FIRST_LINK_ARG; + save_arg(&link_args, "-libpath:", arg, NULL); + } +#endif /* #ifdef __WIN32__ */ + else if (is_prefix("-l", &arg)) { + CHECK_FIRST_LINK_ARG; + if (is_debug && strcmp("ethread", arg) == 0) + arg = "ethread.debug"; + else if (is_purify && strcmp("ethread", arg) == 0) + arg = "ethread.purify"; + else if (is_quantify && strcmp("ethread", arg) == 0) + arg = "ethread.quantify"; + else if (is_purecov && strcmp("ethread", arg) == 0) + arg = "ethread.purecov"; +#ifdef __WIN32__ + else if (strcmp("socket", arg) == 0) + arg = "ws2_32"; + save_arg(&link_args, arg, ".lib", NULL); +#else + save_arg(&args, "-l", arg, NULL); +#endif + } + else + save_arg(&args, argv[i], NULL); + } + + if (!cc || !cc[0]) { + fprintf(stderr, "%s: Missing compulsory -CC flag%s", prog, EOL); + exit(1); + } + + cmd_len = strlen(cc) + 1 + args.chars + 1; + +#ifdef __WIN32__ + if (is_shared) + shared_flag = is_debug ? "-LDd " : "-LD "; + switch (stdlib) { + case STDLIB_MD: stdlib_flag = is_debug ? "-MDd " : "-MD "; break; + case STDLIB_ML: stdlib_flag = is_debug ? "-MLd " : "-ML "; break; + case STDLIB_MT: stdlib_flag = is_debug ? "-MTd " : "-MT "; break; + case STDLIB_NONE: break; + } + + cmd_len += strlen(shared_flag) + strlen(stdlib_flag) + link_args.chars; +#endif + + cmd = (char *) malloc(sizeof(char) * cmd_len); + + if (!cmd) + enomem(); + cmd_end = cmd; + cpy(&cmd_end, cc); + cpy(&cmd_end, " "); +#ifdef __WIN32__ + cpy(&cmd_end, stdlib_flag); + cpy(&cmd_end, shared_flag); +#endif + for (i = 0; i < args.ix; i++) + cpy(&cmd_end, args.vec[i]); +#ifdef __WIN32__ + for (i = 0; i < link_args.ix; i++) + cpy(&cmd_end, link_args.vec[i]); +#endif + *cmd_end = '\0'; + + printf("==> %s%s", cmd, EOL); + fflush(stdout); + +#ifdef USE_EXEC + (void) execl("/bin/sh", "sh", "-c", cmd, (char *) NULL); + perror(NULL); + res = 1; +#else + res = system(cmd); +#endif + + free((void *) args.vec); +#ifdef __WIN32__ + free((void *) link_args.vec); +#endif + free((void *) cmd); + + if (res < 0) + res = 1; + return res; +} diff --git a/lib/erl_interface/test/all_SUITE_data/gccifier.sh b/lib/erl_interface/test/all_SUITE_data/gccifier.sh new file mode 100755 index 0000000000..42253213b1 --- /dev/null +++ b/lib/erl_interface/test/all_SUITE_data/gccifier.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2005-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +CC=`echo "$1" | sed -e "s/-CC//"` +shift +echo "->" +echo "$CC $*" +$CC $* +echo "" diff --git a/lib/erl_interface/test/all_SUITE_data/init_tc.erl b/lib/erl_interface/test/all_SUITE_data/init_tc.erl new file mode 100644 index 0000000000..8157d590fc --- /dev/null +++ b/lib/erl_interface/test/all_SUITE_data/init_tc.erl @@ -0,0 +1,101 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(init_tc). + +-export([run/1]). + +%% The argument should be a list of filenames (atoms), without extension +%% A .c extension is assumed. +%% + +run([Name|Rest]) -> + case catch run1(atom_to_list(Name)) of + {'EXIT', Reason} -> + io:format("Failed: ~p~n", [Reason]), + halt(1); + _Other -> + run(Rest) + end; +run([]) -> + ok. + +run1(Name) -> + CFile = Name ++ ".c", + {ok, Bin} = file:read_file(CFile), + String = binary_to_list(Bin), + + %% This ConstPart stuff is because you can't retrieve part of a match. + %% Long live Perl! + + ConstPart = "\nTESTCASE\\(", + ConstPartLen = 10, + {match, Matches} = regexp:matches(String, ConstPart++"[_a-zA-Z]*"), + Cases = get_names(Matches, ConstPartLen, Bin, []), + generate(Name, Cases). + +get_names([{Start, Length}|Rest], Skip, Bin, Result) -> + Name = binary_to_list(Bin, Start+Skip, Start+Length-1), + get_names(Rest, Skip, Bin, [Name|Result]); +get_names([], _Skip, _Bin, Result) -> + lists:reverse(Result). + +generate(TcName, Cases) -> + Hrl = TcName ++ "_cases.hrl", + {ok, HrlFile} = file:open(Hrl, write), + {ok, Dir} = file:get_cwd(), + generate_hrl(Cases, HrlFile, {filename:join(Dir, TcName), 0}), + file:close(HrlFile), + C = TcName ++ "_decl.c", + {ok, CFile} = file:open(C, write), + generate_c(Cases, CFile, TcName), + file:close(CFile). + +generate_hrl([Case|Rest], File, {Name, Number}) -> + io:format(File, "-define(~s, {\"~s\", ~w}).~n", [Case, Name, Number]), + generate_hrl(Rest, File, {Name, Number+1}); +generate_hrl([], _, _) -> + ok. + +generate_c(Cases, File, TcName) -> + E= case lists:prefix("ei_", TcName) of + true -> "ei_"; + false -> "" + end, + io:format(File, "#include \"~srunner.h\"\n", [E]), + lists:foreach( + fun(Case) -> + io:format(File, "extern void ~s(void);~n", + [Case]) end, + Cases), + io:format(File, "~nstatic TestCase test_cases[] = {~n", []), + lists:foreach(fun(Case) -> io:format(File, " ~s,~n", [Case]) end, Cases), + io:format(File, "~s", + [["};\n\n", + "#ifdef VXWORKS\n", + "int ", TcName, "(int argc, char* argv[])\n", + "#else\n", + "int main(int argc, char* argv[])\n", + "#endif\n", + "{\n", + " run_tests(argv[0], test_cases, ", + "sizeof(test_cases)/sizeof(test_cases[0]));\n", + " return 0;\n", + "}\n"]]). diff --git a/lib/erl_interface/test/all_SUITE_data/reclaim.h b/lib/erl_interface/test/all_SUITE_data/reclaim.h new file mode 100644 index 0000000000..00fdfc38dc --- /dev/null +++ b/lib/erl_interface/test/all_SUITE_data/reclaim.h @@ -0,0 +1,151 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#ifndef _RECLAIM_H +#define _RECLAIM_H + + +/* The Erlang release for VxWorks includes a simple mechanism for + "resource reclamation" at task exit - it allows replacement of the + functions that open/close "files" and malloc/free memory with versions + that keep track, to be able to "reclaim" file descriptors and memory + when a task exits (regardless of *how* it exits). + + The interface to this mechanism is made available via this file, + with the following caveats: + + - The interface may change (or perhaps even be removed, though that + isn't likely until VxWorks itself provides similar functionality) + in future releases - i.e. you must always use the version of this + file that comes with the Erlang release you are using. + + - Disaster is guaranteed if you use the mechanism incorrectly (see + below for the correct way), e.g. allocate memory with the "tracking" + version of malloc() and free it with the "standard" version of free(). + + - The mechanism (of course) incurs some performance penalty - thus + for a simple program you may be better off with careful programming, + making sure that you do whatever close()/free()/etc calls that are + appropriate at all exit points (though if you need to guard against + taskDelete() etc, things get messy...). + + To use the mechanism, simply program your application normally, i.e. + use open()/close()/malloc()/free() etc as usual, but #include this + file before any usage of the relevant functions. NOTE: To avoid the + "disaster" mentioned above, you *must* #include it in *all* (or none) + of the files that manipulate a particular file descriptor, allocated + memory area, etc. + + Before any task that uses this utility is loaded (which includes the + erlang emulator), the reclaim.o object file has to be loaded and + the function reclaim_init() has to be called. reclaim_init should be called + only _ONCE_ in a systems lifetime and has only a primitive guard + against multiple calls (i.e. a global variable is checked). Therefore + the initialization should occur either in the start script of the system + or (even better) in the usrInit() part of system initialization. The + object file itself should be loaded only once, so linking it with the + kernel is a good idea, linking with each application is an extremely bad + dito. Make really sure that it's loaded _before_ any application that + uses it if You want to load it in the startup script. + + If You dont want to have #define's for the posix/stdio names + of the file/memory operations (i.e. no #define malloc save_malloc etc), + #define RECLAIM_NO_ALIAS in Your source before reclaim.h is included. +*/ + +#include <vxWorks.h> /* STATUS, size_t */ +#include <sockLib.h> /* struct sockaddr */ +#include <stdio.h> /* FILE */ + +#if defined(__STDC__) +#define _RECLAIM_DECL_FUN(RetType, FunName, ParamList) \ +extern RetType FunName##ParamList +#define _RECLAIM_VOID_PTR void * +#define _RECLAIM_VOID_PARAM void +#define _RECLAIM_VOID_RETURN void +#elif defined(__cplusplus) +#define _RECLAIM_DECL_FUN(RetType, FunName, ParamList) \ +extern "C" RetType FunName##ParamList +#define _RECLAIM_VOID_PTR void * +#define _RECLAIM_VOID_PARAM +#define _RECLAIM_VOID_RETURN void +#else +#define _RECLAIM_DECL_FUN(RetType, FunName, Ignore) extern RetType FunName() +#define DECLARE_FUNCTION_TYPE(RetType, Type, PList) typedef RetType (* Type)() +#define _RECLAIM_VOID_PTR char * +#define _RECLAIM_VOID_PARAM +#define _RECLAIM_VOID_RETURN +#endif /* __STDC__ / __cplusplus */ + +/* Initialize the facility, on a per system basis. */ +_RECLAIM_DECL_FUN(STATUS, reclaim_init, (_RECLAIM_VOID_PARAM)); + +/* File descriptor operations */ +_RECLAIM_DECL_FUN(int,save_open,(char *, int, ...)); +_RECLAIM_DECL_FUN(int,save_creat,(char *, int)); +_RECLAIM_DECL_FUN(int,save_socket,(int, int, int)); +_RECLAIM_DECL_FUN(int,save_accept,(int, struct sockaddr *, int *)); +_RECLAIM_DECL_FUN(int,save_close,(int)); +/* Interface to add an fd to what's reclaimed even though it's not open with + one of the above functions */ +_RECLAIM_DECL_FUN(_RECLAIM_VOID_RETURN, save_fd, (int fd)); +#ifndef RECLAIM_NO_ALIAS +#define open save_open +#define creat save_creat +#define socket save_socket +#define accept save_accept +#define close save_close +#endif +/* Stdio file operations */ +_RECLAIM_DECL_FUN(FILE *, save_fopen, (char *, char *)); +_RECLAIM_DECL_FUN(FILE *, save_fdopen, (int, char *)); +_RECLAIM_DECL_FUN(FILE *, save_freopen, (char *, char *, FILE *)); +_RECLAIM_DECL_FUN(int, save_fclose, (FILE *)); +/* XXX Should do opendir/closedir too... */ +#ifndef RECLAIM_NO_ALIAS +#define fopen save_fopen +#define fdopen save_fdopen +#define freopen save_freopen +#define fclose save_fclose +#endif +/* Memory allocation */ +_RECLAIM_DECL_FUN(_RECLAIM_VOID_PTR, save_malloc, (size_t)); +_RECLAIM_DECL_FUN(_RECLAIM_VOID_PTR, save_calloc, (size_t, size_t)); +_RECLAIM_DECL_FUN(_RECLAIM_VOID_PTR, save_realloc, + (_RECLAIM_VOID_PTR, size_t)); +_RECLAIM_DECL_FUN(void, save_free, (_RECLAIM_VOID_PTR)); +_RECLAIM_DECL_FUN(void, save_cfree, (_RECLAIM_VOID_PTR)); +#ifndef RECLAIM_NO_ALIAS +#define malloc save_malloc +#define calloc save_calloc +#define realloc save_realloc +#define free save_free +#define cfree save_cfree +#endif +/* Generic interfaces to malloc etc... */ +_RECLAIM_DECL_FUN(_RECLAIM_VOID_PTR, plain_malloc, (size_t)); +_RECLAIM_DECL_FUN(_RECLAIM_VOID_PTR, plain_realloc, + (_RECLAIM_VOID_PTR, size_t)); +_RECLAIM_DECL_FUN(void, plain_free, (_RECLAIM_VOID_PTR)); +#endif /* _RECLAIM_H */ + + + + diff --git a/lib/erl_interface/test/all_SUITE_data/runner.c b/lib/erl_interface/test/all_SUITE_data/runner.c new file mode 100644 index 0000000000..24df0f5f40 --- /dev/null +++ b/lib/erl_interface/test/all_SUITE_data/runner.c @@ -0,0 +1,457 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1997-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#ifndef __WIN32__ +#include <unistd.h> +#endif +#include <stdarg.h> + +#include "runner.h" + +#ifndef __WIN32__ +#define _O_BINARY 0 +#define _setmode(fd, mode) +#endif + +#define HEADER_SIZE 4 + +static char* progname; /* Name of this program (from argv[0]). */ +static int fd_from_erl; /* File descriptor from Erlang. */ +static int fd_to_erl; /* File descriptor to Erlang. */ + +static int packet_loop(); +static void ensure_buf_big_enough(); +static int readn(); +static void reply(char* buf, unsigned size); +static void dump(); + +void +run_tests(char* argv0, TestCase test_cases[], unsigned number) +{ + int i; + int n; + char* packet; + + progname = argv0; + _setmode(0, _O_BINARY); + _setmode(1, _O_BINARY); + fd_from_erl = 0; + fd_to_erl = 1; + + packet = read_packet(&n); + + /* + * Dispatch to the appropriate test function. + */ + + i = packet[0] * 256 + packet[1]; + if (i >= number) { + fprintf(stderr, "%s: bad test case number %d", + progname, i); + free(packet); + exit(1); + } else { + (*test_cases[i])(); + free(packet); + } +} + + +/*********************************************************************** + * + * R e a d i n g p a c k e t s + * + ************************************************************************/ + +/* + * Reads an Erlang term. + * + * Returns: A pointer to a term (an ETERM structure) if there was + * at term available, or a NULL pointer if there was an 'eot' (end-of-test) + * packet. Aborts if anything else received. + */ + +ETERM* +get_term(void) +{ + char* encoded; + ETERM* term; + int n; + + encoded = read_packet(&n); + + switch (encoded[0]) { + case 'e': + free(encoded); + return NULL; + case 't': + term = erl_decode(encoded+1); + free(encoded); + if (term == NULL) { + fail("Failed to decode term"); + exit(0); + } + return term; + default: + fprintf(stderr, "Garbage received: "); + dump(encoded, n, 16); + putc('\n', stderr); + fail("C program received garbage"); + free(encoded); + exit(1); + } +} + + +/* + * Reads a packet from Erlang. The packet must be a standard {packet, 2} + * packet. This function aborts if any error is detected (including EOF). + * + * Returns: The number of bytes in the packet. + */ + +char *read_packet(int *len) +{ + + unsigned char* io_buf = NULL; /* Buffer for file i/o. */ + int i; + unsigned char header[HEADER_SIZE]; + unsigned packet_length; /* Length of current packet. */ + int bytes_read; + + /* + * Read the packet header. + */ + + bytes_read = readn(fd_from_erl, header, HEADER_SIZE); + + if (bytes_read == 0) { + fprintf(stderr, "%s: Unexpected end of file\n", progname); + exit(1); + } + if (bytes_read != HEADER_SIZE) { + fprintf(stderr, "%s: Failed to read packet header\n", progname); + exit(1); + } + + /* + * Get the length of this packet. + */ + + packet_length = 0; + + for (i = 0; i < HEADER_SIZE; i++) + packet_length = (packet_length << 8) | header[i]; + + if (len) *len=packet_length; /* report length only if caller requested it */ + + if ((io_buf = (char *) malloc(packet_length)) == NULL) { + fprintf(stderr, "%s: insufficient memory for i/o buffer of size %d\n", + progname, packet_length); + exit(1); + } + + /* + * Read the packet itself. + */ + + bytes_read = readn(fd_from_erl, io_buf, packet_length); + if (bytes_read != packet_length) { + fprintf(stderr, "%s: couldn't read packet of length %d\r\n", + progname, packet_length); + free(io_buf); + exit(1); + } + + return io_buf; +} + + +/*********************************************************************** + * S e n d i n g r e p l i e s + * + * The functions below send various types of replies back to Erlang. + * Each reply start with a letter indicating the type of reply. + * + * Reply Translated to on Erlang side + * ----- ---------------------------- + * [$b|Bytes] {bytes, Bytes} + * [$e] eot + * [$f] test_server:fail() + * [$f|Reason] test_server:fail(Reason) + * [$t|EncodedTerm] {term, Term} + * [$N] 'NULL' + * [$m|Message] io:format("~s", [Message]) (otherwise ignored) + * + ***********************************************************************/ + +/* + * This function reports the outcome of a test fail. It is useful if + * you implement a test case entirely in C code. + * + * If the ok argument is zero, a [$f] reply will be sent to the + * Erlang side (causing test_server:fail() to be called); otherwise, + * the atom 'eot' will be sent to Erlang. + * + * If you need to provide more details on a failure, use the fail() function. + */ + +void +do_report(file, line, ok) + char* file; + int line; + int ok; /* Zero if failed; non-zero otherwise. */ +{ + char reason; + unsigned long ab; + unsigned long fb; + + reason = ok ? 'e' : 'f'; + + if (!ok) { + do_fail(file, line, "Generic failure"); + } else { + /* release all unallocated blocks */ + erl_eterm_release(); + /* check mem usage stats */ + erl_eterm_statistics(&ab, &fb); + if ((ab == 0) && (fb == 0) ) { + reply(&reason, 1); + } + else { + char sbuf[128]; + + sprintf(sbuf, "still %lu terms allocated," + " %lu on freelist at end of test", ab, fb); + do_fail(file, line, sbuf); + } + } +} + + +/* + * This function causes a call to test_server:fail(Reason) on the + * Erlang side. + */ + +void +do_fail(char* file, int line, char* reason) +{ + char sbuf[2048]; + + sbuf[0] = 'f'; + sprintf(sbuf+1, "%s, line %d: %s", file, line, reason); + reply(sbuf, 1+strlen(sbuf+1)); +} + +/* + * This function sends a message to the Erlang side. + * The message will be written to the test servers log file, + * but will otherwise be completly ignored. + */ + +void +message(char* format, ...) +{ + va_list ap; + char sbuf[1024]; + + sbuf[0] = 'm'; + va_start(ap, format); + vsprintf(sbuf+1, format, ap); + va_end(ap); + + reply(sbuf, 1+strlen(sbuf+1)); +} + +/* + * This function sends the given term to the Erlang side, + * where it will be received as {term, Term}. + * + * If the given pointer is NULL (indicating an invalid term), + * the result on the Erlang side will be the atom 'NULL'. + * + * After sending the term, this function frees the term by + * calling erl_free_term(). + */ + +void +send_term(term) + ETERM* term; /* Term to be sent to Erlang side. */ +{ + char encoded[64*1024]; + int n; + + if (term == NULL) { + encoded[0] = 'N'; + n = 1; + } else { + encoded[0] = 't'; + n = 1 + erl_encode(term, encoded+1); + erl_free_term(term); + } + reply(encoded, n); +} + +#if 0 + +/* Seriously broken!!! */ + +void +send_bin_term(x_ei_buff* x) +{ + x_ei_buff x2; + x_ei_new(&x2); + x2.buff[x2.index++] = 't'; + x_ei_append(&x2, x); + reply(x2.buff, x2.index); + free(x2.buff); +} +#endif + +/* + * This function sends a raw buffer of data to the + * Erlang side, where it will be received as {bytes, Bytes}. + */ + +void +send_buffer(buf, size) + char* buf; /* Buffer with bytes to send to Erlang. */ + int size; /* Size of data to send to Erlang. */ +{ + char* send_buf; + + send_buf = (char *) malloc(size+1); + send_buf[0] = 'b'; + memcpy(send_buf+1, buf, size); + reply(send_buf, size+1); + free(send_buf); +} + +/*********************************************************************** + * + * P r i v a t e h e l p e r s + * + ***********************************************************************/ + +/* + * Sends a packet back to Erlang. + */ + +static void +reply(reply_buf, size) + char* reply_buf; /* Buffer with reply. */ + unsigned size; /* Size of reply. */ +{ + int n; /* Temporary to hold size. */ + int i; /* Loop counter. */ + char* buf; + + + buf = (char *) malloc(size+HEADER_SIZE); + memcpy(buf+HEADER_SIZE, reply_buf, size); + + /* + * Fill the header starting with the least significant byte. + */ + + n = size; + for (i = HEADER_SIZE-1; i >= 0; i--) { + buf[i] = (char) n; /* Store least significant byte. */ + n = n >> 8; + } + + size += HEADER_SIZE; +/* + fprintf(stderr, "\r\nReply size: %u\r\n", + (unsigned)buf[0] << 8 + (unsigned)buf[1]); + + for (i = 0; i < size; i++) { + fprintf(stderr,"%u %c\r\n",buf[i],buf[i]); + } + + fprintf(stderr, "\r\n"); +*/ + write(fd_to_erl, buf, size); + free(buf); +} + + +/* + * Reads len number of bytes. + */ + +static int +readn(fd, buf, len) + int fd; /* File descriptor to read from. */ + unsigned char *buf; /* Store in this buffer. */ + int len; /* Number of bytes to read. */ +{ + int n; /* Byte count in last read call. */ + int sofar = 0; /* Bytes read so far. */ + + do { + if ((n = read(fd, buf+sofar, len-sofar)) <= 0) + /* error or EOF in read */ + return(n); + sofar += n; + } while (sofar < len); + return sofar; +} + +void +dump(buf, sz, max) + unsigned char* buf; + int sz; + int max; +{ + int i, imax; + char comma[5] = ","; + + if (!sz) + return; + if (sz > max) + imax = max; + else + imax = sz; + + for (i=0; i<imax; i++) { + if (i == imax-1) { + if (sz > max) + strcpy(comma, ",..."); + else + comma[0] = 0; + } + if (isdigit(buf[i])) + fprintf(stderr, "%u%s", (int)(buf[i]), comma); + else { + if (isalpha(buf[i])) { + fprintf(stderr, "%c%s", buf[i], comma); + } + else + fprintf(stderr, "%u%s", (int)(buf[i]), comma); + } + } +} + diff --git a/lib/erl_interface/test/all_SUITE_data/runner.h b/lib/erl_interface/test/all_SUITE_data/runner.h new file mode 100644 index 0000000000..fb29d5166d --- /dev/null +++ b/lib/erl_interface/test/all_SUITE_data/runner.h @@ -0,0 +1,50 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1997-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#include "erl_interface.h" + +typedef void (*TestCase)(void); + +#define TESTCASE(name) void name(void) +#define ASIZE(a) (sizeof(a)/sizeof(a[0])) + +void run_tests(char* argv0, TestCase cases[], unsigned number); + +/* + * Reading. + */ + +ETERM* get_term(void); +char *read_packet(int *len); + +/* + * Sending replies. + */ + +#define fail(reason) do_fail(__FILE__, __LINE__, reason) +#define report(ok) do_report(__FILE__, __LINE__, ok) + +void do_report(char* file, int line, int ok); +void do_fail(char* file, int line, char* reason); +void send_term(ETERM* term); +void send_buffer(char* buf, int size); +void message(char* format, ...); + +void send_bin_term(ei_x_buff* x); + diff --git a/lib/erl_interface/test/ei_accept_SUITE.erl b/lib/erl_interface/test/ei_accept_SUITE.erl new file mode 100644 index 0000000000..bc83d6a62e --- /dev/null +++ b/lib/erl_interface/test/ei_accept_SUITE.erl @@ -0,0 +1,151 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(ei_accept_SUITE). + +-include("test_server.hrl"). +-include("ei_accept_SUITE_data/ei_accept_test_cases.hrl"). + +-export([all/1, init_per_testcase/2, fin_per_testcase/2, + ei_accept/1, ei_threaded_accept/1]). + +-import(runner, [get_term/1,send_term/2]). + +all(suite) -> [ei_accept, ei_threaded_accept]. + +init_per_testcase(_Case, Config) -> + Dog = ?t:timetrap(?t:minutes(0.25)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +ei_accept(Config) when is_list(Config) -> + ?line P = runner:start(?interpret), + ?line 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0), + +% ?line AMsg={a,[message, with], " strings in it!", [-12, -23], 1.001}, + %% shouldn't this be a bif or function or something? + ?line Myname= hd(tl(string:tokens(atom_to_list(node()), "@"))), + ?line io:format("Myname ~p ~n", [Myname]), + ?line EINode= list_to_atom("c42@"++Myname), + ?line io:format("EINode ~p ~n", [EINode]), + ?line Self= self(), + ?line TermToSend= {call, Self, "Test"}, + ?line F= fun() -> + timer:sleep(500), + {any, EINode} ! TermToSend, + Self ! sent_ok, + ok + end, + + ?line spawn(F), + ?line Port = 6543, + ?line {ok, Fd, _Node} = ei_accept(P, Port), + ?line TermReceived= ei_receive(P, Fd), + ?line io:format("Sent ~p received ~p ~n", [TermToSend, TermReceived]), + ?line TermToSend= TermReceived, + ?line receive + sent_ok -> + ok; + Unknown -> + io:format("~p ~n", [Unknown]) + after 1000 -> + io:format("timeout ~n") + end, + ?line ok= ei_unpublish(P), + ok. + +ei_threaded_accept(Config) when is_list(Config) -> + ?line Einode = filename:join(?config(data_dir, Config), "eiaccnode"), + ?line N = 1, % 3, + ?line Host = atom_to_list(node()), + ?line Port = 6767, + ?line start_einode(Einode, N, Host, Port), + ?line io:format("started eiaccnode"), + %%?line spawn_link(fun() -> start_einode(Einode, N, Host, Port) end), + ?line TestServerPid = self(), + ?line [ spawn_link(fun() -> send_rec_einode(I, TestServerPid) end) + || I <- lists:seq(0, N-1) ], + ?line [ receive I -> ok end + || I <- lists:seq(0, N-1) ], + ok. + +send_rec_einode(N, TestServerPid) -> + ?line Myname= hd(tl(string:tokens(atom_to_list(node()), "@"))), + ?line EINode= list_to_atom("eiacc" ++ integer_to_list(N) ++ "@" ++ Myname), + ?line io:format("EINode ~p ~n", [EINode]), + ?line Self= self(), + ?line timer:sleep(10*1000), + ?line {any, EINode} ! Self, + ?line receive + {N,_}=X -> + ?line io:format("Received by ~s ~p~n", [EINode, X]), + ?line TestServerPid ! N, + ?line X + after 10000 -> + ?line test_server:fail(EINode) + end. + +start_einode(Einode, N, Host, Port) -> + Einodecmd = Einode ++ " " ++ atom_to_list(erlang:get_cookie()) + ++ " " ++ integer_to_list(N) ++ " " ++ Host ++ " " + ++ integer_to_list(Port) ++ " nothreads", + io:format("Einodecmd ~p ~n", [Einodecmd]), + ?line open_port({spawn, Einodecmd}, []), + ok. + + + +%%% Interface functions for ei (erl_interface) functions. + +ei_connect_init(P, Num, Cookie, Creation) -> + send_command(P, ei_connect_init, [Num,Cookie,Creation]), + case get_term(P) of + {term,Int} when is_integer(Int) -> Int + end. + +ei_accept(P, PortNo) -> + send_command(P, ei_accept, [PortNo]), + case get_term(P) of + {term,{Fd, _, Node}} when Fd >= 0 -> {ok, Fd, Node}; + {term,{_Fd, Errno, _Node}} -> {error,Errno} + end. + +ei_receive(P, Fd) -> + send_command(P, ei_receive, [Fd]), + {term, T}= get_term(P), + T. + +ei_unpublish(P) -> + send_command(P, ei_unpublish, []), + case get_term(P) of + {term,{0, _}} -> ok; + {term,{_X, Errno}} -> {error,Errno} + end. + +send_command(P, Name, Args) -> + runner:send_term(P, {Name,list_to_tuple(Args)}). + + + + diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.first b/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.first new file mode 100644 index 0000000000..d7ec976cd0 --- /dev/null +++ b/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.first @@ -0,0 +1,21 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +ei_accept_test_decl.c: ei_accept_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run ei_accept_test -s erlang halt diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src new file mode 100644 index 0000000000..9b751d8f65 --- /dev/null +++ b/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src @@ -0,0 +1,45 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \ + $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + @erl_interface_threadlib@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data +EI_ACCEPT_OBJS = ei_accept_test@obj@ ei_accept_test_decl@obj@ +EIACCNODE_OBJS = eiaccnode@obj@ + +all: ei_accept_test@exe@ eiaccnode@exe@ + +clean: + $(RM) $(EI_ACCEPT_OBJS) $(EIACCNODE_OBJS) + $(RM) ei_accept_test@exe@ eiaccnode@exe@ + +ei_accept_test@exe@: $(EI_ACCEPT_OBJS) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(EI_ACCEPT_OBJS) $(LIBFLAGS) + + +eiaccnode@exe@: $(EIACCNODE_OBJS) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(EIACCNODE_OBJS) $(LIBFLAGS) diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c new file mode 100644 index 0000000000..5f898b5944 --- /dev/null +++ b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c @@ -0,0 +1,224 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* + * Purpose: Tests the accept function in ei_connect.c. + * Author: Jakob Cederlund (taken from erl_connect by Bj�rn Gustavsson) + * + * See the ei_accept_SUITE.erl file for a "table of contents". + */ + +#include <stdio.h> +#include <string.h> +#ifdef VXWORKS +#include "reclaim.h" +#endif + +#ifdef __WIN32__ +#include <winsock2.h> +#include <windows.h> +#else +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#endif + +#include "ei_runner.h" + +static void cmd_ei_connect_init(char* buf, int len); +static void cmd_ei_accept(char* buf, int len); +static void cmd_ei_receive(char* buf, int len); +static void cmd_ei_unpublish(char* buf, int len); + +static void send_errno_result(int value); + +ei_cnode ec; + + +static struct { + char* name; + int num_args; /* Number of arguments. */ + void (*func)(char* buf, int len); +} commands[] = { + "ei_connect_init", 3, cmd_ei_connect_init, + "ei_accept", 1, cmd_ei_accept, + "ei_receive", 1, cmd_ei_receive, + "ei_unpublish", 0, cmd_ei_unpublish +}; + +/* + * Sends a list contaning all data types to the Erlang side. + */ +TESTCASE(interpret) +{ + ei_x_buff x; + int i; + ei_term term; + + ei_x_new(&x); + for (;;) { + if (get_bin_term(&x, &term)) { + report(1); + return; + } else { + char* buf = x.buff, func[MAXATOMLEN]; + int index = x.index, arity; + if (term.ei_type != ERL_SMALL_TUPLE_EXT || term.arity != 2) + fail("term should be a tuple of size 2"); + if (ei_decode_atom(buf, &index, func) < 0) + fail("function name should be an atom"); + if (ei_decode_tuple_header(buf, &index, &arity) != 0) + fail("function arguments should be a tuple"); + for (i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) { + if (strcmp(func, commands[i].name) == 0) { + if (arity != commands[i].num_args) + fail("wrong number of arguments"); + commands[i].func(buf + index, x.buffsz - index); + break; + } + } + if (i >= sizeof(commands)/sizeof(commands[0])) { + message("\"%d\" \n", func); + fail("bad command"); + } + } + } +} + +static void cmd_ei_connect_init(char* buf, int len) +{ + int index = 0, r = 0; + int type, size; + long l; + char b[100]; + char cookie[MAXATOMLEN], * cp = cookie; + ei_x_buff res; + if (ei_decode_long(buf, &index, &l) < 0) + fail("expected int"); + sprintf(b, "c%d", l); + /* FIXME don't use internal and maybe use skip?! */ + ei_get_type_internal(buf, &index, &type, &size); + if (ei_decode_atom(buf, &index, cookie) < 0) + fail("expected atom (cookie)"); + if (cookie[0] == '\0') + cp = NULL; + r = ei_connect_init(&ec, b, cp, 0); + ei_x_new_with_version(&res); + ei_x_encode_long(&res, r); + send_bin_term(&res); + ei_x_free(&res); +} + +static int my_listen(int port) +{ + int listen_fd; + struct sockaddr_in addr; + const char *on = "1"; + + if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return -1; + + setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, on, sizeof(on)); + + memset((void*) &addr, 0, (size_t) sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(listen_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0) + return -1; + + listen(listen_fd, 5); + return listen_fd; +} + +static void cmd_ei_accept(char* buf, int len) +{ + int index = 0; + int listen, r; + ErlConnect conn; + long port; + ei_x_buff x; + int i; + + /* get port */ + if (ei_decode_long(buf, &index, &port) < 0) + fail("expected int (port)"); + /* Make a listen socket */ + if ((listen = my_listen(port)) <= 0) + fail("listen"); + + if ((i = ei_publish(&ec, port)) == -1) + fail("ei_publish"); +#ifdef VXWORKS + save_fd(i); +#endif + r = ei_accept(&ec, listen, &conn); +#ifdef VXWORKS + save_fd(r); +#endif + /* send result, errno and nodename */ + ei_x_new_with_version(&x); + ei_x_encode_tuple_header(&x, 3); + ei_x_encode_long(&x, r); + ei_x_encode_long(&x, erl_errno); + ei_x_encode_atom(&x, conn.nodename); /* or rather string? */ + send_bin_term(&x); + ei_x_free(&x); +} + +static void cmd_ei_receive(char* buf, int len) +{ + ei_x_buff x; + erlang_msg msg; + long l; + int fd, index = 0; + + if (ei_decode_long(buf, &index, &l) < 0) + fail("expected int (fd)"); + fd = l; + ei_x_new(&x); + for (;;) { + int got = ei_xreceive_msg(fd, &msg, &x); + if (got == ERL_TICK) + continue; + if (got == ERL_ERROR) + fail("ei_xreceive_msg"); + break; + } + index = 1; + send_bin_term(&x); + ei_x_free(&x); +} + +static void cmd_ei_unpublish(char* buf, int len) +{ + send_errno_result(ei_unpublish(&ec)); +} + +static void send_errno_result(int value) +{ + ei_x_buff x; + ei_x_new_with_version(&x); + ei_x_encode_tuple_header(&x, 2); + ei_x_encode_long(&x, value); + ei_x_encode_long(&x, erl_errno); + send_bin_term(&x); + ei_x_free(&x); +} diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c b/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c new file mode 100644 index 0000000000..af58f75963 --- /dev/null +++ b/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c @@ -0,0 +1,234 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* to test multiple threads in ei */ + +#include <stdlib.h> +#include <stdio.h> + +#ifdef __WIN32__ +#include <winsock2.h> +#include <windows.h> +#include <process.h> +#else +#ifndef VXWORKS +#include <pthread.h> +#endif +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#endif + +#include "ei.h" + +#ifdef VXWORKS +#include <vxWorks.h> +#include <sockLib.h> +#include <inetLib.h> +#define MAIN cnode +#else +#define MAIN main +#endif + +static int my_listen(int port); + +/* + A small einode. + To be called from the test case ei_accept_SUITE:multi_thread + usage: eiaccnode <cookie> <n> + + - start threads 0..n-1 + - in each thread + - listen on "ei0" .. "ei<n-1>" + - wait for connection + - receive a pid + - send {i, <pid>} back + - shutdown gracefully +*/ + +static const char* cookie, * desthost; +static int port; /* actually base port */ + +#ifndef SD_SEND +#ifdef SHUTWR +#define SD_SEND SHUT_WR +#else +#define SD_SEND 1 +#endif +#endif + +#ifndef __WIN32__ +#define closesocket(fd) close(fd) +#endif + +#ifdef __WIN32__ +static DWORD WINAPI +#else +static void* +#endif + einode_thread(void* num) +{ + int n = (int)num; + ei_cnode ec; + char myname[100], destname[100]; + int r, fd, listen; + ErlConnect conn; + erlang_msg msg; +/* FILE* f;*/ + + sprintf(myname, "eiacc%d", n); + printf("thread %d (%s) listening\n", n, myname, destname); + r = ei_connect_init(&ec, myname, cookie, 0); + if ((listen = my_listen(port+n)) <= 0) { + printf("listen err\n"); + exit(7); + } + if (ei_publish(&ec, port + n) == -1) { + printf("ei_publish port %d\n", port+n); + exit(8); + } + fd = ei_accept(&ec, listen, &conn); + printf("ei_accept %d\n", fd); + if (fd >= 0) { + ei_x_buff x, xs; + int index, version; + erlang_pid pid; + + ei_x_new(&x); + for (;;) { + int got = ei_xreceive_msg(fd, &msg, &x); + if (got == ERL_TICK) + continue; + if (got == ERL_ERROR) { + printf("receive error %d\n", n); + return 0; + } + printf("received %d\n", got); + break; + } + index = 0; + if (ei_decode_version(x.buff, &index, &version) != 0) { + printf("ei_decode_version %d\n", n); + return 0; + } + if (ei_decode_pid(x.buff, &index, &pid) != 0) { + printf("ei_decode_pid %d\n", n); + return 0; + } +/* fprintf(f, "got pid from %s \n", pid.node);*/ + ei_x_new_with_version(&xs); + ei_x_encode_tuple_header(&xs, 2); + ei_x_encode_long(&xs, n); + ei_x_encode_pid(&xs, &pid); + r = ei_send(fd, &pid, xs.buff, xs.index); +/* fprintf(f, "sent %d bytes %d\n", xs.index, r);*/ + shutdown(fd, SD_SEND); + closesocket(fd); + ei_x_free(&x); + ei_x_free(&xs); + } else { + printf("coudn't connect fd %d r %d\n", fd, r); + } + printf("done thread %d\n", n); +/* fclose(f);*/ + return 0; +} + +MAIN(int argc, char *argv[]) +{ + int i, n, no_threads; +#ifndef VXWORKS +#ifdef __WIN32__ + HANDLE threads[100]; +#else + pthread_t threads[100]; +#endif +#endif + + if (argc < 3) + exit(1); + + cookie = argv[1]; + n = atoi(argv[2]); + if (n > 100) + exit(2); + desthost = argv[3]; + port = atoi(argv[4]); +#ifndef VXWORKS + no_threads = argv[5] != NULL && strcmp(argv[5], "nothreads") == 0; +#else + no_threads = 1; +#endif + for (i = 0; i < n; ++i) { + if (!no_threads) { +#ifndef VXWORKS +#ifdef __WIN32__ + unsigned tid; + threads[i] = (HANDLE)_beginthreadex(NULL, 0, einode_thread, + (void*)i, 0, &tid); +#else + pthread_create(&threads[i], NULL, einode_thread, (void*)i); +#endif +#else + ; +#endif + } else + einode_thread((void*)i); + } + + if (!no_threads) +#ifndef VXWORKS + for (i = 0; i < n; ++i) { +#ifdef __WIN32__ + if (WaitForSingleObject(threads[i], INFINITE) != WAIT_OBJECT_0) +#else + if (pthread_join(threads[i], NULL) != 0) +#endif + printf("bad wait thread %d\n", i); + } +#else + ; +#endif + printf("ok\n"); + return 0; +} + +static int my_listen(int port) +{ + int listen_fd; + struct sockaddr_in addr; + const char *on = "1"; + + if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return -1; + + setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, on, sizeof(on)); + + memset((void*) &addr, 0, (size_t) sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(listen_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0) + return -1; + + listen(listen_fd, 5); + return listen_fd; +} + diff --git a/lib/erl_interface/test/ei_connect_SUITE.erl b/lib/erl_interface/test/ei_connect_SUITE.erl new file mode 100644 index 0000000000..56f478edad --- /dev/null +++ b/lib/erl_interface/test/ei_connect_SUITE.erl @@ -0,0 +1,218 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(ei_connect_SUITE). + +-include("test_server.hrl"). +-include("ei_connect_SUITE_data/ei_connect_test_cases.hrl"). + +-export([ + all/1, + init_per_testcase/2, + fin_per_testcase/2, + + ei_send/1, + ei_reg_send/1, + ei_rpc/1, + rpc_test/1, + ei_send_funs/1, + ei_threaded_send/1, + ei_set_get_tracelevel/1 + ]). + +-import(runner, [get_term/1,send_term/2]). + +all(suite) -> [ ei_send, + ei_reg_send, + ei_rpc, + ei_send_funs, + ei_threaded_send, + ei_set_get_tracelevel]. + +init_per_testcase(_Case, Config) -> + Dog = ?t:timetrap(?t:minutes(0.25)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +ei_send(Config) when is_list(Config) -> + ?line P = runner:start(?interpret), + ?line 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0), + ?line {ok,Fd} = ei_connect(P, node()), + + ?line ok = ei_send(P, Fd, self(), AMsg={a,message}), + ?line receive AMsg -> ok end, + + ?line runner:send_eot(P), + ?line runner:recv_eot(P), + ok. + +ei_send_funs(Config) when is_list(Config) -> + ?line P = runner:start(?interpret), + ?line 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0), + ?line {ok,Fd} = ei_connect(P, node()), + + ?line Fun1 = fun ei_send/1, + ?line Fun2 = fun(X) -> P, X, Fd, Fun1 end, + + ?line AMsg={Fun1,Fun2}, + %%AMsg={wait_with_funs, new_dist_format}, + ?line ok = ei_send_funs(P, Fd, self(), AMsg), + ?line EIMsg = receive M -> M end, + ?line EIMsg = AMsg, + + ?line runner:send_eot(P), + ?line runner:recv_eot(P), + ok. + +ei_reg_send(Config) when is_list(Config) -> + ?line P = runner:start(?interpret), + ?line 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0), + ?line {ok,Fd} = ei_connect(P, node()), + + ARegName = a_strange_registred_name, + ?line register(ARegName, self()), + ?line ok = ei_reg_send(P, Fd, ARegName, AMsg={another,[strange],message}), + ?line receive AMsg -> ok end, + + ?line runner:send_eot(P), + ?line runner:recv_eot(P), + ok. + +ei_threaded_send(Config) when is_list(Config) -> + ?line Einode = filename:join(?config(data_dir, Config), "einode"), + ?line N = 15, + ?line Host = atom_to_list(node()), + ?line spawn_link(fun() -> start_einode(Einode, N, Host) end), + ?line TestServerPid = self(), + ?line [ spawn_link(fun() -> rec_einode(I, TestServerPid) end) + || I <- lists:seq(0, N-1) ], + ?line [ receive I -> ok end + || I <- lists:seq(0, N-1) ], + ok. + +rec_einode(N, TestServerPid) -> + ?line Regname = list_to_atom("mth"++integer_to_list(N)), + ?line register(Regname, self()), + ?line io:format("~p waiting~n", [Regname]), + ?line receive + X -> + ?line io:format("Received by ~s ~p~n", [Regname, X]), + ?line TestServerPid ! N, + ?line X + after 10000 -> + ?line test_server:fail(Regname) + end. + +start_einode(Einode, N, Host) -> + Einodecmd = Einode ++ " " ++ atom_to_list(erlang:get_cookie()) + ++ " " ++ integer_to_list(N) ++ " " ++ Host, + io:format("Einodecmd ~p ~n", [Einodecmd]), + ?line open_port({spawn, Einodecmd}, []), + ok. + +ei_rpc(Config) when is_list(Config) -> + ?line P = runner:start(?interpret), + ?line 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0), + ?line {ok,Fd} = ei_connect(P, node()), + + ?line S= "Hej du glade!", SRev = lists:reverse(S), + ?line X = ei_rpc(P, Fd, self(), {?MODULE, rpc_test}, [SRev]), + ?line {term, S}= X, + + ?line runner:send_eot(P), + ?line runner:recv_eot(P), + ok. + +ei_set_get_tracelevel(Config) when is_list(Config) -> + ?line P = runner:start(?interpret), + ?line 5 = ei_set_get_tracelevel(P, 5), + ?line 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0), + ?line {ok,Fd} = ei_connect(P, node()), + + ?line S= "Hej du glade!", SRev = lists:reverse(S), + ?line X = ei_rpc(P, Fd, self(), {?MODULE, rpc_test}, [SRev]), + ?line {term, S}= X, + + ?line 0 = ei_set_get_tracelevel(P, 0), + + ?line runner:send_eot(P), + ?line runner:recv_eot(P), + ok. + + +%%% Interface functions for ei (erl_interface) functions. + +ei_connect_init(P, Num, Cookie, Creation) -> + send_command(P, ei_connect_init, [Num,Cookie,Creation]), + case get_term(P) of + {term,Int} when is_integer(Int) -> Int + end. + +ei_connect(P, Node) -> + send_command(P, ei_connect, [Node]), + case get_term(P) of + {term,{Fd,_}} when Fd >= 0 -> {ok,Fd}; + {term,{-1,Errno}} -> {error,Errno} + end. + +ei_set_get_tracelevel(P, Tracelevel) -> + send_command(P, ei_set_get_tracelevel, [Tracelevel]), + case get_term(P) of + {term,{tracelevel, Level}} when is_integer(Level) -> Level + end. + +ei_send(P, Fd, To, Msg) -> + send_command(P, ei_send, [Fd,To,Msg]), + get_send_result(P). + +ei_send_funs(P, Fd, To, Msg) -> + send_command(P, ei_send_funs, [Fd,To,Msg]), + get_send_result(P). + +ei_reg_send(P, Fd, To, Msg) -> + send_command(P, ei_reg_send, [Fd,To,Msg]), + get_send_result(P). + +ei_rpc(P, Fd, To, Func, Msg) -> + send_command(P, ei_rpc, [Fd, To, Func, Msg]), + get_term(P). + + +get_send_result(P) -> + case get_term(P) of + {term,{0,_}} -> ok; + {term,{1,_}} -> ok; + {term,{-1,Errno}} -> {error,Errno}; + {term,{Res,Errno}}-> + io:format("Return value: ~p\nerl_errno: ~p", [Res,Errno]), + ?t:fail(bad_return_value) + end. + +send_command(P, Name, Args) -> + runner:send_term(P, {Name,list_to_tuple(Args)}). + +%%% Test function for RPC + +rpc_test(S) -> + lists:reverse(S). diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/Makefile.first b/lib/erl_interface/test/ei_connect_SUITE_data/Makefile.first new file mode 100644 index 0000000000..8bf22e366e --- /dev/null +++ b/lib/erl_interface/test/ei_connect_SUITE_data/Makefile.first @@ -0,0 +1,21 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +ei_connect_test_decl.c: ei_connect_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run ei_connect_test -s erlang halt diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_connect_SUITE_data/Makefile.src new file mode 100644 index 0000000000..a6525a9138 --- /dev/null +++ b/lib/erl_interface/test/ei_connect_SUITE_data/Makefile.src @@ -0,0 +1,46 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \ + $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + @erl_interface_threadlib@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data +EI_CONNECT_OBJS = ei_connect_test@obj@ ei_connect_test_decl@obj@ +EINODE_OBJS = einode@obj@ + +all: ei_connect_test@exe@ einode@exe@ + +clean: + $(RM) $(EI_CONNECT_OBJS) $(EINODE_OBJS) + $(RM) ei_connect_test@exe@ einode@exe@ + +ei_connect_test@exe@: $(EI_CONNECT_OBJS) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(EI_CONNECT_OBJS) $(LIBFLAGS) + + +einode@exe@: $(EINODE_OBJS) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(EINODE_OBJS) $(LIBFLAGS) + diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c new file mode 100644 index 0000000000..debd3e789b --- /dev/null +++ b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c @@ -0,0 +1,289 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* + * Purpose: Tests the functions in ei_connect.c. + * Author: Bjorn Gustavsson (rewritten somewhat by Jakob Cederlund) + * + * See the ei_connect_SUITE.erl file for a "table of contents". + */ + +#include <stdio.h> +#include <string.h> +#ifdef VXWORKS +#include "reclaim.h" +#endif + +#include "ei_runner.h" + +static void cmd_ei_connect_init(char* buf, int len); +static void cmd_ei_connect(char* buf, int len); +static void cmd_ei_send(char* buf, int len); +static void cmd_ei_send_funs(char* buf, int len); +static void cmd_ei_reg_send(char* buf, int len); +static void cmd_ei_rpc(char* buf, int len); +static void cmd_ei_set_get_tracelevel(char* buf, int len); + +static void send_errno_result(int value); + +ei_cnode ec; + + +static struct { + char* name; + int num_args; /* Number of arguments. */ + void (*func)(char* buf, int len); +} commands[] = { + "ei_connect_init", 3, cmd_ei_connect_init, + "ei_connect", 1, cmd_ei_connect, + "ei_send", 3, cmd_ei_send, + "ei_send_funs", 3, cmd_ei_send_funs, + "ei_reg_send", 3, cmd_ei_reg_send, + "ei_rpc", 4, cmd_ei_rpc, + "ei_set_get_tracelevel", 1, cmd_ei_set_get_tracelevel, +}; + + +/* + * Sends a list contaning all data types to the Erlang side. + */ + +TESTCASE(interpret) +{ + ei_x_buff x; + int i; + ei_term term; + + ei_x_new(&x); + for (;;) { + if (get_bin_term(&x, &term)) { + report(1); + return; + } else { + char* buf = x.buff, func[MAXATOMLEN]; + int index = x.index, arity; + if (term.ei_type != ERL_SMALL_TUPLE_EXT || term.arity != 2) + fail("term should be a tuple of size 2"); + if (ei_decode_atom(buf, &index, func) < 0) + fail("function name should be an atom"); + if (ei_decode_tuple_header(buf, &index, &arity) != 0) + fail("function arguments should be a tuple"); + for (i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) { + if (strcmp(func, commands[i].name) == 0) { + if (arity != commands[i].num_args) + fail("wrong number of arguments"); + commands[i].func(buf + index, x.buffsz - index); + break; + } + } + if (i >= sizeof(commands)/sizeof(commands[0])) { + message("\"%d\" \n", func); + fail("bad command"); + } + } + } +} + + +static void cmd_ei_connect_init(char* buf, int len) +{ + int index = 0, r = 0; + int type, size; + long l; + char b[100]; + char cookie[MAXATOMLEN], * cp = cookie; + ei_x_buff res; + if (ei_decode_long(buf, &index, &l) < 0) + fail("expected int"); + sprintf(b, "c%d", l); + /* FIXME don't use internal and maybe use skip?! */ + ei_get_type_internal(buf, &index, &type, &size); + if (ei_decode_atom(buf, &index, cookie) < 0) + fail("expected atom (cookie)"); + if (cookie[0] == '\0') + cp = NULL; + r = ei_connect_init(&ec, b, cp, 0); + ei_x_new_with_version(&res); + ei_x_encode_long(&res, r); + send_bin_term(&res); + ei_x_free(&res); +} + +static void cmd_ei_connect(char* buf, int len) +{ + int index = 0; + char node[256]; + int i; + if (ei_decode_atom(buf, &index, node) < 0) + fail("expected atom"); + i=ei_connect(&ec, node); +#ifdef VXWORKS + if(i >= 0) { + save_fd(i); + } +#endif + send_errno_result(i); +} + +static void cmd_ei_set_get_tracelevel(char* buf, int len) +{ + int index = 0; + long level = 0; + long ret = 0; + ei_x_buff x; + + if (ei_decode_long(buf, &index, &level) < 0) { + fail("expected long"); + } + + ei_set_tracelevel((int)level); + + ret = (long) ei_get_tracelevel(); + + ei_x_new_with_version(&x); + ei_x_encode_tuple_header(&x, 2); + ei_x_encode_atom(&x, "tracelevel"); + ei_x_encode_long(&x, ret); + send_bin_term(&x); + ei_x_free(&x); +} + +static void cmd_ei_send(char* buf, int len) +{ + int index = 0; + long fd; + erlang_pid pid; + ei_x_buff x; + + if (ei_decode_long(buf, &index, &fd) < 0) + fail("expected long"); + if (ei_decode_pid(buf, &index, &pid) < 0) + fail("expected pid (node)"); + if (ei_x_new_with_version(&x) < 0) + fail("ei_x_new_with_version"); + if (ei_x_append_buf(&x, &buf[index], len - index) < 0) + fail("append"); + send_errno_result(ei_send(fd, &pid, x.buff, x.index)); + ei_x_free(&x); +} + +static void cmd_ei_send_funs(char* buf, int len) +{ + int index = 0, n; + long fd; + erlang_pid pid; + ei_x_buff x; + erlang_fun fun1, fun2; + + if (ei_decode_long(buf, &index, &fd) < 0) + fail("expected long"); + if (ei_decode_pid(buf, &index, &pid) < 0) + fail("expected pid (node)"); + if (ei_decode_tuple_header(buf, &index, &n) < 0) + fail("expected tuple"); + if (n != 2) + fail("expected tuple"); + if (ei_decode_fun(buf, &index, &fun1) < 0) + fail("expected Fun1"); + if (ei_decode_fun(buf, &index, &fun2) < 0) + fail("expected Fun2"); + if (ei_x_new_with_version(&x) < 0) + fail("ei_x_new_with_version"); + if (ei_x_encode_tuple_header(&x, 2) < 0) + fail("encode tuple header"); + if (ei_x_encode_fun(&x, &fun1) < 0) + fail("encode fun1"); + if (ei_x_encode_fun(&x, &fun2) < 0) + fail("encode fun2"); + free_fun(&fun1); + free_fun(&fun2); + send_errno_result(ei_send(fd, &pid, x.buff, x.index)); + ei_x_free(&x); +} + +static void cmd_ei_reg_send(char* buf, int len) +{ + int index = 0; + long fd; + char reg_name[MAXATOMLEN]; + erlang_pid pid; + ei_x_buff x; + + if (ei_decode_long(buf, &index, &fd) < 0) + fail("expected long (fd)"); + if (ei_decode_atom(buf, &index, reg_name) < 0) + fail("expected atom (reg name)"); + if (ei_x_new_with_version(&x) < 0) + fail("ei_x_new_with_version"); + if (ei_x_append_buf(&x, &buf[index], len - index) < 0) + fail("append"); + send_errno_result(ei_reg_send(&ec, fd, + reg_name, x.buff, x.index)); + ei_x_free(&x); +} + +static void cmd_ei_rpc(char* buf, int len) +{ + int index = 0, n; + long fd; + erlang_pid pid; + ei_x_buff x, rpc_x; + int r; + char mod[MAXATOMLEN], func[MAXATOMLEN]; + +#if 0 && defined(__WIN32__) + DebugBreak(); +#endif + + if (ei_decode_long(buf, &index, &fd) < 0) + fail("expected long"); + if (ei_decode_pid(buf, &index, &pid) < 0) + fail("expected pid (node)"); + if (ei_decode_tuple_header(buf, &index, &n) < 0 && n < 2) + fail("expected tuple {module, function}"); + if (ei_decode_atom(buf, &index, mod) < 0) + fail("expected atom (module)"); + if (ei_decode_atom(buf, &index, func) < 0) + fail("expected atom (function)"); + message("pid %s %d %d %d\n", pid.node, pid.num, pid.serial, pid.creation); + message("{%s, %s}\n", mod, func); + if (ei_x_new(&rpc_x) < 0) + fail("ei_x_new"); + if (ei_rpc(&ec, fd, mod, func, &buf[index], len - index, &rpc_x) < 0) + fail("ei_rpc"); + if (ei_x_new_with_version(&x) < 0) + fail("ei_x_new_with_version"); + if (ei_x_append(&x, &rpc_x) < 0) + fail("append"); + send_bin_term(&x); + /*send_errno_result(ei_send(&ec, fd, &pid, x.buff, x.index));*/ + ei_x_free(&x); + ei_x_free(&rpc_x); +} + +static void send_errno_result(int value) +{ + ei_x_buff x; + ei_x_new_with_version(&x); + ei_x_encode_tuple_header(&x, 2); + ei_x_encode_long(&x, value); + ei_x_encode_long(&x, erl_errno); + send_bin_term(&x); + ei_x_free(&x); +} diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/einode.c b/lib/erl_interface/test/ei_connect_SUITE_data/einode.c new file mode 100644 index 0000000000..bafe8bd5bd --- /dev/null +++ b/lib/erl_interface/test/ei_connect_SUITE_data/einode.c @@ -0,0 +1,158 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* to test multiple threads in ei */ + +#include <stdlib.h> +#include <stdio.h> + +#ifdef __WIN32__ +#include <winsock2.h> +#include <windows.h> +#include <process.h> +#else +#ifndef VXWORKS +#include <pthread.h> +#endif +#include <sys/socket.h> +#endif + +#include "ei.h" + +#ifdef VXWORKS +#define MAIN cnode +#else +#define MAIN main +#endif + +/* + A small einode. + To be called from the test case ei_accept_SUITE:multi_thread + usage: einode <cookie> <n> <destnode> + + - start threads 0..n-1 + - in each thread + - connect to destnode + - send a message ("ei0".."ei<n-1>") to mth0..mth<n-1> on destnode + - shutdown gracefully +*/ + +static const char* cookie, * desthost; + +#ifndef SD_SEND +#ifdef SHUTWR +#define SD_SEND SHUT_WR +#else +#define SD_SEND 1 +#endif +#endif + +#ifndef __WIN32__ +#define closesocket(fd) close(fd) +#endif + +#ifdef __WIN32__ +static DWORD WINAPI +#else +static void* +#endif + einode_thread(void* num) +{ + int n = (int)num; + ei_cnode ec; + char myname[100], destname[100]; + int r, fd; + + sprintf(myname, "ei%d", n); + sprintf(destname, "mth%d", n); + printf("thread %d (%s %s) connecting\n", n, myname, destname); + r = ei_connect_init(&ec, myname, cookie, 0); + fd = ei_connect(&ec, (char*)desthost); + if (r == 0 && fd >= 0) { + ei_x_buff x; + ei_x_new_with_version(&x); + ei_x_encode_string(&x, myname); + ei_reg_send(&ec, fd, destname, x.buff, x.index); + ei_x_free(&x); + //SleepEx(100); + shutdown(fd, SD_SEND); + closesocket(fd); + } else { + printf("coudn't connect fd %d r %d\n", fd, r); // DebugBreak(); + } + printf("done thread %d\n", n); + return 0; +} + +MAIN(int argc, char *argv[]) +{ + int i, n, no_threads; +#ifndef VXWORKS +#ifdef __WIN32__ + HANDLE threads[100]; +#else + pthread_t threads[100]; +#endif +#endif + + if (argc < 3) + exit(1); + + cookie = argv[1]; + n = atoi(argv[2]); + if (n > 100) + exit(2); + desthost = argv[3]; +#ifndef VXWORKS + no_threads = argv[4] != NULL && strcmp(argv[4], "nothreads") == 0; +#else + no_threads = 1; +#endif + for (i = 0; i < n; ++i) { + if (!no_threads) { +#ifndef VXWORKS +#ifdef __WIN32__ + unsigned tid; + threads[i] = (HANDLE)_beginthreadex(NULL, 0, einode_thread, + (void*)i, 0, &tid); +#else + pthread_create(&threads[i], NULL, einode_thread, (void*)i); +#endif +#else + ; +#endif + } else + einode_thread((void*)i); + } + if (!no_threads) +#ifndef VXWORKS + for (i = 0; i < n; ++i) { +#ifdef __WIN32__ + if (WaitForSingleObject(threads[i], INFINITE) != WAIT_OBJECT_0) +#else + if (pthread_join(threads[i], NULL) != 0) +#endif + printf("bad wait thread %d\n", i); + } +#else + ; +#endif + printf("ok\n"); + return 0; +} diff --git a/lib/erl_interface/test/ei_decode_SUITE.erl b/lib/erl_interface/test/ei_decode_SUITE.erl new file mode 100644 index 0000000000..ea528728ab --- /dev/null +++ b/lib/erl_interface/test/ei_decode_SUITE.erl @@ -0,0 +1,300 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(ei_decode_SUITE). + +-include("test_server.hrl"). +-include("ei_decode_SUITE_data/ei_decode_test_cases.hrl"). + +-export( + [ + all/1, + test_ei_decode_long/1, + test_ei_decode_ulong/1, + test_ei_decode_longlong/1, + test_ei_decode_ulonglong/1, + test_ei_decode_char/1, + test_ei_decode_nonoptimal/1, + test_ei_decode_misc/1 + ]). + +all(suite) -> + [ + test_ei_decode_long, + test_ei_decode_ulong, + test_ei_decode_longlong, + test_ei_decode_ulonglong, + test_ei_decode_char, + test_ei_decode_nonoptimal, + test_ei_decode_misc + ]. + +%% --------------------------------------------------------------------------- + +% NOTE: for historical reasons we don't pach as tight as we can, +% we only fill 27 bits in 32 bit INTEGER_EXT + + +%% ######################################################################## %% + +test_ei_decode_long(suite) -> []; +test_ei_decode_long(Config) when is_list(Config) -> + ?line P = runner:start(?test_ei_decode_long), + send_integers(P), + ?line runner:recv_eot(P), + ok. + + +%% ######################################################################## %% + +test_ei_decode_ulong(suite) -> []; +test_ei_decode_ulong(Config) when is_list(Config) -> + ?line P = runner:start(?test_ei_decode_ulong), + send_integers(P), + ?line runner:recv_eot(P), + ok. + + +% (*) In practical terms, other values may fit into the ext format +% i32 is signed 32 bit on C side +% u32 is unsigned 32 bit on C side + +%% ######################################################################## %% + +test_ei_decode_longlong(suite) -> []; +test_ei_decode_longlong(Config) when is_list(Config) -> + case os:type() of + vxworks -> + {skip,"Skipped on VxWorks"}; + _ -> + ?line P = runner:start(?test_ei_decode_longlong), + send_integers2(P), + ?line runner:recv_eot(P), + ok + end. + + +%% ######################################################################## %% + +test_ei_decode_ulonglong(suite) -> []; +test_ei_decode_ulonglong(Config) when is_list(Config) -> + case os:type() of + vxworks -> + {skip,"Skipped on VxWorks"}; + _ -> + ?line P = runner:start(?test_ei_decode_ulonglong), + send_integers2(P), + ?line runner:recv_eot(P), + ok + end. + + +%% ######################################################################## %% +%% A "character" for us is an 8 bit integer, alwasy positive, i.e. +%% it is unsigned. +%% FIXME maybe the API should change to use "unsigned char" to be clear?! + +test_ei_decode_char(suite) -> []; +test_ei_decode_char(Config) when is_list(Config) -> + ?line P = runner:start(?test_ei_decode_char), + + ?line send_term_as_binary(P,0), + ?line send_term_as_binary(P,16#7f), + ?line send_term_as_binary(P,16#ff), + + ?line send_term_as_binary(P, []), % illegal type + + ?line runner:recv_eot(P), + ok. + + +%% ######################################################################## %% + +test_ei_decode_nonoptimal(suite) -> []; +test_ei_decode_nonoptimal(Config) when is_list(Config) -> + ?line P = runner:start(?test_ei_decode_nonoptimal), + + send_non_optimal_pos(P), % decode_char + send_non_optimal(P), % decode_long + send_non_optimal_pos(P), % decode_ulong + case os:type() of + vxworks -> + ok; + _ -> + send_non_optimal(P), % decode_longlong + send_non_optimal_pos(P) % decode_ulonglong + end, + + ?line runner:recv_eot(P), + ok. + + +send_non_optimal(P) -> + send_non_optimal_pos(P), + send_non_optimal_neg(P). + +send_non_optimal_pos(P) -> + ?line send_raw(P, <<131,97,42>>), + ?line send_raw(P, <<131,98,42:32>>), + ?line send_raw(P, <<131,110,1,0,42>>), + ?line send_raw(P, <<131,110,2,0,42,0>>), + ?line send_raw(P, <<131,110,4,0,42,0,0,0>>), + ?line send_raw(P, <<131,111,0,0,0,1,0,42>>), + ?line send_raw(P, <<131,111,0,0,0,2,0,42,0>>), + ?line send_raw(P, <<131,111,0,0,0,3,0,42,0,0>>), + ?line send_raw(P, <<131,111,0,0,0,6,0,42,0,0,0,0,0>>), + ok. + +send_non_optimal_neg(P) -> +% ?line send_raw(P, <<131,97,-42>>), + ?line send_raw(P, <<131,98,-42:32>>), + ?line send_raw(P, <<131,110,1,1,42>>), + ?line send_raw(P, <<131,110,2,1,42,0>>), + ?line send_raw(P, <<131,110,4,1,42,0,0,0>>), + ?line send_raw(P, <<131,111,0,0,0,1,1,42>>), + ?line send_raw(P, <<131,111,0,0,0,2,1,42,0>>), + ?line send_raw(P, <<131,111,0,0,0,3,1,42,0,0>>), + ?line send_raw(P, <<131,111,0,0,0,6,1,42,0,0,0,0,0>>), + ok. + + +%% ######################################################################## %% + +test_ei_decode_misc(suite) -> []; +test_ei_decode_misc(Config) when is_list(Config) -> + ?line P = runner:start(?test_ei_decode_misc), + +% ?line <<131>> = get_binaries(P), + +% ?line {term,F} = get_term(P), +% ?line match_float(F, 0.0), +% ?line {term,F} = get_term(P), +% ?line match_float(F, 0.0), + +% ?line {term,F} = get_term(P), +% ?line true = match_float(F, -1.0), +% ?line {term,F} = get_term(P), +% ?line true = match_float(F, -1.0), + +% ?line {term,F} = get_term(P), +% ?line true = match_float(F, 1.0), +% ?line {term,F} = get_term(P), +% ?line true = match_float(F, 1.0), + + ?line send_term_as_binary(P,false), + ?line send_term_as_binary(P,true), + + ?line send_term_as_binary(P,foo), + ?line send_term_as_binary(P,''), + ?line send_term_as_binary(P,'������'), + + ?line send_term_as_binary(P,"foo"), + ?line send_term_as_binary(P,""), + ?line send_term_as_binary(P,"������"), + + ?line send_term_as_binary(P,<<"foo">>), + ?line send_term_as_binary(P,<<>>), + ?line send_term_as_binary(P,<<"������">>), + +% ?line send_term_as_binary(P,{}), +% ?line send_term_as_binary(P,[]), + + ?line runner:recv_eot(P), + ok. + + +%% ######################################################################## %% + +send_term_as_binary(Port, Term) when is_port(Port) -> + Port ! {self(), {command, term_to_binary(Term)}}. + +send_raw(Port, Bin) when is_port(Port) -> + Port ! {self(), {command, Bin}}. + + +send_integers(P) -> + ?line send_term_as_binary(P,0), % SMALL_INTEGER_EXT smallest + ?line send_term_as_binary(P,255), % SMALL_INTEGER_EXT largest + ?line send_term_as_binary(P,256), % INTEGER_EXT smallest pos (*) + ?line send_term_as_binary(P,-1), % INTEGER_EXT largest neg + + ?line send_term_as_binary(P, 16#07ffffff), % INTEGER_EXT largest (28 bits) + ?line send_term_as_binary(P,-16#08000000), % INTEGER_EXT smallest + ?line send_term_as_binary(P, 16#08000000), % SMALL_BIG_EXT smallest pos(*) + ?line send_term_as_binary(P,-16#08000001), % SMALL_BIG_EXT largest neg (*) + + ?line send_term_as_binary(P, 16#7fffffff), % SMALL_BIG_EXT largest i32 + ?line send_term_as_binary(P,-16#80000000), % SMALL_BIG_EXT smallest i32 + + case erlang:system_info(wordsize) of + 4 -> + ?line send_term_as_binary(P, 16#80000000),% SMALL_BIG_EXT u32 + ?line send_term_as_binary(P, 16#ffffffff),% SMALL_BIG_EXT largest u32 + + ?line send_term_as_binary(P, 16#7fffffffffff), % largest i48 + ?line send_term_as_binary(P,-16#800000000000), % smallest i48 + ?line send_term_as_binary(P, 16#ffffffffffff), % largest u48 + ?line send_term_as_binary(P, 16#7fffffffffffffff), % largest i64 + ?line send_term_as_binary(P,-16#8000000000000000), % smallest i64 + ?line send_term_as_binary(P, 16#ffffffffffffffff); % largest u64 + 8 -> + ?line send_term_as_binary(P, 16#8000000000000000),% SMALL_BIG_EXT u64 + % SMALL_BIG_EXT largest u64 + ?line send_term_as_binary(P, 16#ffffffffffffffff), + % largest i96 + ?line send_term_as_binary(P, 16#7fffffffffffffffffffffff), + % smallest i96 + ?line send_term_as_binary(P,-16#800000000000000000000000), + % largest u96 + ?line send_term_as_binary(P, 16#ffffffffffffffffffffffff), + % largest i128 + ?line send_term_as_binary(P, 16#7fffffffffffffffffffffffffffffff), + % smallest i128 + ?line send_term_as_binary(P,-16#80000000000000000000000000000000), + % largest u128 + ?line send_term_as_binary(P, 16#ffffffffffffffffffffffffffffffff) + end, + ?line send_term_as_binary(P, []), % illegal type + ok. + +send_integers2(P) -> + ?line send_term_as_binary(P,0), % SMALL_INTEGER_EXT smallest + ?line send_term_as_binary(P,255), % SMALL_INTEGER_EXT largest + ?line send_term_as_binary(P,256), % INTEGER_EXT smallest pos (*) + ?line send_term_as_binary(P,-1), % INTEGER_EXT largest neg + + ?line send_term_as_binary(P, 16#07ffffff), % INTEGER_EXT largest (28 bits) + ?line send_term_as_binary(P,-16#08000000), % INTEGER_EXT smallest + ?line send_term_as_binary(P, 16#08000000), % SMALL_BIG_EXT smallest pos(*) + ?line send_term_as_binary(P,-16#08000001), % SMALL_BIG_EXT largest neg (*) + + ?line send_term_as_binary(P, 16#7fffffff), % SMALL_BIG_EXT largest i32 + ?line send_term_as_binary(P,-16#80000000), % SMALL_BIG_EXT smallest i32 + ?line send_term_as_binary(P, 16#80000000),% SMALL_BIG_EXT u32 + ?line send_term_as_binary(P, 16#ffffffff),% SMALL_BIG_EXT largest u32 + + ?line send_term_as_binary(P, 16#7fffffffffff), % largest i48 + ?line send_term_as_binary(P,-16#800000000000), % smallest i48 + ?line send_term_as_binary(P, 16#ffffffffffff), % largest u48 + ?line send_term_as_binary(P, 16#7fffffffffffffff), % largest i64 + ?line send_term_as_binary(P,-16#8000000000000000), % smallest i64 + ?line send_term_as_binary(P, 16#ffffffffffffffff), % largest u64 + ?line send_term_as_binary(P, []), % illegal type + ok. diff --git a/lib/erl_interface/test/ei_decode_SUITE_data/Makefile.first b/lib/erl_interface/test/ei_decode_SUITE_data/Makefile.first new file mode 100644 index 0000000000..0791b54109 --- /dev/null +++ b/lib/erl_interface/test/ei_decode_SUITE_data/Makefile.first @@ -0,0 +1,21 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2004-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +ei_decode_test_decl.c: ei_decode_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run ei_decode_test -s erlang halt diff --git a/lib/erl_interface/test/ei_decode_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_decode_SUITE_data/Makefile.src new file mode 100644 index 0000000000..76e55750c3 --- /dev/null +++ b/lib/erl_interface/test/ei_decode_SUITE_data/Makefile.src @@ -0,0 +1,42 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2004-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \ + $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + @erl_interface_threadlib@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data +EI_DECODE_OBJS = ei_decode_test@obj@ ei_decode_test_decl@obj@ + +all: ei_decode_test@exe@ + +clean: + $(RM) $(EI_DECODE_OBJS) + $(RM) ei_decode_test@exe@ + +ei_decode_test@exe@: $(EI_DECODE_OBJS) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(EI_DECODE_OBJS) $(LIBFLAGS) + + diff --git a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c new file mode 100644 index 0000000000..d81ea88437 --- /dev/null +++ b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c @@ -0,0 +1,548 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#ifdef VXWORKS +#include "reclaim.h" +#endif + +#include "ei_runner.h" + +/* + * Purpose: Tests the ei_format() function. + * Author: Kent + */ + +#ifdef VXWORKS +#define MESSAGE_BACK(SIZE) \ + message("err = %d, size2 = %d, expected size = %d", \ + err, size1, SIZE); +#else +#define MESSAGE_BACK(SIZE) \ + message("err = %d, size2 = %d, expected size = %d, long long val = %lld", \ + err, size1, SIZE, (EI_LONGLONG)p); +#endif + +#define EI_DECODE_2(FUNC,SIZE,TYPE,VAL) \ + { \ + TYPE p; \ + char *buf; \ + int size1 = 0; \ + int size2 = 0; \ + int err; \ + message("ei_" #FUNC " " #TYPE " should be " #VAL); \ + buf = read_packet(NULL); \ +\ + err = ei_ ## FUNC(buf+1, &size1, NULL); \ + message("err = %d, size1 = %d, expected size = %d", \ + err, size1, SIZE); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1 if NULL pointer"); \ + } else { \ + fail("returned non zero if NULL pointer"); \ + } \ + return; \ + } \ +\ + err = ei_ ## FUNC(buf+1, &size2, &p); \ + MESSAGE_BACK(SIZE) \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + return; \ + } \ + if (p != (TYPE)VAL) { \ + fail("value is not correct"); \ + return; \ + } \ +\ + if (size1 != size2) { \ + fail("size with and without pointer differs"); \ + return; \ + } \ +\ + if (size1 != SIZE) { \ + fail("size of encoded data is incorrect"); \ + return; \ + } \ + } \ + +#define EI_DECODE_2_FAIL(FUNC,SIZE,TYPE,VAL) \ + { \ + TYPE p, saved_p; \ + char *buf; \ + int size1 = 0; \ + int size2 = 0; \ + int err; \ + message("ei_" #FUNC " " #TYPE " should fail"); \ + memset(&p,'\0',sizeof(p)); \ + saved_p = p; \ + buf = read_packet(NULL); \ +\ + err = ei_ ## FUNC(buf+1, &size1, NULL); \ + message("err = %d, size1 = %d, expected size = %d", \ + err, size1, SIZE); \ + if (err != -1) { \ + fail("should return -1 if NULL pointer"); \ + return; \ + } \ +\ + err = ei_ ## FUNC(buf+1, &size2, &p); \ + message("err = %d, size2 = %d, expected size = %d", \ + err, size1, SIZE); \ + if (err != -1) { \ + fail("should return -1"); \ + return; \ + } \ + if (p != saved_p) { \ + fail("p argument was modified"); \ + return; \ + } \ +\ + if (size1 != 0) { \ + fail("size of encoded data should be 0 if NULL"); \ + return; \ + } \ +\ + if (size2 != 0) { \ + fail("size of encoded data should be 0"); \ + return; \ + } \ + } \ + +#define EI_DECODE_STRING(FUNC,SIZE,VAL) \ + { \ + char p[1024]; \ + char *buf; \ + int size1 = 0; \ + int size2 = 0; \ + int err; \ + message("ei_" #FUNC " should be " #VAL); \ + buf = read_packet(NULL); \ +\ + err = ei_ ## FUNC(buf+1, &size1, NULL); \ + message("err = %d, size = %d, expected size = %d\n",err,size1,SIZE); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1 if NULL pointer"); \ + } else { \ + fail("returned non zero if NULL pointer"); \ + } \ + return; \ + } \ +\ + err = ei_ ## FUNC(buf+1, &size2, p); \ + message("err = %d, size = %d, expected size = %d\n",err,size2,SIZE); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + return; \ + } \ +\ + if (strcmp(p,VAL) != 0) { \ + fail("value is not correct"); \ + return; \ + } \ +\ + if (size1 != size2) { \ + fail("size with and without pointer differs"); \ + return; \ + } \ +\ + if (size1 != SIZE) { \ + fail("size of encoded data is incorrect"); \ + return; \ + } \ + } \ + +#define EI_DECODE_BIN(FUNC,SIZE,VAL,LEN) \ + { \ + char p[1024]; \ + char *buf; \ + long len; \ + int size1 = 0; \ + int size2 = 0; \ + int err; \ + message("ei_" #FUNC " should be " #VAL); \ + buf = read_packet(NULL); \ + err = ei_ ## FUNC(buf+1, &size1, NULL, &len); \ + message("err = %d, size = %d, len = %d, expected size = %d, expected len = %d\n",\ + err,size1,len,SIZE,LEN); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1 if NULL pointer"); \ + } else { \ + fail("returned non zero"); \ + } \ + return; \ + } \ +\ + if (len != LEN) { \ + fail("size is not correct"); \ + return; \ + } \ +\ + err = ei_ ## FUNC(buf+1, &size2, p, &len); \ + message("err = %d, size = %d, len = %d, expected size = %d, expected len = %d\n",\ + err,size2,len,SIZE,LEN); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1 if NULL pointer"); \ + } else { \ + fail("returned non zero"); \ + } \ + return; \ + } \ +\ + if (len != LEN) { \ + fail("size is not correct"); \ + return; \ + } \ +\ + if (strncmp(p,VAL,LEN) != 0) { \ + fail("value is not correct"); \ + return; \ + } \ +\ + if (size1 != size2) { \ + fail("size with and without pointer differs"); \ + return; \ + } \ +\ + if (size1 != SIZE) { \ + fail("size of encoded data is incorrect"); \ + return; \ + } \ + } \ + +/* ******************************************************************** */ + +TESTCASE(test_ei_decode_long) +{ + EI_DECODE_2 (decode_long, 2, long, 0); + EI_DECODE_2 (decode_long, 2, long, 255); + EI_DECODE_2 (decode_long, 5, long, 256); + EI_DECODE_2 (decode_long, 5, long, -1); + + EI_DECODE_2 (decode_long, 5, long, 0x07ffffff); + EI_DECODE_2 (decode_long, 5, long, -0x08000000); + EI_DECODE_2 (decode_long, 7, long, 0x08000000); + EI_DECODE_2 (decode_long, 7, long, -0x08000001); + + EI_DECODE_2 (decode_long, 7, long, 0x7fffffff); + EI_DECODE_2 (decode_long, 7, long, -ll(0x80000000)); /* Strange :-( */ + + EI_DECODE_2_FAIL(decode_long, 7, long, 0x80000000); + EI_DECODE_2_FAIL(decode_long, 7, long, 0xffffffff); + + EI_DECODE_2_FAIL(decode_long, 9, long, ll(0x7fffffffffff)); + EI_DECODE_2_FAIL(decode_long, 9, long, -ll(0x800000000000)); + EI_DECODE_2_FAIL(decode_long, 9, long, ll(0xffffffffffff)); + EI_DECODE_2_FAIL(decode_long, 11, long, ll(0x7fffffffffffffff)); + EI_DECODE_2_FAIL(decode_long, 11, long, -ll(0x8000000000000000)); + EI_DECODE_2_FAIL(decode_long, 11, long, ll(0xffffffffffffffff)); + + EI_DECODE_2_FAIL(decode_long, 1, long, 0); /* Illegal type sent */ + + report(1); +} + +/* ******************************************************************** */ + +TESTCASE(test_ei_decode_ulong) +{ + EI_DECODE_2 (decode_ulong, 2, unsigned long, 0); + EI_DECODE_2 (decode_ulong, 2, unsigned long, 255); + EI_DECODE_2 (decode_ulong, 5, unsigned long, 256); + EI_DECODE_2_FAIL(decode_ulong, 5, unsigned long, -1); + + EI_DECODE_2 (decode_ulong, 5, unsigned long, 0x07ffffff); + EI_DECODE_2_FAIL(decode_ulong, 5, unsigned long, -0x08000000); + EI_DECODE_2 (decode_ulong, 7, unsigned long, 0x08000000); + EI_DECODE_2_FAIL(decode_ulong, 7, unsigned long, -0x08000001); + + EI_DECODE_2 (decode_ulong, 7, unsigned long, 0x7fffffff); + EI_DECODE_2_FAIL(decode_ulong, 7, unsigned long, -ll(0x80000000)); + + if (sizeof(long) > 4) { + EI_DECODE_2 (decode_ulong, 11, unsigned long, ll(0x8000000000000000)); + EI_DECODE_2 (decode_ulong, 11, unsigned long, ll(0xffffffffffffffff)); + } else { + EI_DECODE_2 (decode_ulong, 7, unsigned long, 0x80000000); + EI_DECODE_2 (decode_ulong, 7, unsigned long, 0xffffffff); + } + + EI_DECODE_2_FAIL(decode_ulong, 9, unsigned long, ll(0x7fffffffffff)); + EI_DECODE_2_FAIL(decode_ulong, 9, unsigned long, -ll(0x800000000000)); + EI_DECODE_2_FAIL(decode_ulong, 9, unsigned long, ll(0xffffffffffff)); + EI_DECODE_2_FAIL(decode_ulong, 11, unsigned long, ll(0x7fffffffffffffff)); + EI_DECODE_2_FAIL(decode_ulong, 11, unsigned long, -ll(0x8000000000000000)); + EI_DECODE_2_FAIL(decode_ulong, 11, unsigned long, ll(0xffffffffffffffff)); + + EI_DECODE_2_FAIL(decode_ulong, 1, unsigned long, 0); /* Illegal type */ + + report(1); +} + +/* ******************************************************************** */ + + +TESTCASE(test_ei_decode_longlong) +{ +#ifndef VXWORKS + EI_DECODE_2 (decode_longlong, 2, EI_LONGLONG, 0); + EI_DECODE_2 (decode_longlong, 2, EI_LONGLONG, 255); + EI_DECODE_2 (decode_longlong, 5, EI_LONGLONG, 256); + EI_DECODE_2 (decode_longlong, 5, EI_LONGLONG, -1); + + EI_DECODE_2 (decode_longlong, 5, EI_LONGLONG, 0x07ffffff); + EI_DECODE_2 (decode_longlong, 5, EI_LONGLONG, -0x08000000); + EI_DECODE_2 (decode_longlong, 7, EI_LONGLONG, 0x08000000); + EI_DECODE_2 (decode_longlong, 7, EI_LONGLONG, -0x08000001); + + EI_DECODE_2 (decode_longlong, 7, EI_LONGLONG, 0x7fffffff); + EI_DECODE_2 (decode_longlong, 7, EI_LONGLONG, -ll(0x80000000)); + + EI_DECODE_2 (decode_longlong, 7, EI_LONGLONG, 0x80000000); + EI_DECODE_2 (decode_longlong, 7, EI_LONGLONG, 0xffffffff); + + EI_DECODE_2 (decode_longlong, 9, EI_LONGLONG, ll(0x7fffffffffff)); + EI_DECODE_2 (decode_longlong, 9, EI_LONGLONG, -ll(0x800000000000)); + EI_DECODE_2 (decode_longlong, 9, EI_LONGLONG, ll(0xffffffffffff)); + EI_DECODE_2 (decode_longlong, 11, EI_LONGLONG, ll(0x7fffffffffffffff)); + EI_DECODE_2 (decode_longlong, 11, EI_LONGLONG, -ll(0x8000000000000000)); + EI_DECODE_2_FAIL(decode_longlong, 11, EI_LONGLONG, ll(0xffffffffffffffff)); + + EI_DECODE_2_FAIL(decode_longlong, 1, EI_LONGLONG, 0); /* Illegal type */ +#endif + report(1); +} + +/* ******************************************************************** */ + +TESTCASE(test_ei_decode_ulonglong) +{ +#ifndef VXWORKS + EI_DECODE_2 (decode_ulonglong, 2, EI_ULONGLONG, 0); + EI_DECODE_2 (decode_ulonglong, 2, EI_ULONGLONG, 255); + EI_DECODE_2 (decode_ulonglong, 5, EI_ULONGLONG, 256); + EI_DECODE_2_FAIL(decode_ulonglong, 5, EI_ULONGLONG, -1); + + EI_DECODE_2 (decode_ulonglong, 5, EI_ULONGLONG, 0x07ffffff); + EI_DECODE_2_FAIL(decode_ulonglong, 5, EI_ULONGLONG, -0x08000000); + EI_DECODE_2 (decode_ulonglong, 7, EI_ULONGLONG, 0x08000000); + EI_DECODE_2_FAIL(decode_ulonglong, 7, EI_ULONGLONG, -0x08000001); + + EI_DECODE_2 (decode_ulonglong, 7, EI_ULONGLONG, 0x7fffffff); + EI_DECODE_2_FAIL(decode_ulonglong, 7, EI_ULONGLONG, -ll(0x80000000)); + + EI_DECODE_2 (decode_ulonglong, 7, EI_ULONGLONG, 0x80000000); + EI_DECODE_2 (decode_ulonglong, 7, EI_ULONGLONG, 0xffffffff); + + EI_DECODE_2 (decode_ulonglong, 9, EI_ULONGLONG, ll(0x7fffffffffff)); + EI_DECODE_2_FAIL(decode_ulonglong, 9, EI_ULONGLONG, -ll(0x800000000000)); + EI_DECODE_2 (decode_ulonglong, 9, EI_ULONGLONG, ll(0xffffffffffff)); + EI_DECODE_2 (decode_ulonglong,11, EI_ULONGLONG, ll(0x7fffffffffffffff)); + EI_DECODE_2_FAIL(decode_ulonglong,11, EI_ULONGLONG, -ll(0x8000000000000000)); + EI_DECODE_2 (decode_ulonglong,11, EI_ULONGLONG, ll(0xffffffffffffffff)); + + EI_DECODE_2_FAIL(decode_ulonglong, 1, EI_ULONGLONG, 0); /* Illegal type */ +#endif + report(1); +} + + +/* ******************************************************************** */ + +TESTCASE(test_ei_decode_char) +{ + EI_DECODE_2(decode_char, 2, char, 0); + EI_DECODE_2(decode_char, 2, char, 0x7f); + EI_DECODE_2(decode_char, 2, char, 0xff); + + EI_DECODE_2_FAIL(decode_char, 1, char, 0); /* Illegal type */ + + report(1); +} + +/* ******************************************************************** */ + +TESTCASE(test_ei_decode_nonoptimal) +{ + EI_DECODE_2(decode_char, 2, char, 42); + EI_DECODE_2(decode_char, 5, char, 42); + EI_DECODE_2(decode_char, 4, char, 42); + EI_DECODE_2(decode_char, 5, char, 42); + EI_DECODE_2(decode_char, 7, char, 42); + EI_DECODE_2(decode_char, 7, char, 42); + EI_DECODE_2(decode_char, 8, char, 42); + EI_DECODE_2(decode_char, 9, char, 42); + EI_DECODE_2(decode_char, 12, char, 42); + +/* EI_DECODE_2(decode_char, char, -42); */ +/* EI_DECODE_2(decode_char, char, -42); */ +/* EI_DECODE_2(decode_char, char, -42); */ +/* EI_DECODE_2(decode_char, char, -42); */ +/* EI_DECODE_2(decode_char, char, -42); */ +/* EI_DECODE_2(decode_char, char, -42); */ +/* EI_DECODE_2(decode_char, char, -42); */ +/* EI_DECODE_2(decode_char, char, -42); */ +/* EI_DECODE_2(decode_char, char, -42); */ + + /* ---------------------------------------------------------------- */ + + EI_DECODE_2(decode_long, 2, long, 42); + EI_DECODE_2(decode_long, 5, long, 42); + EI_DECODE_2(decode_long, 4, long, 42); + EI_DECODE_2(decode_long, 5, long, 42); + EI_DECODE_2(decode_long, 7, long, 42); + EI_DECODE_2(decode_long, 7, long, 42); + EI_DECODE_2(decode_long, 8, long, 42); + EI_DECODE_2(decode_long, 9, long, 42); + EI_DECODE_2(decode_long, 12, long, 42); + +/* EI_DECODE_2(decode_long, 2, long, -42); */ + EI_DECODE_2(decode_long, 5, long, -42); + EI_DECODE_2(decode_long, 4, long, -42); + EI_DECODE_2(decode_long, 5, long, -42); + EI_DECODE_2(decode_long, 7, long, -42); + EI_DECODE_2(decode_long, 7, long, -42); + EI_DECODE_2(decode_long, 8, long, -42); + EI_DECODE_2(decode_long, 9, long, -42); + EI_DECODE_2(decode_long, 12, long, -42); + + /* ---------------------------------------------------------------- */ + + EI_DECODE_2(decode_ulong, 2, unsigned long, 42); + EI_DECODE_2(decode_ulong, 5, unsigned long, 42); + EI_DECODE_2(decode_ulong, 4, unsigned long, 42); + EI_DECODE_2(decode_ulong, 5, unsigned long, 42); + EI_DECODE_2(decode_ulong, 7, unsigned long, 42); + EI_DECODE_2(decode_ulong, 7, unsigned long, 42); + EI_DECODE_2(decode_ulong, 8, unsigned long, 42); + EI_DECODE_2(decode_ulong, 9, unsigned long, 42); + EI_DECODE_2(decode_ulong, 12, unsigned long, 42); + +/* EI_DECODE_2(decode_ulong, unsigned long, -42); */ +/* EI_DECODE_2(decode_ulong, unsigned long, -42); */ +/* EI_DECODE_2(decode_ulong, unsigned long, -42); */ +/* EI_DECODE_2(decode_ulong, unsigned long, -42); */ +/* EI_DECODE_2(decode_ulong, unsigned long, -42); */ +/* EI_DECODE_2(decode_ulong, unsigned long, -42); */ +/* EI_DECODE_2(decode_ulong, unsigned long, -42); */ +/* EI_DECODE_2(decode_ulong, unsigned long, -42); */ +/* EI_DECODE_2(decode_ulong, unsigned long, -42); */ + + /* ---------------------------------------------------------------- */ + +#ifndef VXWORKS + + EI_DECODE_2(decode_longlong, 2, EI_LONGLONG, 42); + EI_DECODE_2(decode_longlong, 5, EI_LONGLONG, 42); + EI_DECODE_2(decode_longlong, 4, EI_LONGLONG, 42); + EI_DECODE_2(decode_longlong, 5, EI_LONGLONG, 42); + EI_DECODE_2(decode_longlong, 7, EI_LONGLONG, 42); + EI_DECODE_2(decode_longlong, 7, EI_LONGLONG, 42); + EI_DECODE_2(decode_longlong, 8, EI_LONGLONG, 42); + EI_DECODE_2(decode_longlong, 9, EI_LONGLONG, 42); + EI_DECODE_2(decode_longlong, 12, EI_LONGLONG, 42); + +/* EI_DECODE_2(decode_longlong, 2, EI_LONGLONG, -42); */ + EI_DECODE_2(decode_longlong, 5, EI_LONGLONG, -42); + EI_DECODE_2(decode_longlong, 4, EI_LONGLONG, -42); + EI_DECODE_2(decode_longlong, 5, EI_LONGLONG, -42); + EI_DECODE_2(decode_longlong, 7, EI_LONGLONG, -42); + EI_DECODE_2(decode_longlong, 7, EI_LONGLONG, -42); + EI_DECODE_2(decode_longlong, 8, EI_LONGLONG, -42); + EI_DECODE_2(decode_longlong, 9, EI_LONGLONG, -42); + EI_DECODE_2(decode_longlong, 12, EI_LONGLONG, -42); + + /* ---------------------------------------------------------------- */ + + EI_DECODE_2(decode_ulonglong, 2, EI_ULONGLONG, 42); + EI_DECODE_2(decode_ulonglong, 5, EI_ULONGLONG, 42); + EI_DECODE_2(decode_ulonglong, 4, EI_ULONGLONG, 42); + EI_DECODE_2(decode_ulonglong, 5, EI_ULONGLONG, 42); + EI_DECODE_2(decode_ulonglong, 7, EI_ULONGLONG, 42); + EI_DECODE_2(decode_ulonglong, 7, EI_ULONGLONG, 42); + EI_DECODE_2(decode_ulonglong, 8, EI_ULONGLONG, 42); + EI_DECODE_2(decode_ulonglong, 9, EI_ULONGLONG, 42); + EI_DECODE_2(decode_ulonglong, 12, EI_ULONGLONG, 42); + +/* EI_DECODE_2(decode_ulonglong, EI_ULONGLONG, -42); */ +/* EI_DECODE_2(decode_ulonglong, EI_ULONGLONG, -42); */ +/* EI_DECODE_2(decode_ulonglong, EI_ULONGLONG, -42); */ +/* EI_DECODE_2(decode_ulonglong, EI_ULONGLONG, -42); */ +/* EI_DECODE_2(decode_ulonglong, EI_ULONGLONG, -42); */ +/* EI_DECODE_2(decode_ulonglong, EI_ULONGLONG, -42); */ +/* EI_DECODE_2(decode_ulonglong, EI_ULONGLONG, -42); */ +/* EI_DECODE_2(decode_ulonglong, EI_ULONGLONG, -42); */ +/* EI_DECODE_2(decode_ulonglong, EI_ULONGLONG, -42); */ + +#endif /* !VXWORKS */ + + /* ---------------------------------------------------------------- */ + + report(1); +} + +/* ******************************************************************** */ + +TESTCASE(test_ei_decode_misc) +{ +/* + EI_DECODE_0(decode_version); +*/ +/* + EI_DECODE_2(decode_double, 0.0); + EI_DECODE_2(decode_double, -1.0); + EI_DECODE_2(decode_double, 1.0); +*/ + EI_DECODE_2(decode_boolean, 8, int, 0); + EI_DECODE_2(decode_boolean, 7, int, 1); + + EI_DECODE_STRING(decode_atom, 6, "foo"); + EI_DECODE_STRING(decode_atom, 3, ""); + EI_DECODE_STRING(decode_atom, 9, "������"); + + EI_DECODE_STRING(decode_string, 6, "foo"); + EI_DECODE_STRING(decode_string, 1, ""); + EI_DECODE_STRING(decode_string, 9, "������"); + + EI_DECODE_BIN(decode_binary, 8, "foo", 3); + EI_DECODE_BIN(decode_binary, 5, "", 0); + EI_DECODE_BIN(decode_binary, 11, "������", 6); + + /* FIXME check \0 in strings and atoms? */ +/* + EI_ENCODE_1(decode_tuple_header, 0); + + EI_ENCODE_0(decode_empty_list); +*/ + report(1); +} + +/* ******************************************************************** */ + diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl new file mode 100644 index 0000000000..c19c1d0887 --- /dev/null +++ b/lib/erl_interface/test/ei_decode_encode_SUITE.erl @@ -0,0 +1,290 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(ei_decode_encode_SUITE). + +-include("test_server.hrl"). +-include("ei_decode_encode_SUITE_data/ei_decode_encode_test_cases.hrl"). + +-export( + [ + all/1, + test_ei_decode_encode/1 + ]). + +all(suite) -> + [ + test_ei_decode_encode + ]. + +%% --------------------------------------------------------------------------- + +% NOTE: these types have no meaning on the C side so we pass them +% to C and back just to see they are the same. + + +%% ######################################################################## %% + +test_ei_decode_encode(suite) -> []; +test_ei_decode_encode(Config) when is_list(Config) -> + ?line P = runner:start(?test_ei_decode_encode), + + Fun = fun (X) -> {X,true} end, + Pid = self(), + Port = case os:type() of + {win32,_} -> + open_port({spawn,"sort"},[]); + _ -> + open_port({spawn,"/bin/true"},[]) + end, + Ref = make_ref(), + Trace = {1,2,3,self(),4}, % FIXME how to construct?! + + + BigSmallA = 1696192905348584855517250509684275447603964214606878827319923580493120589769459602596313014087329389174229999430092223701630077631205171572331191216670754029016160388576759960413039261647653627052707047, + BigSmallB = 43581177444506616087519351724629421082877485633442736512567383077022781906420535744195118099822189576169114064491200598595995538299156626345938812352676950427869649947439032133573270227067833308153431095, + BigSmallC = 52751775381034251994634567029696659541685100826881826508158083211003576763074162948462801435204697796532659535818017760528684167216110865807581759669824808936751316879636014972704885388116861127856231, + + BigLargeA = 1 bsl 11111 + BigSmallA, + BigLargeB = 1 bsl 11112 + BigSmallB, + BigLargeC = BigSmallA * BigSmallB * BigSmallC * BigSmallA, + + ?line send_rec(P, Fun), + ?line send_rec(P, Pid), + ?line send_rec(P, Port), + ?line send_rec(P, Ref), + ?line send_rec(P, Trace), + + % bigs + + ?line send_rec(P, BigSmallA), + ?line send_rec(P, BigSmallB), + ?line send_rec(P, BigSmallC), + + ?line send_rec(P, BigLargeA), + ?line send_rec(P, BigLargeB), + ?line send_rec(P, BigLargeC), + + %% Test large node containers... + + ?line ThisNode = {node(), erlang:system_info(creation)}, + ?line TXPid = mk_pid(ThisNode, 32767, 8191), + ?line TXPort = mk_port(ThisNode, 268435455), + ?line TXRef = mk_ref(ThisNode, [262143, 4294967295, 4294967295]), + + ?line OtherNode = {gurka@sallad, 2}, + ?line OXPid = mk_pid(OtherNode, 32767, 8191), + ?line OXPort = mk_port(OtherNode, 268435455), + ?line OXRef = mk_ref(OtherNode, [262143, 4294967295, 4294967295]), + + ?line send_rec(P, TXPid), + ?line send_rec(P, TXPort), + ?line send_rec(P, TXRef), + ?line send_rec(P, OXPid), + ?line send_rec(P, OXPort), + ?line send_rec(P, OXRef), + + ?line runner:recv_eot(P), + ok. + + +%% ######################################################################## %% + +% We read two packets for each test, the ei_decode_encode and ei_x_decode_encode version.... + +send_rec(P, Term) when is_port(P) -> + ?t:format("Testing: ~p~n", [Term]), + P ! {self(), {command, term_to_binary(Term)}}, + {_B,Term} = get_buf_and_term(P). + + + +get_buf_and_term(P) -> + B = get_binaries(P), + case B of + <<131>> -> + io:format("(got single magic, no content)\n",[]), + {B,'$$magic$$'}; + <<131,_>> -> + T = binary_to_term(B), + io:format("~w\n~w\n(got magic)\n",[B,T]), + {B,T}; + _ -> + B1 = list_to_binary([131,B]), % No magic, add + T = binary_to_term(B1), + io:format("~w\n~w\n(got no magic)\n",[B,T]), + {B,T} + end. + + +get_binaries(P) -> + B1 = get_binary(P), + B2 = get_binary(P), + B1 = B2. + +get_binary(P) -> + case runner:get_term(P) of + {bytes,L} -> + B = list_to_binary(L), + io:format("~w\n",[L]), +% For strange reasons <<131>> show up as <>.... +% io:format("~w\n",[B]), + B; + Other -> + Other + end. + +%% + +% We use our own get_term() + +get_term(P) -> + case runner:get_term(P) of + {bytes,[131]} -> + io:format("(got single magic, no content)\n",[]), + '$$magic$$'; + {bytes,[131,L]} -> + B = list_to_binary(L), + T = binary_to_term(B), + io:format("~w\n~w\n(got magic)\n",[L,T]), + T; + {bytes,L} -> + B = list_to_binary([131,L]), + T = binary_to_term(B), + io:format("~w\n~w\n(got no magic)\n",[L,T]), + T; + Other -> + Other + end. + +%% +%% Node container constructor functions +%% + +-define(VERSION_MAGIC, 131). + +-define(ATOM_EXT, 100). +-define(REFERENCE_EXT, 101). +-define(PORT_EXT, 102). +-define(PID_EXT, 103). +-define(NEW_REFERENCE_EXT, 114). + +uint32_be(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 32 -> + [(Uint bsr 24) band 16#ff, + (Uint bsr 16) band 16#ff, + (Uint bsr 8) band 16#ff, + Uint band 16#ff]; +uint32_be(Uint) -> + exit({badarg, uint32_be, [Uint]}). + + +uint16_be(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 16 -> + [(Uint bsr 8) band 16#ff, + Uint band 16#ff]; +uint16_be(Uint) -> + exit({badarg, uint16_be, [Uint]}). + +uint8(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 8 -> + Uint band 16#ff; +uint8(Uint) -> + exit({badarg, uint8, [Uint]}). + + + +mk_pid({NodeName, Creation}, Number, Serial) when is_atom(NodeName) -> + mk_pid({atom_to_list(NodeName), Creation}, Number, Serial); +mk_pid({NodeName, Creation}, Number, Serial) -> + case catch binary_to_term(list_to_binary([?VERSION_MAGIC, + ?PID_EXT, + ?ATOM_EXT, + uint16_be(length(NodeName)), + NodeName, + uint32_be(Number), + uint32_be(Serial), + uint8(Creation)])) of + Pid when is_pid(Pid) -> + Pid; + {'EXIT', {badarg, _}} -> + exit({badarg, mk_pid, [{NodeName, Creation}, Number, Serial]}); + Other -> + exit({unexpected_binary_to_term_result, Other}) + end. + +mk_port({NodeName, Creation}, Number) when is_atom(NodeName) -> + mk_port({atom_to_list(NodeName), Creation}, Number); +mk_port({NodeName, Creation}, Number) -> + case catch binary_to_term(list_to_binary([?VERSION_MAGIC, + ?PORT_EXT, + ?ATOM_EXT, + uint16_be(length(NodeName)), + NodeName, + uint32_be(Number), + uint8(Creation)])) of + Port when is_port(Port) -> + Port; + {'EXIT', {badarg, _}} -> + exit({badarg, mk_port, [{NodeName, Creation}, Number]}); + Other -> + exit({unexpected_binary_to_term_result, Other}) + end. + +mk_ref({NodeName, Creation}, Numbers) when is_atom(NodeName), + is_integer(Creation), + is_list(Numbers) -> + mk_ref({atom_to_list(NodeName), Creation}, Numbers); +mk_ref({NodeName, Creation}, [Number]) when is_list(NodeName), + is_integer(Creation), + is_integer(Number) -> + case catch binary_to_term(list_to_binary([?VERSION_MAGIC, + ?REFERENCE_EXT, + ?ATOM_EXT, + uint16_be(length(NodeName)), + NodeName, + uint32_be(Number), + uint8(Creation)])) of + Ref when is_reference(Ref) -> + Ref; + {'EXIT', {badarg, _}} -> + exit({badarg, mk_ref, [{NodeName, Creation}, [Number]]}); + Other -> + exit({unexpected_binary_to_term_result, Other}) + end; +mk_ref({NodeName, Creation}, Numbers) when is_list(NodeName), + is_integer(Creation), + is_list(Numbers) -> + case catch binary_to_term(list_to_binary([?VERSION_MAGIC, + ?NEW_REFERENCE_EXT, + uint16_be(length(Numbers)), + ?ATOM_EXT, + uint16_be(length(NodeName)), + NodeName, + uint8(Creation), + lists:map(fun (N) -> + uint32_be(N) + end, + Numbers)])) of + Ref when is_reference(Ref) -> + Ref; + {'EXIT', {badarg, _}} -> + exit({badarg, mk_ref, [{NodeName, Creation}, Numbers]}); + Other -> + exit({unexpected_binary_to_term_result, Other}) + end. + diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/Makefile.first b/lib/erl_interface/test/ei_decode_encode_SUITE_data/Makefile.first new file mode 100644 index 0000000000..168a21b10e --- /dev/null +++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/Makefile.first @@ -0,0 +1,21 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2004-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +ei_decode_encode_test_decl.c: ei_decode_encode_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run ei_decode_encode_test -s erlang halt diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_decode_encode_SUITE_data/Makefile.src new file mode 100644 index 0000000000..d43e834558 --- /dev/null +++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/Makefile.src @@ -0,0 +1,42 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2004-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \ + $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + @erl_interface_threadlib@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data +EI_DECODE_ENCODE_OBJS = ei_decode_encode_test@obj@ ei_decode_encode_test_decl@obj@ + +all: ei_decode_encode_test@exe@ + +clean: + $(RM) $(EI_DECODE_ENCODE_OBJS) + $(RM) ei_decode_encode_test@exe@ + +ei_decode_encode_test@exe@: $(EI_DECODE_ENCODE_OBJS) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(EI_DECODE_ENCODE_OBJS) $(LIBFLAGS) + + diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c new file mode 100644 index 0000000000..406f02ecfb --- /dev/null +++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c @@ -0,0 +1,229 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#ifdef VXWORKS +#include "reclaim.h" +#endif + +#include "ei_runner.h" + +/* + * Purpose: Read pids, funs and others without real meaning on the C side + * and pass it back to Erlang to test that it is still the same. + * Author: [email protected] + */ + +#define EI_DECODE_ENCODE(FUNC,TYPE) \ + { \ + char *buf; \ + char buf2[1024]; \ + TYPE p; \ + int size1 = 0; \ + int size2 = 0; \ + int size3 = 0; \ + int err; \ + ei_x_buff arg; \ +\ + message("ei_decode_" #FUNC ", arg is type " #TYPE); \ + buf = read_packet(NULL); \ + err = ei_decode_ ## FUNC(buf+1, &size1, &p); \ + if (err != 0) { \ + if (err != -1) { \ + fail("decode returned non zero but not -1"); \ + } else { \ + fail("decode returned non zero"); \ + } \ + return; \ + } \ + if (size1 < 1) { \ + fail("size is < 1"); \ + return; \ + } \ +\ + message("ei_encode_" #FUNC " buf is NULL, arg is type " #TYPE); \ + err = ei_encode_ ## FUNC(NULL, &size2, &p); \ + if (err != 0) { \ + if (err != -1) { \ + fail("size calculation returned non zero but not -1"); \ + return; \ + } else { \ + fail("size calculation returned non zero"); \ + return; \ + } \ + } \ + if (size1 != size2) { \ + message("size1 = %d, size2 = %d\n",size1,size2); \ + fail("decode and encode size differs when buf is NULL"); \ + return; \ + } \ + message("ei_encode_" #FUNC ", arg is type " #TYPE); \ + err = ei_encode_ ## FUNC(buf2, &size3, &p); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + return; \ + } \ + if (size1 != size3) { \ + message("size1 = %d, size2 = %d\n",size1,size3); \ + fail("decode and encode size differs"); \ + return; \ + } \ + send_buffer(buf2, size1); \ +\ + message("ei_x_encode_" #FUNC ", arg is type " #TYPE); \ + ei_x_new(&arg); \ + err = ei_x_encode_ ## FUNC(&arg, &p); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + ei_x_free(&arg); \ + return; \ + } \ + if (arg.index < 1) { \ + fail("size is < 1"); \ + ei_x_free(&arg); \ + return; \ + } \ + send_buffer(arg.buff, arg.index); \ + ei_x_free(&arg); \ + } + +#define EI_DECODE_ENCODE_BIG(FUNC,TYPE) \ + { \ + char *buf; \ + char buf2[2048]; \ + TYPE *p; \ + int size1 = 0; \ + int size2 = 0; \ + int size3 = 0; \ + int err, index = 0, len, type; \ + ei_x_buff arg; \ +\ + message("ei_decode_" #FUNC ", arg is type " #TYPE); \ + buf = read_packet(NULL); \ + ei_get_type(buf+1, &index, &type, &len); \ + p = ei_alloc_big(len); \ + err = ei_decode_ ## FUNC(buf+1, &size1, p); \ + if (err != 0) { \ + if (err != -1) { \ + fail("decode returned non zero but not -1"); \ + } else { \ + fail("decode returned non zero"); \ + } \ + return; \ + } \ + if (size1 < 1) { \ + fail("size is < 1"); \ + return; \ + } \ +\ + message("ei_encode_" #FUNC " buf is NULL, arg is type " #TYPE); \ + err = ei_encode_ ## FUNC(NULL, &size2, p); \ + if (err != 0) { \ + if (err != -1) { \ + fail("size calculation returned non zero but not -1"); \ + return; \ + } else { \ + fail("size calculation returned non zero"); \ + return; \ + } \ + } \ + if (size1 != size2) { \ + message("size1 = %d, size2 = %d\n",size1,size2); \ + fail("decode and encode size differs when buf is NULL"); \ + return; \ + } \ + message("ei_encode_" #FUNC ", arg is type " #TYPE); \ + err = ei_encode_ ## FUNC(buf2, &size3, p); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + return; \ + } \ + if (size1 != size3) { \ + message("size1 = %d, size2 = %d\n",size1,size3); \ + fail("decode and encode size differs"); \ + return; \ + } \ + send_buffer(buf2, size1); \ +\ + message("ei_x_encode_" #FUNC ", arg is type " #TYPE); \ + ei_x_new(&arg); \ + err = ei_x_encode_ ## FUNC(&arg, p); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + ei_x_free(&arg); \ + return; \ + } \ + if (arg.index < 1) { \ + fail("size is < 1"); \ + ei_x_free(&arg); \ + return; \ + } \ + send_buffer(arg.buff, arg.index); \ + ei_x_free(&arg); \ + ei_free_big(p); \ + } + + + + +/* ******************************************************************** */ + +TESTCASE(test_ei_decode_encode) +{ + EI_DECODE_ENCODE(fun , erlang_fun); + EI_DECODE_ENCODE(pid , erlang_pid); + EI_DECODE_ENCODE(port , erlang_port); + EI_DECODE_ENCODE(ref , erlang_ref); + EI_DECODE_ENCODE(trace, erlang_trace); + + EI_DECODE_ENCODE_BIG(big , erlang_big); + EI_DECODE_ENCODE_BIG(big , erlang_big); + EI_DECODE_ENCODE_BIG(big , erlang_big); + + EI_DECODE_ENCODE_BIG(big , erlang_big); + EI_DECODE_ENCODE_BIG(big , erlang_big); + EI_DECODE_ENCODE_BIG(big , erlang_big); + + /* Test large node containers... */ + EI_DECODE_ENCODE(pid , erlang_pid); + EI_DECODE_ENCODE(port , erlang_port); + EI_DECODE_ENCODE(ref , erlang_ref); + EI_DECODE_ENCODE(pid , erlang_pid); + EI_DECODE_ENCODE(port , erlang_port); + EI_DECODE_ENCODE(ref , erlang_ref); + + report(1); +} + +/* ******************************************************************** */ diff --git a/lib/erl_interface/test/ei_encode_SUITE.erl b/lib/erl_interface/test/ei_encode_SUITE.erl new file mode 100644 index 0000000000..fb790eb7c3 --- /dev/null +++ b/lib/erl_interface/test/ei_encode_SUITE.erl @@ -0,0 +1,315 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(ei_encode_SUITE). + +-include("test_server.hrl"). +-include("ei_encode_SUITE_data/ei_encode_test_cases.hrl"). + +-export( + [ + all/1, + test_ei_encode_long/1, + test_ei_encode_ulong/1, + test_ei_encode_longlong/1, + test_ei_encode_ulonglong/1, + test_ei_encode_char/1, + test_ei_encode_misc/1, + test_ei_encode_fails/1 + ]). + +all(suite) -> + [ + test_ei_encode_long, + test_ei_encode_ulong, + test_ei_encode_longlong, + test_ei_encode_ulonglong, + test_ei_encode_char, + test_ei_encode_misc, + test_ei_encode_fails + ]. + +%% --------------------------------------------------------------------------- + +% NOTE: for historical reasons we don't pach as tight as we can, +% we only fill 27 bits in 32 bit INTEGER_EXT + + +%% ######################################################################## %% + +test_ei_encode_long(suite) -> []; +test_ei_encode_long(Config) when is_list(Config) -> + ?line P = runner:start(?test_ei_encode_long), + + ?line {<<97,0>> ,0} = get_buf_and_term(P), + ?line {<<97,255>> ,255} = get_buf_and_term(P), + ?line {<<98,256:32/big-signed-integer>>,256} = get_buf_and_term(P), + ?line {<<98,-1:32/big-signed-integer>> ,-1} = get_buf_and_term(P), + + ?line {<<98, 16#07ffffff:32/big-signed-integer>>, 16#07ffffff} = get_buf_and_term(P), + ?line {<<98,-16#08000000:32/big-signed-integer>>,-16#08000000} = get_buf_and_term(P), + ?line {<<110,4,0, 0,0,0,8>> , 16#08000000} = get_buf_and_term(P), + ?line {<<110,4,1, 1,0,0,8>> ,-16#08000001} = get_buf_and_term(P), + + ?line {<<110,4,0, 255,255,255,127>> , 16#7fffffff} = get_buf_and_term(P), + ?line {<<110,4,1, 0,0,0,128>> ,-16#80000000} = get_buf_and_term(P), + + ?line runner:recv_eot(P), + ok. + + +%% ######################################################################## %% + +test_ei_encode_ulong(suite) -> []; +test_ei_encode_ulong(Config) when is_list(Config) -> + ?line P = runner:start(?test_ei_encode_ulong), + + ?line {<<97,0>> ,0} = get_buf_and_term(P), + ?line {<<97,255>> ,255} = get_buf_and_term(P), + ?line {<<98,256:32/big-unsigned-integer>>,256} = get_buf_and_term(P), + + ?line {<<98, 16#07ffffff:32/big-signed-integer>>,16#07ffffff} = get_buf_and_term(P), + ?line {<<110,4,0, 0,0,0,8>> ,16#08000000} = get_buf_and_term(P), + + ?line {<<110,4,0, 255,255,255,127>> ,16#7fffffff} = get_buf_and_term(P), + ?line {<<110,4,0, 0,0,0,128>> ,16#80000000} = get_buf_and_term(P), + ?line {<<110,4,0, 255,255,255,255>> ,16#ffffffff} = get_buf_and_term(P), + + ?line runner:recv_eot(P), + ok. + + +%% ######################################################################## %% + +test_ei_encode_longlong(suite) -> []; +test_ei_encode_longlong(Config) when is_list(Config) -> + case os:type() of + vxworks -> + {skip,"Skipped on VxWorks"}; + _ -> + ?line P = runner:start(?test_ei_encode_longlong), + + ?line {<<97,0>> ,0} = get_buf_and_term(P), + ?line {<<97,255>> ,255} = get_buf_and_term(P), + ?line {<<98,256:32/big-signed-integer>>,256} = get_buf_and_term(P), + ?line {<<98,-1:32/big-signed-integer>> ,-1} = get_buf_and_term(P), + + ?line {<<98, 16#07ffffff:32/big-signed-integer>>, 16#07ffffff} = get_buf_and_term(P), + ?line {<<98,-16#08000000:32/big-signed-integer>>,-16#08000000} = get_buf_and_term(P), + ?line {<<110,4,0, 0,0,0,8>> , 16#08000000} = get_buf_and_term(P), + ?line {<<110,4,1, 1,0,0,8>> ,-16#08000001} = get_buf_and_term(P), + + ?line {<<110,4,0, 255,255,255,127>> , 16#7fffffff} = get_buf_and_term(P), + ?line {<<110,4,1, 0,0,0,128>> ,-16#80000000} = get_buf_and_term(P), + ?line {<<110,6,0, 255,255,255,255,255,127>> , 16#7fffffffffff} = get_buf_and_term(P), + ?line {<<110,6,1, 0,0,0,0,0,128>> ,-16#800000000000} = get_buf_and_term(P), + ?line {<<110,8,0, 255,255,255,255,255,255,255,127>>,16#7fffffffffffffff} = get_buf_and_term(P), + ?line {<<110,8,1, 0,0,0,0,0,0,0,128>> ,-16#8000000000000000} = get_buf_and_term(P), + + ?line runner:recv_eot(P), + ok + end. + + +%% ######################################################################## %% + +test_ei_encode_ulonglong(suite) -> []; +test_ei_encode_ulonglong(Config) when is_list(Config) -> + case os:type() of + vxworks -> + {skip,"Skipped on VxWorks"}; + _ -> + ?line P = runner:start(?test_ei_encode_ulonglong), + + ?line {<<97,0>> ,0} = get_buf_and_term(P), + ?line {<<97,255>> ,255} = get_buf_and_term(P), + ?line {<<98,256:32/big-unsigned-integer>>,256} = get_buf_and_term(P), + + ?line {<<98, 16#07ffffff:32/big-signed-integer>>,16#07ffffff} = get_buf_and_term(P), + ?line {<<110,4,0, 0,0,0,8>> ,16#08000000} = get_buf_and_term(P), + + ?line {<<110,4,0, 255,255,255,127>> ,16#7fffffff} = get_buf_and_term(P), + ?line {<<110,4,0, 0,0,0,128>> ,16#80000000} = get_buf_and_term(P), + ?line {<<110,4,0, 255,255,255,255>> ,16#ffffffff} = get_buf_and_term(P), + ?line {<<110,6,0, 255,255,255,255,255,255>>,16#ffffffffffff} = get_buf_and_term(P), + ?line {<<110,8,0, 255,255,255,255,255,255,255,255>>,16#ffffffffffffffff} = get_buf_and_term(P), + + ?line runner:recv_eot(P), + ok + end. + + +%% ######################################################################## %% +%% A "character" for us is an 8 bit integer, alwasy positive, i.e. +%% it is unsigned. +%% FIXME maybe the API should change to use "unsigned char" to be clear?! + +test_ei_encode_char(suite) -> []; +test_ei_encode_char(Config) when is_list(Config) -> + ?line P = runner:start(?test_ei_encode_char), + + ?line {<<97, 0>>,0} = get_buf_and_term(P), + ?line {<<97,127>>,16#7f} = get_buf_and_term(P), + ?line {<<97,255>>,16#ff} = get_buf_and_term(P), + + ?line runner:recv_eot(P), + ok. + + +%% ######################################################################## %% + +test_ei_encode_misc(suite) -> []; +test_ei_encode_misc(Config) when is_list(Config) -> + ?line P = runner:start(?test_ei_encode_misc), + + ?line <<131>> = get_binaries(P), + +% ?line {term,F} = get_term(P), +% ?line match_float(F, 0.0), +% ?line {term,F} = get_term(P), +% ?line match_float(F, 0.0), + +% ?line {term,F} = get_term(P), +% ?line true = match_float(F, -1.0), +% ?line {term,F} = get_term(P), +% ?line true = match_float(F, -1.0), + +% ?line {term,F} = get_term(P), +% ?line true = match_float(F, 1.0), +% ?line {term,F} = get_term(P), +% ?line true = match_float(F, 1.0), + + ?line {<<100,0,5,"false">>,false} = get_buf_and_term(P), + ?line {<<100,0,4,"true">> ,true} = get_buf_and_term(P), + ?line {<<100,0,4,"true">> ,true} = get_buf_and_term(P), + ?line {<<100,0,4,"true">> ,true} = get_buf_and_term(P), + + ?line {<<100,0,3,"foo">>,foo} = get_buf_and_term(P), + ?line {<<100,0,3,"foo">>,foo} = get_buf_and_term(P), + ?line {<<100,0,0,"">>,''} = get_buf_and_term(P), + ?line {<<100,0,0,"">>,''} = get_buf_and_term(P), + ?line {<<100,0,6,"������">>,'������'} = get_buf_and_term(P), + ?line {<<100,0,6,"������">>,'������'} = get_buf_and_term(P), + + ?line {<<107,0,3,"foo">>,"foo"} = get_buf_and_term(P), + ?line {<<107,0,3,"foo">>,"foo"} = get_buf_and_term(P), + ?line {<<106>>,""} = get_buf_and_term(P), + ?line {<<106>>,""} = get_buf_and_term(P), + ?line {<<107,0,6,"������">>,"������"} = get_buf_and_term(P), + ?line {<<107,0,6,"������">>,"������"} = get_buf_and_term(P), + + ?line {<<109,0,0,0,3,"foo">>,<<"foo">>} = get_buf_and_term(P), + ?line {<<109,0,0,0,0,"">>,<<>>} = get_buf_and_term(P), + ?line {<<109,0,0,0,6,"������">>,<<"������">>} = get_buf_and_term(P), + + ?line {<<104,0>>,{}} = get_buf_and_term(P), % Tuple header for {} + ?line {<<106>>,[]} = get_buf_and_term(P), % Empty list [] + + ?line runner:recv_eot(P), + ok. + + +%% ######################################################################## %% + +test_ei_encode_fails(suite) -> []; +test_ei_encode_fails(Config) when is_list(Config) -> + ?line P = runner:start(?test_ei_encode_fails), + + ?line XAtom = list_to_atom(lists:duplicate(255, $x)), + ?line YAtom = list_to_atom(lists:duplicate(255, $y)), + + ?line XAtom = get_term(P), + ?line XAtom = get_term(P), + ?line YAtom = get_term(P), + ?line YAtom = get_term(P), + + ?line {{{{}}}} = get_term(P), + + ?line runner:recv_eot(P), + ok. + + +%% ######################################################################## %% + +% We read two packets for each test, the ei_encode and ei_x_encode version.... + +get_buf_and_term(P) -> + B = get_binaries(P), + case B of + <<131>> -> + io:format("(got single magic, no content)\n",[]), + {B,'$$magic$$'}; + <<131,_>> -> + T = binary_to_term(B), + io:format("~w\n~w\n(got magic)\n",[B,T]), + {B,T}; + _ -> + B1 = list_to_binary([131,B]), % No magic, add + T = binary_to_term(B1), + io:format("~w\n~w\n(got no magic)\n",[B,T]), + {B,T} + end. + + +get_binaries(P) -> + B1 = get_binary(P), + B2 = get_binary(P), + B1 = B2. + +get_binary(P) -> + case runner:get_term(P) of + {bytes,L} -> + B = list_to_binary(L), + io:format("~w\n",[L]), +% For strange reasons <<131>> show up as <>.... +% io:format("~w\n",[B]), + B; + Other -> + Other + end. + +%% + +% We use our own get_term() + +get_term(P) -> + case runner:get_term(P) of + {bytes,[131]} -> + io:format("(got single magic, no content)\n",[]), + '$$magic$$'; + {bytes,[131,L]} -> + B = list_to_binary(L), + T = binary_to_term(B), + io:format("~w\n~w\n(got magic)\n",[L,T]), + T; + {bytes,L} -> + B = list_to_binary([131,L]), + T = binary_to_term(B), + io:format("~w\n~w\n(got no magic)\n",[L,T]), + T; + Other -> + Other + end. + +%% + +match_float(F, Match) when is_float(F), F > Match*0.99, F < Match*1.01 -> + true. + diff --git a/lib/erl_interface/test/ei_encode_SUITE_data/Makefile.first b/lib/erl_interface/test/ei_encode_SUITE_data/Makefile.first new file mode 100644 index 0000000000..19a6f4c0aa --- /dev/null +++ b/lib/erl_interface/test/ei_encode_SUITE_data/Makefile.first @@ -0,0 +1,21 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2004-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +ei_encode_test_decl.c: ei_encode_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run ei_encode_test -s erlang halt diff --git a/lib/erl_interface/test/ei_encode_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_encode_SUITE_data/Makefile.src new file mode 100644 index 0000000000..f2a2c40615 --- /dev/null +++ b/lib/erl_interface/test/ei_encode_SUITE_data/Makefile.src @@ -0,0 +1,42 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2004-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \ + $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + @erl_interface_threadlib@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data +EI_ENCODE_OBJS = ei_encode_test@obj@ ei_encode_test_decl@obj@ + +all: ei_encode_test@exe@ + +clean: + $(RM) $(EI_ENCODE_OBJS) + $(RM) ei_encode_test@exe@ + +ei_encode_test@exe@: $(EI_ENCODE_OBJS) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(EI_ENCODE_OBJS) $(LIBFLAGS) + + diff --git a/lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c b/lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c new file mode 100644 index 0000000000..f8de0b7878 --- /dev/null +++ b/lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c @@ -0,0 +1,466 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2004-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#ifdef VXWORKS +#include "reclaim.h" +#endif + +#include "ei_runner.h" + +/* + * Purpose: Tests the ei_format() function. + * Author: Kent + */ + +#define EI_ENCODE_0(FUNC) \ + { \ + char buf[1024]; \ + int size1 = 0; \ + int size2 = 0; \ + int err; \ + message("ei_" #FUNC " encoded as "); \ + err = ei_ ## FUNC(NULL, &size1); \ + if (err != 0) { \ + if (err != -1) { \ + fail("size calculation returned non zero but not -1"); \ + return; \ + } else { \ + fail("size calculation returned non zero"); \ + return; \ + } \ + } \ + err = ei_ ## FUNC(buf, &size2); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + return; \ + } \ + if (size1 != size2) { \ + fail("size differs when arg is NULL or buf"); \ + return; \ + } \ + if (size1 < 1) { \ + fail("size is < 1"); \ + return; \ + } \ + send_buffer(buf, size1); \ + } \ + { \ + ei_x_buff arg; \ + int err; \ + message("ei_x_" #FUNC " encoded as "); \ + ei_x_new(&arg); \ + err = ei_x_ ## FUNC(&arg); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + ei_x_free(&arg); \ + return; \ + } \ + if (arg.index < 1) { \ + fail("size is < 1"); \ + ei_x_free(&arg); \ + return; \ + } \ + send_buffer(arg.buff, arg.index); \ + ei_x_free(&arg); \ + } + +#define EI_ENCODE_1(FUNC,ARG) \ + { \ + char buf[1024]; \ + int size1 = 0; \ + int size2 = 0; \ + int err; \ + message("ei_" #FUNC " " #ARG " encoded as "); \ + err = ei_ ## FUNC(NULL, &size1, ARG); \ + if (err != 0) { \ + if (err != -1) { \ + fail("size calculation returned non zero but not -1"); \ + return; \ + } else { \ + fail("size calculation returned non zero"); \ + return; \ + } \ + } \ + err = ei_ ## FUNC(buf, &size2, ARG); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + return; \ + } \ + if (size1 != size2) { \ + fail("size differs when arg is NULL or buf"); \ + return; \ + } \ + if (size1 < 1) { \ + fail("size is < 1"); \ + return; \ + } \ + send_buffer(buf, size1); \ + } \ + { \ + ei_x_buff arg; \ + int err; \ + message("ei_x_" #FUNC " " #ARG " encoded as "); \ + ei_x_new(&arg); \ + err = ei_x_ ## FUNC(&arg, ARG); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + ei_x_free(&arg); \ + return; \ + } \ + if (arg.index < 1) { \ + fail("size is < 1"); \ + ei_x_free(&arg); \ + return; \ + } \ + send_buffer(arg.buff, arg.index); \ + ei_x_free(&arg); \ + } + +#define EI_ENCODE_2(FUNC,ARG1,ARG2) \ + { \ + char buf[1024]; \ + int size1 = 0; \ + int size2 = 0; \ + int err; \ + message("ei_" #FUNC " " #ARG1 " " #ARG2 " encoded as "); \ + err = ei_ ## FUNC(NULL, &size1, ARG1, ARG2); \ + if (err != 0) { \ + if (err != -1) { \ + fail("size calculation returned non zero but not -1"); \ + return; \ + } else { \ + fail("size calculation returned non zero"); \ + return; \ + } \ + } \ + err = ei_ ## FUNC(buf, &size2, ARG1, ARG2); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + return; \ + } \ + if (size1 != size2) { \ + fail("size differs when arg is NULL or buf"); \ + return; \ + } \ + if (size1 < 1) { \ + fail("size is < 1"); \ + return; \ + } \ + send_buffer(buf, size1); \ + } \ + { \ + ei_x_buff arg; \ + int err; \ + message("ei_x_" #FUNC " " #ARG1 " " #ARG2 " encoded as "); \ + ei_x_new(&arg); \ + err = ei_x_ ## FUNC(&arg, ARG1, ARG2); \ + if (err != 0) { \ + if (err != -1) { \ + fail("returned non zero but not -1"); \ + } else { \ + fail("returned non zero"); \ + } \ + ei_x_free(&arg); \ + return; \ + } \ + if (arg.index < 1) { \ + fail("size is < 1"); \ + ei_x_free(&arg); \ + return; \ + } \ + send_buffer(arg.buff, arg.index); \ + ei_x_free(&arg); \ + } + +/* ******************************************************************** */ + +TESTCASE(test_ei_encode_long) +{ + EI_ENCODE_1(encode_long, 0); + + EI_ENCODE_1(encode_long, 255); + + EI_ENCODE_1(encode_long, 256); + + EI_ENCODE_1(encode_long, -1); + + EI_ENCODE_1(encode_long, 0x07ffffff); + + EI_ENCODE_1(encode_long, -ll(0x08000000)); + + EI_ENCODE_1(encode_long, 0x07ffffff+1); + + EI_ENCODE_1(encode_long, -ll(0x08000000)-1); + + EI_ENCODE_1(encode_long, 0x7fffffff); + + EI_ENCODE_1(encode_long, -ll(0x80000000)); + + report(1); +} + +/* ******************************************************************** */ + +TESTCASE(test_ei_encode_ulong) +{ + EI_ENCODE_1(encode_ulong, 0); + + EI_ENCODE_1(encode_ulong, 255); + + EI_ENCODE_1(encode_ulong, 256); + + EI_ENCODE_1(encode_ulong, 0x07ffffff); + + EI_ENCODE_1(encode_ulong, 0x07ffffff+1); + + EI_ENCODE_1(encode_ulong, 0x7fffffff); + + EI_ENCODE_1(encode_ulong, 0x80000000); + + EI_ENCODE_1(encode_ulong, 0xffffffff); + + report(1); +} + +/* ******************************************************************** */ + + +TESTCASE(test_ei_encode_longlong) +{ + +#ifndef VXWORKS + + EI_ENCODE_1(encode_longlong, 0); + + EI_ENCODE_1(encode_longlong, 255); + + EI_ENCODE_1(encode_longlong, 256); + + EI_ENCODE_1(encode_longlong, -1); + + EI_ENCODE_1(encode_longlong, 0x07ffffff); + + EI_ENCODE_1(encode_longlong, -ll(0x08000000)); + + EI_ENCODE_1(encode_longlong, 0x07ffffff+1); + + EI_ENCODE_1(encode_longlong, -ll(0x08000000)-1); + + EI_ENCODE_1(encode_longlong, 0x7fffffff); + + EI_ENCODE_1(encode_longlong, -ll(0x80000000)); + + EI_ENCODE_1(encode_longlong, ll(0x7fffffffffff)); + + EI_ENCODE_1(encode_longlong, -ll(0x800000000000)); + + EI_ENCODE_1(encode_longlong, ll(0x7fffffffffffffff)); + + EI_ENCODE_1(encode_longlong, -ll(0x8000000000000000)); + +#endif /* !VXWORKS */ + + report(1); +} + +/* ******************************************************************** */ + +TESTCASE(test_ei_encode_ulonglong) +{ + +#ifndef VXWORKS + + EI_ENCODE_1(encode_ulonglong, 0); + + EI_ENCODE_1(encode_ulonglong, 255); + + EI_ENCODE_1(encode_ulonglong, 256); + + EI_ENCODE_1(encode_ulonglong, 0x07ffffff); + + EI_ENCODE_1(encode_ulonglong, 0x07ffffff+1); + + EI_ENCODE_1(encode_ulonglong, 0x7fffffff); + + EI_ENCODE_1(encode_ulonglong, 0x80000000); + + EI_ENCODE_1(encode_ulonglong, 0xffffffff); + + EI_ENCODE_1(encode_ulonglong, ll(0xffffffffffff)); + + EI_ENCODE_1(encode_ulonglong, ll(0xffffffffffffffff)); + +#endif /* !VXWORKS */ + + report(1); +} + + +/* ******************************************************************** */ + +TESTCASE(test_ei_encode_char) +{ + EI_ENCODE_1(encode_char, 0); + + EI_ENCODE_1(encode_char, 0x7f); + + EI_ENCODE_1(encode_char, 0xff); + + report(1); +} + +/* ******************************************************************** */ + +TESTCASE(test_ei_encode_misc) +{ + EI_ENCODE_0(encode_version); +/* + EI_ENCODE_1(encode_double, 0.0); + + EI_ENCODE_1(encode_double, -1.0); + + EI_ENCODE_1(encode_double, 1.0); +*/ + EI_ENCODE_1(encode_boolean, 0) /* Only case it should be false */; + + EI_ENCODE_1(encode_boolean, 1); + + EI_ENCODE_1(encode_boolean, 42); + + EI_ENCODE_1(encode_boolean, -1); + + EI_ENCODE_1(encode_atom, "foo"); + EI_ENCODE_2(encode_atom_len, "foo", 3); + + EI_ENCODE_1(encode_atom, ""); + EI_ENCODE_2(encode_atom_len, "", 0); + + EI_ENCODE_1(encode_atom, "������"); + EI_ENCODE_2(encode_atom_len, "������", 6); + + EI_ENCODE_1(encode_string, "foo"); + EI_ENCODE_2(encode_string_len, "foo", 3); + + EI_ENCODE_1(encode_string, ""); + EI_ENCODE_2(encode_string_len, "", 0); + + EI_ENCODE_1(encode_string, "������"); + EI_ENCODE_2(encode_string_len, "������", 6); + + EI_ENCODE_2(encode_binary, "foo", 3); + EI_ENCODE_2(encode_binary, "", 0); + EI_ENCODE_2(encode_binary, "������", 6); + + /* FIXME check \0 in strings and atoms */ + + EI_ENCODE_1(encode_tuple_header, 0); + + EI_ENCODE_0(encode_empty_list); + + report(1); +} + +/* ******************************************************************** */ + +TESTCASE(test_ei_encode_fails) +{ + char buf[1024]; + int index; + + /* FIXME the ei_x versions are not tested */ + + index = 0; + if (ei_encode_atom(buf, &index, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") != 0) { + fail("could not encode atom with 255 chars"); + } + message("Encoding atom with 255 chars, encoded %d",index); + if (index != 255+3) { + fail("encoded with incorrect size"); + } + send_buffer(buf, index); + + index = 0; + if (ei_encode_atom_len(buf, &index, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 255) != 0) { + fail("could not encode atom with 255 chars"); + } + message("Encoding atom with 255 chars, encoded %d",index); + if (index != 255+3) { + fail("encoded with incorrect size"); + } + send_buffer(buf, index); + + index = 0; + if (ei_encode_atom(buf, &index, "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy") != 0) { + fail("could not encode atom with 256 chars, truncated to 255"); + } + message("Encoding atom with 256 chars, encoded %d",index); + if (index != 255+3) { + fail("did not truncate at 255 chars"); + } + send_buffer(buf, index); + + index = 0; + if (ei_encode_atom_len(buf, &index, "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", 256) != 0) { + fail("could not encode atom with 256 chars, truncated to 255"); + } + message("Encoding atom with 256 chars, encoded %d",index); + if (index != 255+3) { + fail("did not truncate at 255 chars"); + } + send_buffer(buf, index); + + /* ---------------------------------------------------------------------- */ + + index = 0; + if (ei_encode_tuple_header(buf, &index, 1) != 0) { + fail("could not create tuple header arity 1, take 1"); + } + if (ei_encode_tuple_header(buf, &index, 1) != 0) { + fail("could not create tuple header arity 1, take 2"); + } + if (ei_encode_tuple_header(buf, &index, 1) != 0) { + fail("could not create tuple header arity 1, take 3"); + } + if (ei_encode_tuple_header(buf, &index, 0) != 0) { + fail("could not create tuple header arity 0"); + } + send_buffer(buf, index); + + report(1); +} diff --git a/lib/erl_interface/test/ei_format_SUITE.erl b/lib/erl_interface/test/ei_format_SUITE.erl new file mode 100644 index 0000000000..7871f07ae9 --- /dev/null +++ b/lib/erl_interface/test/ei_format_SUITE.erl @@ -0,0 +1,161 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(ei_format_SUITE). + +-include("test_server.hrl"). +-include("ei_format_SUITE_data/ei_format_test_cases.hrl"). + +-export([ + format_wo_ver/1, + all/1, + atoms/1, + tuples/1, + lists/1 + ]). + +-import(runner, [get_term/1]). + +%% This test suite test the erl_format() function. +%% It uses the port program "ei_format_test". + +all(suite) -> [ + format_wo_ver, + atoms, + tuples, + lists + ]. + +%% Tests formatting various atoms. + +atoms(suite) -> []; +atoms(Config) when is_list(Config) -> + ?line P = runner:start(?atoms), + + ?line {term, ''} = get_term(P), + ?line {term, 'a'} = get_term(P), + ?line {term, 'A'} = get_term(P), + ?line {term, 'abc'} = get_term(P), + ?line {term, 'Abc'} = get_term(P), + ?line {term, 'ab@c'} = get_term(P), + ?line {term, 'The rain in Spain stays mainly in the plains'} = + get_term(P), + + ?line {term, a} = get_term(P), + ?line {term, ab} = get_term(P), + ?line {term, abc} = get_term(P), + ?line {term, ab@c} = get_term(P), + ?line {term, abcdefghijklmnopq} = get_term(P), + + ?line {term, ''} = get_term(P), + ?line {term, 'a'} = get_term(P), + ?line {term, 'A'} = get_term(P), + ?line {term, 'abc'} = get_term(P), + ?line {term, 'Abc'} = get_term(P), + ?line {term, 'ab@c'} = get_term(P), + ?line {term, 'The rain in Spain stays mainly in the plains'} = + get_term(P), + + ?line {term, a} = get_term(P), + ?line {term, ab} = get_term(P), + ?line {term, abc} = get_term(P), + ?line {term, ab@c} = get_term(P), + ?line {term, ' abcdefghijklmnopq '} = get_term(P), + + ?line runner:recv_eot(P), + ok. + + + +%% Tests formatting various tuples + +tuples(suite) -> []; +tuples(Config) when is_list(Config) -> + ?line P = runner:start(?tuples), + + ?line {term, {}} = get_term(P), + ?line {term, {a}} = get_term(P), + ?line {term, {a, b}} = get_term(P), + ?line {term, {a, b, c}} = get_term(P), + ?line {term, {1}} = get_term(P), + ?line {term, {[]}} = get_term(P), + ?line {term, {[], []}} = get_term(P), + ?line {term, {[], a, b, c}} = get_term(P), + ?line {term, {[], a, [], b, c}} = get_term(P), + ?line {term, {[], a, '', b, c}} = get_term(P), + + ?line runner:recv_eot(P), + ok. + + + +%% Tests formatting various lists + +lists(suite) -> []; +lists(Config) when is_list(Config) -> + ?line P = runner:start(?lists), + + ?line {term, []} = get_term(P), + ?line {term, [a]} = get_term(P), + ?line {term, [a, b]} = get_term(P), + ?line {term, [a, b, c]} = get_term(P), + ?line {term, [1]} = get_term(P), + ?line {term, [[]]} = get_term(P), + ?line {term, [[], []]} = get_term(P), + ?line {term, [[], a, b, c]} = get_term(P), + ?line {term, [[], a, [], b, c]} = get_term(P), + ?line {term, [[], a, '', b, c]} = get_term(P), + ?line {term, [[x, 2], [y, 3], [z, 4]]}= get_term(P), + ?line {term, [{a,b},{c,d}]}= get_term(P), +%% ?line {term, [{name, 'Madonna'}, {age, 21}, {data, [{addr, "E-street", 42}]}]} = +%% get_term(P), + + ?line {term, [{pi, F1}, {'cos(70)', F2}]} = get_term(P), + %% don't match floats directly + true= abs(3.1415-F1) < 0.01, + true= abs(0.34202-F2) < 0.01, + + ?line {term, [[pi, F3], ['cos(70)', F4]]} = get_term(P), + true= abs(3.1415-F3) < 0.01, + true= abs(0.34202-F4) < 0.01, + + +%% ?line {term, [[pi, 3.1415], [], ["cos(70)", 0.34202]]} = get_term(P), + ?line {term, [-1]} = get_term(P), + ?line {term, "hejsan"} = get_term(P), + + + ?line Str1 = lists:duplicate(65535,$A), + ?line Str2 = lists:duplicate(65536,$A), + ?line {term,Str1} = get_term(P), + ?line {term,Str2} = get_term(P), + + ?line runner:recv_eot(P), + ok. + + +format_wo_ver(suite) -> []; +format_wo_ver(Config) when is_list(Config) -> + ?line P = runner:start(?format_wo_ver), + + ?line {term, [{a, "b"}, {c, 10}]} = get_term(P), + + ?line runner:recv_eot(P), + ok. diff --git a/lib/erl_interface/test/ei_format_SUITE_data/Makefile.first b/lib/erl_interface/test/ei_format_SUITE_data/Makefile.first new file mode 100644 index 0000000000..1247ce08c7 --- /dev/null +++ b/lib/erl_interface/test/ei_format_SUITE_data/Makefile.first @@ -0,0 +1,21 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +ei_format_test_decl.c: ei_format_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run ei_format_test -s erlang halt diff --git a/lib/erl_interface/test/ei_format_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_format_SUITE_data/Makefile.src new file mode 100644 index 0000000000..73d51794e9 --- /dev/null +++ b/lib/erl_interface/test/ei_format_SUITE_data/Makefile.src @@ -0,0 +1,42 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \ + $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + @erl_interface_threadlib@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data +EI_FORMAT_OBJS = ei_format_test@obj@ ei_format_test_decl@obj@ + +all: ei_format_test@exe@ + +clean: + $(RM) $(EI_FORMAT_OBJS) + $(RM) ei_format_test@exe@ + +ei_format_test@exe@: $(EI_FORMAT_OBJS) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(EI_FORMAT_OBJS) $(LIBFLAGS) + + diff --git a/lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c b/lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c new file mode 100644 index 0000000000..a969ded3dc --- /dev/null +++ b/lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c @@ -0,0 +1,184 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#ifdef VXWORKS +#include "reclaim.h" +#endif + +#include "ei_runner.h" + +/* + * Purpose: Tests the ei_format() function. + * Author: Jakob + */ + +static void +send_format2(char* format, char* p) +{ + ei_x_buff x; + ei_x_new(&x); + ei_x_format(&x, format, p); + send_bin_term(&x); + free(x.buff); +} + +static void +send_format(char* format) +{ + send_format2(format, NULL); +} + +TESTCASE(atoms) +{ + send_format("''"); + send_format("'a'"); + send_format("'A'"); + send_format("'abc'"); + send_format("'Abc'"); + send_format("'ab@c'"); + send_format("'The rain in Spain stays mainly in the plains'"); + + send_format("a"); + send_format("ab"); + send_format("abc"); + send_format("ab@c"); + send_format(" abcdefghijklmnopq "); + + send_format2("~a", ""); + send_format2("~a", "a"); + send_format2("~a", "A"); + send_format2("~a", "abc"); + send_format2("~a", "Abc"); + send_format2("~a", "ab@c"); + send_format2("~a", "The rain in Spain stays mainly in the plains"); + + send_format2("~a", "a"); + send_format2("~a", "ab"); + send_format2("~a", "abc"); + send_format2("~a","ab@c"); + send_format2("~a", " abcdefghijklmnopq "); + + + report(1); +} + +TESTCASE(tuples) +{ + send_format("{}"); + send_format("{a}"); + send_format("{a, b}"); + send_format("{a, b, c}"); + send_format("{1}"); + send_format("{[]}"); + send_format("{[], []}"); + send_format("{[], a, b, c}"); + send_format("{[], a, [], b, c}"); + send_format("{[], a, '', b, c}"); + + report(1); +} + + + +TESTCASE(lists) +{ +/* FIXME cases to add? + ETERM* a; + ETERM* b; + ETERM* c; +*/ + ei_x_buff x; + static char str[65537]; + + send_format("[]"); + send_format("[a]"); + send_format("[a, b]"); + send_format("[a, b, c]"); + send_format("[1]"); + send_format("[[]]"); + send_format("[[], []]"); + send_format("[[], a, b, c]"); + send_format("[[], a, [], b, c]"); + send_format("[[], a, '', b, c]"); + send_format("[[x, 2], [y, 3], [z, 4]]"); + send_format("[{a,b},{c,d}]"); /* OTP-4777 */ + + ei_x_new(&x); +/* + b = erl_format("[{addr, ~s, ~i}]", "E-street", 42); + a = ei_format(x, "[{name, ~a}, {age, ~i}, {data, ~w}]", "Madonna", 21, b); + send_bin_term(a); + erl_free_term(b);*/ + ei_x_format(&x, "[{pi, ~f}, {'cos(70)', ~f}]", (float)3.1415, (float)0.34202); + send_bin_term(&x); + x.index = 0; /* otherwise it'll send the previous term again */ + ei_x_format(&x, "[[pi, ~d], ['cos(70)', ~d]]", 3.1415, 0.34202); + send_bin_term(&x); + +/* a = erl_mk_float(3.1415); + b = erl_mk_float(0.34202); + send_bin_term(ei_format("[[pi, ~w], ['cos(70)', ~w]]", a, b)); + erl_free_term(a); + erl_free_term(b); + + a = erl_mk_float(3.1415); + b = erl_mk_float(0.34202); + c = erl_mk_empty_list(); + send_bin_term(ei_format("[[~a, ~w], ~w, [~s, ~w]]", "pi", a, c, "cos(70)", b)); + erl_free_term(a); + erl_free_term(b); + erl_free_term(c); +*/ + x.index = 0; /* otherwise it'll send the previous term again */ + ei_x_format(&x, "[~i]", -1); + send_bin_term(&x); + + x.index = 0; + ei_x_format(&x, "~s","hejsan"); + send_bin_term(&x); + + memset(str,'A',65535); + str[65535] = '\0'; + str[65536] = '\0'; + x.index = 0; + ei_x_format(&x, "~s",str); + send_bin_term(&x); + str[65535] = 'A'; + x.index = 0; + ei_x_format(&x, "~s",str); + send_bin_term(&x); + + + free(x.buff); + report(1); +} + +TESTCASE(format_wo_ver) { +/* OTP-6795 + * make example with format_wo_ver + */ + ei_x_buff x; + + ei_x_new (&x); + ei_x_format(&x, "[{~a,~s},{~a,~i}]", "a", "b", "c", 10); + send_bin_term(&x); + + free(x.buff); + report(1); +} diff --git a/lib/erl_interface/test/ei_print_SUITE.erl b/lib/erl_interface/test/ei_print_SUITE.erl new file mode 100644 index 0000000000..a0f15338c6 --- /dev/null +++ b/lib/erl_interface/test/ei_print_SUITE.erl @@ -0,0 +1,142 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(ei_print_SUITE). + +-include("test_server.hrl"). +-include("ei_print_SUITE_data/ei_print_test_cases.hrl"). + +-export([all/1, atoms/1, tuples/1, lists/1, strings/1]). + +-import(runner, [get_term/1]). + +%% This test suite test the ei_print() function. +%% It uses the port program "ei_format_test". + +all(suite) -> [atoms, tuples, lists, strings]. + +%% Tests formatting various atoms. + +atoms(suite) -> []; +atoms(Config) when is_list(Config) -> + ?line P = runner:start(?atoms), + + ?line {term, "''"} = get_term(P), + ?line {term, "a"} = get_term(P), + ?line {term, "'A'"} = get_term(P), + ?line {term, "abc"} = get_term(P), + ?line {term, "'Abc'"} = get_term(P), + ?line {term, "ab@c"} = get_term(P), + ?line {term, "'The rain in Spain stays mainly in the plains'"} = + get_term(P), + + ?line {term, "a"} = get_term(P), + ?line {term, "ab"} = get_term(P), + ?line {term, "abc"} = get_term(P), + ?line {term, "ab@c"} = get_term(P), + ?line {term, "abcdefghijklmnopq"} = get_term(P), + + ?line {term, "''"} = get_term(P), + ?line {term, "a"} = get_term(P), + ?line {term, "'A'"} = get_term(P), + ?line {term, "abc"} = get_term(P), + ?line {term, "'Abc'"} = get_term(P), + ?line {term, "ab@c"} = get_term(P), + ?line {term, "'The rain in Spain stays mainly in the plains'"} = + get_term(P), + + ?line {term, "a"} = get_term(P), + ?line {term, "ab"} = get_term(P), + ?line {term, "abc"} = get_term(P), + ?line {term, "ab@c"} = get_term(P), + ?line {term, "' abcdefghijklmnopq '"} = get_term(P), + + ?line runner:recv_eot(P), + ok. + + + +%% Tests formatting various tuples + +tuples(suite) -> []; +tuples(Config) when is_list(Config) -> + ?line P = runner:start(?tuples), + + ?line {term, "{}"} = get_term(P), + ?line {term, "{a}"} = get_term(P), + ?line {term, "{a, b}"} = get_term(P), + ?line {term, "{a, b, c}"} = get_term(P), + ?line {term, "{1}"} = get_term(P), + ?line {term, "{[]}"} = get_term(P), + ?line {term, "{[], []}"} = get_term(P), + ?line {term, "{[], a, b, c}"} = get_term(P), + ?line {term, "{[], a, [], b, c}"} = get_term(P), + ?line {term, "{[], a, '', b, c}"} = get_term(P), + + ?line runner:recv_eot(P), + ok. + + + +%% Tests formatting various lists + +lists(suite) -> []; +lists(Config) when is_list(Config) -> + ?line P = runner:start(?lists), + + ?line {term, "[]"} = get_term(P), + ?line {term, "[a]"} = get_term(P), + ?line {term, "[a, b]"} = get_term(P), + ?line {term, "[a, b, c]"} = get_term(P), + ?line {term, "[1]"} = get_term(P), + ?line {term, "[[]]"} = get_term(P), + ?line {term, "[[], []]"} = get_term(P), + ?line {term, "[[], a, b, c]"} = get_term(P), + ?line {term, "[[], a, [], b, c]"} = get_term(P), + ?line {term, "[[], a, '', b, c]"} = get_term(P), + ?line {term, "[[x, 2], [y, 3], [z, 4]]"}= get_term(P), + +%% ?line {term, "[{name, 'Madonna'}, {age, 21}, {data, [{addr, "E-street", 42}]}]"} = +%% get_term(P), + %% kanske regexp i st�llet? + ?line {term, "[{pi, 3.141500}, {'cos(70)', 0.342020}]"} = get_term(P), + ?line {term, "[[pi, 3.141500], ['cos(70)', 0.342020]]"} = get_term(P), + + ?line {term, "[-1]"} = get_term(P), + + ?line runner:recv_eot(P), + ok. + +strings(suite) -> []; +strings(Config) when is_list(Config) -> + ?line P = runner:start(?strings), + + ?line {term, "\"\\n\""} = get_term(P), + ?line {term, "\"\\r\\n\""} = get_term(P), + ?line {term, "\"a\""} = get_term(P), + ?line {term, "\"A\""} = get_term(P), + ?line {term, "\"0\""} = get_term(P), + ?line {term, "\"9\""} = get_term(P), + ?line {term, "\"The rain in Spain stays mainly in the plains\""} = get_term(P), + ?line {term, "\" abcdefghijklmnopq \""} = get_term(P), + + ?line runner:recv_eot(P), + ok. + diff --git a/lib/erl_interface/test/ei_print_SUITE_data/Makefile.first b/lib/erl_interface/test/ei_print_SUITE_data/Makefile.first new file mode 100644 index 0000000000..e36d4364dc --- /dev/null +++ b/lib/erl_interface/test/ei_print_SUITE_data/Makefile.first @@ -0,0 +1,21 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +ei_print_test_decl.c: ei_print_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run ei_print_test -s erlang halt diff --git a/lib/erl_interface/test/ei_print_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_print_SUITE_data/Makefile.src new file mode 100644 index 0000000000..6eec4b1990 --- /dev/null +++ b/lib/erl_interface/test/ei_print_SUITE_data/Makefile.src @@ -0,0 +1,42 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \ + $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + @erl_interface_threadlib@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data +EI_PRINT_OBJS = ei_print_test@obj@ ei_print_test_decl@obj@ + +all: ei_print_test@exe@ + +clean: + $(RM) $(EI_PRINT_OBJS) + $(RM) ei_print_test@exe@ + +ei_print_test@exe@: $(EI_PRINT_OBJS) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(EI_PRINT_OBJS) $(LIBFLAGS) + + diff --git a/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c b/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c new file mode 100644 index 0000000000..cc9b8048ca --- /dev/null +++ b/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c @@ -0,0 +1,175 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#include "ei_runner.h" + +/* + * Purpose: Tests the ei_print() function. + * Author: Jakob + */ + +static void +send_printed3(char* format, char* p1, char* p2, int fl) +{ + char* b = NULL; + char fn[100], * tmp = getenv("temp"); + FILE* f; + int n, index = 0, ver; + ei_x_buff x; + + ei_x_new(&x); + if (fl) { + ei_x_format(&x, format, *(float*)p1, *(float*)p2); + } else { + ei_x_format(&x, format, p1, p2); + } +#ifdef VXWORKS + tmp = "."; +#else + if (tmp == NULL) tmp = "/tmp"; +#endif + strcpy(fn, tmp); + strcat(fn, "/ei_print_test.txt"); + f = fopen(fn, "w+"); + ei_decode_version(x.buff, &index, &ver); + n = ei_print_term(f, x.buff, &index); + fseek(f, 0, SEEK_SET); + b = malloc(n+1); + fread(b, 1, n, f); + b[n] = '\0'; + fclose(f); + x.index = 0; + ei_x_format(&x, "~s", b); + send_bin_term(&x); + free(b); + ei_x_free(&x); +} + +static void +send_printed(char* format) +{ + send_printed3(format, NULL, NULL, 0); +} + +static void +send_printed2(char* format, char* p) +{ + send_printed3(format, p, NULL, 0); +} + +static void send_printed3f(char* format, float f1, float f2) +{ + send_printed3(format, (char*)&f1, (char*)&f2, 1); +} + +TESTCASE(atoms) +{ + send_printed("''"); + send_printed("'a'"); + send_printed("'A'"); + send_printed("'abc'"); + send_printed("'Abc'"); + send_printed("'ab@c'"); + send_printed("'The rain in Spain stays mainly in the plains'"); + + send_printed("a"); + send_printed("ab"); + send_printed("abc"); + send_printed("ab@c"); + send_printed(" abcdefghijklmnopq "); + + send_printed2("~a", ""); + send_printed2("~a", "a"); + send_printed2("~a", "A"); + send_printed2("~a", "abc"); + send_printed2("~a", "Abc"); + send_printed2("~a", "ab@c"); + send_printed2("~a", "The rain in Spain stays mainly in the plains"); + + send_printed2("~a", "a"); + send_printed2("~a", "ab"); + send_printed2("~a", "abc"); + send_printed2("~a","ab@c"); + send_printed2("~a", " abcdefghijklmnopq "); + + + report(1); +} + +TESTCASE(tuples) +{ + send_printed("{}"); + send_printed("{a}"); + send_printed("{a, b}"); + send_printed("{a, b, c}"); + send_printed("{1}"); + send_printed("{[]}"); + send_printed("{[], []}"); + send_printed("{[], a, b, c}"); + send_printed("{[], a, [], b, c}"); + send_printed("{[], a, '', b, c}"); + + report(1); +} + + + +TESTCASE(lists) +{ + ei_x_buff x; + + send_printed("[]"); + send_printed("[a]"); + send_printed("[a, b]"); + send_printed("[a, b, c]"); + send_printed("[1]"); + send_printed("[[]]"); + send_printed("[[], []]"); + send_printed("[[], a, b, c]"); + send_printed("[[], a, [], b, c]"); + send_printed("[[], a, '', b, c]"); + send_printed("[[x, 2], [y, 3], [z, 4]]"); + + /* more tests needed */ + send_printed3f("[{pi, ~f}, {'cos(70)', ~f}]", + (float)3.1415, (float)0.34202); + send_printed3f("[[pi, ~f], ['cos(70)', ~f]]", + (float)3.1415, (float)0.34202); + + send_printed2("[~i]", (char*)-1); + report(1); +} + +TESTCASE(strings) +{ + ei_x_buff x; + + send_printed("\"\n\""); + send_printed("\"\r\n\""); + send_printed("\"a\""); + send_printed("\"A\""); + send_printed("\"0\""); + send_printed("\"9\""); + send_printed("\"The rain in Spain stays mainly in the plains\""); + send_printed("\" abcdefghijklmnopq \""); + + report(1); +} + + diff --git a/lib/erl_interface/test/ei_tmo_SUITE.erl b/lib/erl_interface/test/ei_tmo_SUITE.erl new file mode 100644 index 0000000000..0c211aa148 --- /dev/null +++ b/lib/erl_interface/test/ei_tmo_SUITE.erl @@ -0,0 +1,666 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(ei_tmo_SUITE). + +-include("test_server.hrl"). +-include_lib("kernel/include/inet.hrl"). +-include("ei_tmo_SUITE_data/ei_tmo_test_cases.hrl"). + +-define(dummy_host,test01). + +-export([all/1, init_per_testcase/2, fin_per_testcase/2, + framework_check/1, ei_accept_tmo/1, ei_connect_tmo/1, ei_send_tmo/1, + ei_recv_tmo/1]). + +all(suite) -> [framework_check,ei_accept_tmo,ei_connect_tmo, + ei_send_tmo,ei_recv_tmo]. + +init_per_testcase(_Case, Config) -> + Dog = ?t:timetrap(?t:minutes(1)), + % test if platform is vxworks_simso + ?line {_,Host} = split(node()), + Bool = case atom_to_list(Host) of + [$v,$x,$s,$i,$m | _] -> true; + _ -> false + end, + [{vxsim,Bool},{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +framework_check(doc) -> + ["Check the framework."]; +framework_check(suite) -> + []; +framework_check(Config) when is_list(Config) -> + %%dbg:tracer(), + %%dbg:p(self()), + ?line P = runner:start(?framework_check), + ?line runner:send_term(P,{hello,world}), + ?line {term, {hello,world}} = runner:get_term(P), + ?line runner:recv_eot(P), + ok. + + +ei_recv_tmo(doc) -> + ["Check recv with timeouts."]; +ei_recv_tmo(suite) -> + []; +ei_recv_tmo(Config) when is_list(Config) -> + ?line do_one_recv(c_node_recv_tmo_1), + ?line do_one_recv_failure(c_node_recv_tmo_2), + ok. + + +do_one_recv(CNode) -> + ?line {_,Host} = split(node()), + ?line P1 = runner:start(?recv_tmo), + ?line runner:send_term(P1,{CNode, + erlang:get_cookie(), + node()}), + ?line {term, X} = runner:get_term(P1, 10000), + ?line true = is_integer(X), + ?line CNode1 = join(CNode,Host), + ?line Term1 = {hej,[hopp,{i,[lingon,"skogen"]}]}, + ?line {test,CNode1} ! Term1, + ?line {term, Term1} = runner:get_term(P1, 10000), + ?line runner:recv_eot(P1). + +do_one_recv_failure(CNode) -> + ?line P1 = runner:start(?recv_tmo), + ?line runner:send_term(P1,{CNode, + erlang:get_cookie(), + node()}), + ?line {term, X} = runner:get_term(P1, 10000), + ?line true = is_integer(X), + ?line {term, {Ret,ETimedout,ETimedout}} = runner:get_term(P1, 10000), + ?line true = (Ret < 0), + ?line runner:recv_eot(P1). + + +ei_send_tmo(doc) -> + ["Check send with timeouts."]; +ei_send_tmo(suite) -> + []; +ei_send_tmo(Config) when is_list(Config) -> + %dbg:tracer(), + %dbg:p(self()), + VxSim = ?config(vxsim, Config), + ?line register(ei_send_tmo_1,self()), + ?line do_one_send(self(),c_node_send_tmo_1), + ?line do_one_send(ei_send_tmo_1,c_node_send_tmo_2), + ?line do_one_send_failure(self(),cccc1,c_nod_send_tmo_3,VxSim), + ?line do_one_send_failure(ei_send_tmo_1,cccc2,c_nod_send_tmo_4,VxSim), + ok. + + +do_one_send(From,CNode) -> + ?line {_,Host} = split(node()), + ?line P1 = runner:start(?send_tmo), + ?line runner:send_term(P1,{CNode, + erlang:get_cookie(), + node()}), + ?line {term, X} = runner:get_term(P1, 10000), + ?line true = is_integer(X), + ?line CNode1 = join(CNode,Host), + ?line Term1 = {hej,[hopp,{i,[lingon,"skogen"]}]}, + ?line {test,CNode1} ! {From,1,Term1}, + ?line ok = receive + Term1 -> + ok + after 2000 -> + error + end, + ?line {term, 0} = runner:get_term(P1, 10000), + ?line runner:recv_eot(P1). + +do_one_send_failure(From,FakeName,CName,VxSim) -> + ?line {_,Host} = split(node()), + ?line OurName = join(FakeName,Host), + ?line Node = join(CName,Host), + ?line LSocket = case gen_tcp:listen(0, [{active, false}, {packet,2}]) of + {ok, Socket} -> + ?line Socket; + Else -> + ?line exit(Else) + end, + ?line EpmdSocket = register(OurName, LSocket, 1, 5), + ?line P3 = runner:start(?send_tmo), + ?line Cookie = kaksmula_som_ingen_bryr_sig_om, + ?line runner:send_term(P3,{CName, + Cookie, + OurName}), + ?line SocketB = case gen_tcp:accept(LSocket) of + {ok, Socket1} -> + ?line Socket1; + Else2 -> + ?line exit(Else2) + end, + ?line {hidden,Node,5} = recv_name(SocketB), % See 1) + ?line send_status(SocketB, ok), + ?line MyChallengeB = gen_challenge(), + ?line send_challenge(SocketB, OurName, MyChallengeB, 5), + ?line HisChallengeB = recv_challenge_reply( + SocketB, + MyChallengeB, + Cookie), + ?line DigestB = gen_digest(HisChallengeB,Cookie), + ?line send_challenge_ack(SocketB, DigestB), + ?line inet:setopts(SocketB, [{active, false}, + {packet, 4}]), + ?line {term, X} = runner:get_term(P3, 10000), + ?line true = is_integer(X), + ?line Message = [112,term_to_binary({6,self(),'',test}), + term_to_binary({From,10000, + {app,["lapp",{sa,["att",du,{slapp, + sitta}]}]}})], + ?line gen_tcp:send(SocketB,Message), + + %% At this point the test program starts sending messages (max 10000). Since + %% we're not receiving, eventually the send buffer fills up. Then no more + %% sending is possible and select() times out. The number of messages sent + %% before this happens is returned in Iters. The timeout value for get_term/2 + %% must be large enough so there's time for the select() to time out and + %% the test program to return the error tuple (below). + Res0 = + if VxSim == false -> + ?line {term,{Res,ETO,Iters,ETO}} = runner:get_term(P3, 20000), + Res; + true -> % relax the test for vxsim + ?line case runner:get_term(P3, 20000) of + {term,{Res,ETO,Iters,ETO}} -> + Res; + {term,{Res,_,Iters,ETO}} -> % EIO? + Res + end + end, + ?line runner:recv_eot(P3), + ?line true = ((Res0 < 0) and (Iters > 0)), + ?line gen_tcp:close(SocketB), + ?line gen_tcp:close(EpmdSocket), + ok. + + +ei_connect_tmo(doc) -> + ["Check accept with timeouts."]; +ei_connect_tmo(suite) -> + []; +ei_connect_tmo(Config) when is_list(Config) -> + %dbg:tracer(), + %dbg:p(self()), + VxSim = ?config(vxsim, Config), + DummyNode = make_and_check_dummy(), + ?line P = runner:start(?connect_tmo), + ?line runner:send_term(P,{c_nod_connect_tmo_1, + kaksmula_som_ingen_bryr_sig_om, + DummyNode}), + ETimedout = + if VxSim == false -> + ?line {term,{-3,ETO,ETO}} = runner:get_term(P, 10000), + ?line ETO; + true -> % relax the test for vxsim + ?line case runner:get_term(P, 10000) of + {term,{-3,ETO,ETO}} -> + ?line ETO; + {term,{-1,_,ETO}} -> % EHOSTUNREACH = ok + ?line ETO + end + end, + ?line runner:recv_eot(P), + ?line P2 = runner:start(?connect_tmo), + ?line runner:send_term(P2,{c_nod_connect_tmo_2, + erlang:get_cookie(), + node()}), + ?line {term, X} = runner:get_term(P2, 10000), + ?line runner:recv_eot(P2), + ?line true = is_integer(X), + %% Aborted handshake test... + ?line {_,Host} = split(node()), + ?line OurName = join(cccc,Host), + ?line Node = join(c_nod_connect_tmo_3,Host), + ?line LSocket = case gen_tcp:listen(0, [{active, false}, {packet,2}]) of + {ok, Socket} -> + ?line Socket; + Else -> + ?line exit(Else) + end, + ?line EpmdSocket = register(OurName, LSocket, 1, 5), + ?line P3 = runner:start(?connect_tmo), + ?line Cookie = kaksmula_som_ingen_bryr_sig_om, + ?line runner:send_term(P3,{c_nod_connect_tmo_3, + Cookie, + OurName}), + ?line SocketB = case gen_tcp:accept(LSocket) of + {ok, Socket1} -> + ?line Socket1; + Else2 -> + ?line exit(Else2) + end, + ?line {hidden,Node,5} = recv_name(SocketB), % See 1) + ?line send_status(SocketB, ok), + ?line MyChallengeB = gen_challenge(), + ?line send_challenge(SocketB, OurName, MyChallengeB, 5), + ?line HisChallengeB = recv_challenge_reply( + SocketB, + MyChallengeB, + Cookie), + ?line {term,{-1,ETimedout,ETimedout}} = runner:get_term(P3, 10000), + ?line runner:recv_eot(P3), + ?line gen_tcp:close(SocketB), + ?line gen_tcp:close(EpmdSocket), + ok. + + +ei_accept_tmo(doc) -> + ["Check accept with timeouts."]; +ei_accept_tmo(suite) -> + []; +ei_accept_tmo(Config) when is_list(Config) -> + %%dbg:tracer(), + %%dbg:p(self()), + ?line P = runner:start(?accept_tmo), + ?line runner:send_term(P,{c_nod_som_ingen_kontaktar_1, + kaksmula_som_ingen_bryr_sig_om}), + ?line {term,{-1,ETimedout,ETimedout}} = runner:get_term(P, 10000), + ?line runner:recv_eot(P), + ?line P2 = runner:start(?accept_tmo), + ?line runner:send_term(P2,{c_nod_som_vi_kontaktar_1, + erlang:get_cookie()}), + ?line receive after 1000 -> ok end, + ?line CNode1 = make_node(c_nod_som_vi_kontaktar_1), + ?line {ignored,CNode1} ! tjenare, + ?line {term, X} = runner:get_term(P2, 10000), + ?line runner:recv_eot(P2), + ?line true = is_integer(X), + ?line P3 = runner:start(?accept_tmo), + ?line runner:send_term(P3,{c_nod_som_vi_kontaktar_2, + erlang:get_cookie()}), + ?line receive after 1000 -> ok end, + ?line CNode2 = make_node(c_nod_som_vi_kontaktar_2), + ?line {NA,NB} = split(CNode2), + ?line {_,Host} = split(node()), + ?line OurName = join(ccc,Host), + ?line {port,PortNo,_} = erl_epmd:port_please(NA,NB), + ?line {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo, + [{active,false}, + {packet,2}]), + ?line send_name(SocketA,OurName,5), + ?line ok = recv_status(SocketA), + ?line {hidden,Node,5,HisChallengeA} = recv_challenge(SocketA), % See 1) + ?line OurChallengeA = gen_challenge(), + ?line OurDigestA = gen_digest(HisChallengeA, erlang:get_cookie()), + %% Dont do the last two steps of the connection setup... + %% send_challenge_reply(SocketA, OurChallengeA, OurDigestA), + %% ok = recv_challenge_ack(SocketA, OurChallengeA, erlang:get_cookie()), + ?line {term, {-1,ETimedout,ETimedout}} = runner:get_term(P3, 10000), + ?line runner:recv_eot(P3), + ?line gen_tcp:close(SocketA), + ok. + +make_node(X) -> + list_to_atom(atom_to_list(X) ++ "@" ++ + hd(tl(string:tokens(atom_to_list(node()),"@")))). + + +make_and_check_dummy() -> + % First check that the host has an ip and is *not* reachable + ?line case gen_tcp:connect(?dummy_host,23,[{active,false}],5000) of + {error,timeout} -> ok; + {error,ehostunreach} -> ok + end, + + list_to_atom("dummy@"++atom_to_list(?dummy_host)). + +%% +%% Stolen from the erl_distribution_wb_test in kernel +%% To be able to do partial handshakes... +%% + +-define(to_port(Socket, Data), + case inet_tcp:send(Socket, Data) of + {error, closed} -> + self() ! {tcp_closed, Socket}, + {error, closed}; + R -> + R + end). + +-define(DFLAG_PUBLISHED,1). +-define(DFLAG_ATOM_CACHE,2). +-define(DFLAG_EXTENDED_REFERENCES,4). +-define(DFLAG_EXTENDED_PIDS_PORTS,16#100). +-define(DFLAG_DIST_MONITOR,8). + +%% From R9 and forward extended references is compulsory +-define(COMPULSORY_DFLAGS, (?DFLAG_EXTENDED_REFERENCES bor ?DFLAG_EXTENDED_PIDS_PORTS)). + +-define(shutdown(X), exit(X)). +-define(int16(X), [((X) bsr 8) band 16#ff, (X) band 16#ff]). + +-define(int32(X), + [((X) bsr 24) band 16#ff, ((X) bsr 16) band 16#ff, + ((X) bsr 8) band 16#ff, (X) band 16#ff]). + +-define(i16(X1,X0), + (?u16(X1,X0) - + (if (X1) > 127 -> 16#10000; true -> 0 end))). + +-define(u16(X1,X0), + (((X1) bsl 8) bor (X0))). + +-define(u32(X3,X2,X1,X0), + (((X3) bsl 24) bor ((X2) bsl 16) bor ((X1) bsl 8) bor (X0))). + +%% +%% Handshake utilities +%% + +%% +%% MD5 hashing +%% + +%% This is no proper random number, but that is not really important in +%% this test +gen_challenge() -> + {_,_,N} = erlang:now(), + N. + +%% Generate a message digest from Challenge number and Cookie +gen_digest(Challenge, Cookie) when is_integer(Challenge), is_atom(Cookie) -> + C0 = erlang:md5_init(), + C1 = erlang:md5_update(C0, atom_to_list(Cookie)), + C2 = erlang:md5_update(C1, integer_to_list(Challenge)), + binary_to_list(erlang:md5_final(C2)). + + +%% +%% The differrent stages of the MD5 handshake +%% + +send_status(Socket, Stat) -> + case gen_tcp:send(Socket, [$s | atom_to_list(Stat)]) of + {error, _} -> + ?shutdown(could_not_send_status); + _ -> + true + end. + + +recv_status(Socket) -> + case gen_tcp:recv(Socket, 0) of + {ok, [$s|StrStat]} -> + list_to_atom(StrStat); + Bad -> + exit(Bad) + end. + +send_challenge(Socket, Node, Challenge, Version) -> + send_challenge(Socket, Node, Challenge, Version, ?COMPULSORY_DFLAGS). +send_challenge(Socket, Node, Challenge, Version, Flags) -> + {ok, {{Ip1,Ip2,Ip3,Ip4}, _}} = inet:sockname(Socket), + ?to_port(Socket, [$n,?int16(Version),?int32(Flags), + ?int32(Challenge), atom_to_list(Node)]). + +recv_challenge(Socket) -> + case gen_tcp:recv(Socket, 0) of + {ok,[$n,V1,V0,Fl1,Fl2,Fl3,Fl4,CA3,CA2,CA1,CA0 | Ns]} -> + Flags = ?u32(Fl1,Fl2,Fl3,Fl4), + Type = case Flags band ?DFLAG_PUBLISHED of + 0 -> + hidden; + _ -> + normal + end, + Node =list_to_atom(Ns), + Version = ?u16(V1,V0), + Challenge = ?u32(CA3,CA2,CA1,CA0), + {Type,Node,Version,Challenge}; + _ -> + ?shutdown(no_node) + end. + +send_challenge_reply(Socket, Challenge, Digest) -> + ?to_port(Socket, [$r,?int32(Challenge),Digest]). + +recv_challenge_reply(Socket, ChallengeA, Cookie) -> + case gen_tcp:recv(Socket, 0) of + {ok,[$r,CB3,CB2,CB1,CB0 | SumB]} when length(SumB) == 16 -> + SumA = gen_digest(ChallengeA, Cookie), + ChallengeB = ?u32(CB3,CB2,CB1,CB0), + if SumB == SumA -> + ChallengeB; + true -> + ?shutdown(bad_challenge_reply) + end; + _ -> + ?shutdown(no_node) + end. + +send_challenge_ack(Socket, Digest) -> + ?to_port(Socket, [$a,Digest]). + +recv_challenge_ack(Socket, ChallengeB, CookieA) -> + case gen_tcp:recv(Socket, 0) of + {ok,[$a | SumB]} when length(SumB) == 16 -> + SumA = gen_digest(ChallengeB, CookieA), + if SumB == SumA -> + ok; + true -> + ?shutdown(bad_challenge_ack) + end; + _ -> + ?shutdown(bad_challenge_ack) + end. + +send_name(Socket, MyNode0, Version) -> + send_name(Socket, MyNode0, Version, ?COMPULSORY_DFLAGS). +send_name(Socket, MyNode0, Version, Flags) -> + MyNode = atom_to_list(MyNode0), + ?to_port(Socket, [$n,?int16(Version),?int32(Flags)] ++ + MyNode). + +%% +%% recv_name is common for both old and new handshake. +%% +recv_name(Socket) -> + case gen_tcp:recv(Socket, 0) of + {ok,Data} -> + get_name(Data); + Res -> + ?shutdown({no_node,Res}) + end. + +get_name([$m,VersionA,VersionB,_Ip1,_Ip2,_Ip3,_Ip4|OtherNode]) -> + {normal, list_to_atom(OtherNode), ?u16(VersionA,VersionB)}; +get_name([$h,VersionA,VersionB,_Ip1,_Ip2,_Ip3,_Ip4|OtherNode]) -> + {hidden, list_to_atom(OtherNode), ?u16(VersionA,VersionB)}; +get_name([$n,VersionA, VersionB, Flag1, Flag2, Flag3, Flag4 | OtherNode]) -> + Type = case ?u32(Flag1, Flag2, Flag3, Flag4) band ?DFLAG_PUBLISHED of + 0 -> + hidden; + _ -> + normal + end, + {Type, list_to_atom(OtherNode), + ?u16(VersionA,VersionB)}; +get_name(Data) -> + ?shutdown(Data). + +%% +%% tell_name is for old handshake +%% +tell_name(Socket, MyNode0, Version) -> + MyNode = atom_to_list(MyNode0), + {ok, {{Ip1,Ip2,Ip3,Ip4}, _}} = inet:sockname(Socket), + ?to_port(Socket, [$h,?int16(Version),Ip1,Ip2,Ip3,Ip4] ++ + MyNode). + +%% +%% The communication with EPMD follows +%% +do_register_node(NodeName, TcpPort, VLow, VHigh) -> + case gen_tcp:connect({127,0,0,1}, get_epmd_port(), []) of + {ok, Socket} -> + {N0,_} = split(NodeName), + Name = atom_to_list(N0), + Extra = "", + Elen = length(Extra), + Len = 1+2+1+1+2+2+2+length(Name)+2+Elen, + gen_tcp:send(Socket, [?int16(Len), $x, + ?int16(TcpPort), + $M, + 0, + ?int16(VHigh), + ?int16(VLow), + ?int16(length(Name)), + Name, + ?int16(Elen), + Extra]), + case wait_for_reg_reply(Socket, []) of + {error, epmd_close} -> + exit(epmd_broken); + Other -> + Other + end; + Error -> + Error + end. + +wait_for_reg_reply(Socket, SoFar) -> + receive + {tcp, Socket, Data0} -> + case SoFar ++ Data0 of + [$y, Result, A, B] -> + case Result of + 0 -> + {alive, Socket, ?u16(A, B)}; + _ -> + {error, duplicate_name} + end; + Data when length(Data) < 4 -> + wait_for_reg_reply(Socket, Data); + Garbage -> + {error, {garbage_from_epmd, Garbage}} + end; + {tcp_closed, Socket} -> + {error, epmd_close} + after 10000 -> + gen_tcp:close(Socket), + {error, no_reg_reply_from_epmd} + end. + + +register(NodeName, ListenSocket, VLow, VHigh) -> + {ok,{_,TcpPort}} = inet:sockname(ListenSocket), + case do_register_node(NodeName, TcpPort, VLow, VHigh) of + {alive, Socket, Creation} -> + Socket; + Other -> + exit(Other) + end. + + +%% +%% Utilities +%% + +%% Split a nodename +split([$@|T],A) -> + {lists:reverse(A),T}; +split([H|T],A) -> + split(T,[H|A]). + +split(Atom) -> + {A,B} = split(atom_to_list(Atom),[]), + {list_to_atom(A),list_to_atom(B)}. + +%% Build a simple distribution message +build_message(Cookie) -> + [$?,term_to_binary({6,self(),Cookie,rex}),term_to_binary(plupp)]. + +%% Build a distribution message that will make rex answer +build_rex_message(Cookie,OurName) -> + [$?,term_to_binary({6,self(),Cookie,rex}), + term_to_binary({'$gen_cast', + {cast, + rpc, + cast, + [OurName, hello, world, []], + self()} })]. + +%% Receive a distribution message +recv_message(Socket) -> + case gen_tcp:recv(Socket, 0) of + {ok,Data} -> + B0 = list_to_binary(Data), + {_,B1} = erlang:split_binary(B0,1), + Header = erlang:binary_to_term(B1), + Siz = size(term_to_binary(Header)), + {_,B2} = erlang:split_binary(B1,Siz), + Message = case (catch erlang:binary_to_term(B2)) of + {'EXIT', _} -> + could_not_digest_message; + Other -> + Other + end, + {Header, Message}; + Res -> + exit({no_message,Res}) + end. + +%% Build a nodename +join(Name,Host) -> + list_to_atom(atom_to_list(Name) ++ "@" ++ atom_to_list(Host)). + +%% start/stop slave. +start_node(Name, Param) -> + ?t:start_node(Name, slave, [{args, Param}]). + +stop_node(Node) -> + ?t:stop_node(Node). + + +get_nodenames(N, T) -> + get_nodenames(N, T, []). + +get_nodenames(0, _, Acc) -> + Acc; +get_nodenames(N, T, Acc) -> + {A, B, C} = now(), + get_nodenames(N-1, T, [list_to_atom(atom_to_list(?MODULE) + ++ "-" + ++ atom_to_list(T) + ++ "-" + ++ integer_to_list(A) + ++ "-" + ++ integer_to_list(B) + ++ "-" + ++ integer_to_list(C)) | Acc]). + +get_epmd_port() -> + case init:get_argument(epmd_port) of + {ok, [[PortStr|_]|_]} when is_list(PortStr) -> + list_to_integer(PortStr); + error -> + 4369 % Default epmd port + end. diff --git a/lib/erl_interface/test/ei_tmo_SUITE_data/Makefile.first b/lib/erl_interface/test/ei_tmo_SUITE_data/Makefile.first new file mode 100644 index 0000000000..6eb9f2ce71 --- /dev/null +++ b/lib/erl_interface/test/ei_tmo_SUITE_data/Makefile.first @@ -0,0 +1,21 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2003-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +ei_tmo_test_decl.c: ei_tmo_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run ei_tmo_test -s erlang halt diff --git a/lib/erl_interface/test/ei_tmo_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_tmo_SUITE_data/Makefile.src new file mode 100644 index 0000000000..a49eeccc02 --- /dev/null +++ b/lib/erl_interface/test/ei_tmo_SUITE_data/Makefile.src @@ -0,0 +1,41 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2003-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \ + $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + @erl_interface_threadlib@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data +EI_TMO_OBJS = ei_tmo_test@obj@ ei_tmo_test_decl@obj@ + +all: ei_tmo_test@exe@ + +clean: + $(RM) $(EI_TMO_OBJS) + $(RM) ei_tmo_test@exe@ + +ei_tmo_test@exe@: $(EI_TMO_OBJS) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(EI_TMO_OBJS) $(LIBFLAGS) + diff --git a/lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c b/lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c new file mode 100644 index 0000000000..2cc9af975d --- /dev/null +++ b/lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c @@ -0,0 +1,767 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2003-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#include <stdio.h> +#include <string.h> +#ifdef VXWORKS +#include "reclaim.h" +#endif + +#ifdef __WIN32__ +#include <winsock2.h> +#include <windows.h> +#else +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#endif + +#include "ei_runner.h" + +#ifndef __WIN32__ +#define closesocket(X) close(X) +#endif + +#define DEBUG 1 + +#ifdef DEBUG +#include <stdarg.h> + +FILE *debugfile = NULL; +#define OPEN_DEBUGFILE(Number) debugf_open(Number) +#define CLOSE_DEBUGFILE() debugf_close() +#define DEBUGF(X) debugf X + +static void debugf(char *format, ...) +{ + va_list ap; + va_start(ap,format); + if (debugfile) { + vfprintf(debugfile,format,ap); + fflush(debugfile); + } else { + fprintf(stderr,"Attempt to write to debugfile when not open...\n"); + } + va_end(ap); +} + +static void debugf_open(int number) +{ + char filename[1024]; + sprintf(filename,"ei_tmo_test%d.debug",number); +#if !defined(VXWORKS) && !defined(__WIN32__) && !defined(_OSE_) + close(2); +#endif + debugfile = fopen(filename,"a"); + fprintf(debugfile,"===================================================\n"); +} + +static void debugf_close(void) +{ + if (debugfile) + fclose(debugfile); +} + +#else +#define OPEN_DEBUGFILE(X) /* noop */ +#define CLOSE_DEBUGFILE() /* noop */ +#define DEBUGF(X) /* noop */ +#endif + +TESTCASE(framework_check) +{ + char *ptr = NULL; + int len; + +#ifdef DEBUG + int version; + int i; +#endif + + OPEN_DEBUGFILE(1); + + DEBUGF(("B�rjar... \n")); + ptr = read_packet(&len); + if (*ptr != 't') { + DEBUGF(("Gick fel \n")); + report(1); + } else { + ei_x_buff x; + ei_x_new(&x); + ei_x_append_buf(&x, ptr+1,len-1); + DEBUGF(("Gick bra? %d\n",x.index)); +#ifdef DEBUG + for(i=0;i < x.index; ++i) + DEBUGF(("%d ",(int) ((unsigned char *) x.buff)[i])); + DEBUGF(("\n")); + len = 0; + ei_decode_version(x.buff,&len,&version); + ei_print_term(debugfile,x.buff,&len); + fflush(debugfile); +#endif + send_bin_term(&x); + ei_x_free(&x); + } + if (ptr != NULL) + free(ptr); + CLOSE_DEBUGFILE(); + report(1); +} + +int decode_request(char **nodename_p, char **cookie_p, char **peername_p) +{ + char *nodename = NULL; + char *cookie = NULL; + char *peername = NULL; + char *ptr = NULL; + ei_x_buff x; + int len; + int version; + int type; + int size; + int expected_size = (peername_p == NULL) ? 2 : 3; + int ret = -1; + + ptr = read_packet(&len); + ei_x_new(&x); + if (*ptr != 't') { + goto cleanup; + } + ei_x_append_buf(&x, ptr+1,len-1); + len = 0; + ei_decode_version(x.buff,&len,&version); +#ifdef DEBUG + { + int tlen = len; + ei_print_term(debugfile,x.buff,&tlen); + DEBUGF(("\n")); + } +#endif + if (ei_get_type(x.buff,&len,&type,&size) != 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + if (type != ERL_SMALL_TUPLE_EXT || size != expected_size) { + DEBUGF(("Failure at line %d, type=%d, size = %d\n",__LINE__, + type,size)); + goto cleanup; + } + if (ei_decode_tuple_header(x.buff,&len,&size) != 0 || size != expected_size) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + if (ei_get_type(x.buff,&len,&type,&size) != 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + if (type != ERL_ATOM_EXT) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + nodename = malloc(size+1); + ei_decode_atom(x.buff,&len,nodename); + nodename[size] = '\0'; /* needed????? */ + if (ei_get_type(x.buff,&len,&type,&size) != 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + if (type != ERL_ATOM_EXT) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + cookie = malloc(size + 1); + ei_decode_atom(x.buff,&len,cookie); + cookie[size] = '\0'; /* needed????? */ + if (expected_size > 2) { + if (ei_get_type(x.buff,&len,&type,&size) != 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + if (type != ERL_ATOM_EXT) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + peername = malloc(size + 1); + ei_decode_atom(x.buff,&len,peername); + peername[size] = '\0'; /* needed????? */ + DEBUGF(("nodename = %s, cookie = %s, peername = %s\n", + nodename, cookie, peername)); + *peername_p = peername; + peername = NULL; + } else { + DEBUGF(("nodename = %s, cookie = %s\n", + nodename, cookie)); + } + *nodename_p = nodename; + nodename = NULL; + *cookie_p = cookie; + cookie = NULL; + ret = 0; + cleanup: + ei_x_free(&x); + if (ptr != NULL) { + free(ptr); + } + if (nodename != NULL) { + free(nodename); + } + if (cookie != NULL) { + free(cookie); + } + if (peername != NULL) { + free(peername); + } + return ret; +} + +int get_message(int com_sock, ei_x_buff *buff, + char *atom_buff, erlang_pid *pid, int *iterations) +{ + ei_x_buff buffer; + int ret_val,index; + erlang_msg msg; + int res = -1; + int totlen; + int type; + int size; + int version; + long tmp; + + ei_x_new(&buffer); + + for (;;) { + /* Reset buffer index before reading */ + buffer.index = 0; + /* Receive message */ + if ((ret_val = ei_xreceive_msg(com_sock, &msg, &buffer)) == + ERL_TICK) { + /* Ticks are automatically answered, just continue */ + continue; + } else if (ret_val != ERL_MSG) { + DEBUGF(("Peer has closed, ret_val = %d (%d).\n", + ret_val,erl_errno)); + goto cleanup; + } + switch (msg.msgtype) { + case ERL_SEND: + case ERL_REG_SEND: + index = 0; + ei_decode_version(buffer.buff,&index,&version); + DEBUGF(("Peer sent the following message to me: ")); +#ifdef DEBUG + { + int ndx = index; + /*in debug log on Unix*/ + ei_print_term(debugfile, buffer.buff, &ndx); + } +#endif + DEBUGF(("\n")); + if (ei_get_type(buffer.buff,&index,&type,&size) != 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + if (type != ERL_SMALL_TUPLE_EXT || size != 3) { + DEBUGF(("Failure at line %d, type=%d, size = %d\n",__LINE__, + type,size)); + goto cleanup; + } + if (ei_decode_tuple_header(buffer.buff,&index,&size) != 0 || + size != 3) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + if (ei_get_type(buffer.buff,&index,&type,&size) != 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + if (type == ERL_ATOM_EXT) { + ei_decode_atom(buffer.buff,&index,atom_buff); + atom_buff[size] ='\0'; + res = 2; + } else if (type == ERL_PID_EXT) { + ei_decode_pid(buffer.buff,&index,pid); + res = 1; + } else { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + if (ei_get_type(buffer.buff,&index,&type,&size) != 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + switch (type) { + case ERL_SMALL_INTEGER_EXT: + case ERL_INTEGER_EXT: + ei_decode_long(buffer.buff,&index,&tmp); + break; + default: + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + + *iterations = (int)tmp; + + totlen = buffer.index - index; + ei_x_append_buf(buff,buffer.buff+index,totlen); + goto cleanup; + default: + DEBUGF(("Unexpected message type from peer. Goodbye.\n")); + goto cleanup; + } + } + + cleanup: + ei_x_free(&buffer); + return res; +} +TESTCASE(recv_tmo) +{ + char *nodename = NULL; + char *cookie = NULL; + char *peername = NULL; + int com_sock = -1; + ei_cnode nodeinfo; + + + OPEN_DEBUGFILE(5); + + if (decode_request(&nodename,&cookie,&peername) != 0) { + goto cleanup; + } + if (ei_connect_init(&nodeinfo, nodename, cookie, 0) < 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + + if ((com_sock = ei_connect_tmo(&nodeinfo, peername, 5000)) < 0) { + ei_x_buff answer; + DEBUGF(("Got error while connecting.{%d,%d}\n",com_sock,erl_errno)); + ei_x_new(&answer); + ei_x_format(&answer,"{~i,~i,~i}",com_sock,erl_errno,ETIMEDOUT); +#ifdef DEBUG + { + int tlen = 0; + int v; + ei_decode_version(answer.buff,&tlen,&v); + ei_print_term(debugfile,answer.buff,&tlen); + DEBUGF(("\n")); + } +#endif + send_bin_term(&answer); + DEBUGF(("Binary term sent.\n")); + ei_x_free(&answer); + } else { + ei_x_buff answer; + int ret_val; + ei_x_buff buffer; + erlang_msg msg; + int index,version; + + DEBUGF(("Success when connecting.{%d,%d}\n",com_sock,erl_errno)); + ei_x_new(&answer); + ei_x_format(&answer,"~i",com_sock); + send_bin_term(&answer); + ei_x_free(&answer); + ei_x_new(&buffer); + + for (;;) { + /* Reset buffer index before reading */ + buffer.index = 0; + /* Receive message */ + if ((ret_val = ei_xreceive_msg_tmo(com_sock, &msg, &buffer,5000)) + == ERL_TICK) { + /* Ticks are automatically answered, just continue */ + continue; + } else if (ret_val != ERL_MSG) { + ei_x_new(&answer); + ei_x_format(&answer,"{~i,~i,~i}",ret_val,erl_errno,ETIMEDOUT); + send_bin_term(&answer); + ei_x_free(&answer); + ei_x_free(&buffer); + DEBUGF(("Got error receiving, sending {%d,%d} and exiting\n", + ret_val,erl_errno)); + goto cleanup; + } + switch (msg.msgtype) { + case ERL_SEND: + case ERL_REG_SEND: + index = 0; + ei_decode_version(buffer.buff,&index,&version); + DEBUGF(("Peer sent the following message to me: ")); +#ifdef DEBUG + { + int ndx = index; + /*in debug log on Unix*/ + ei_print_term(debugfile, buffer.buff, &ndx); + } +#endif + DEBUGF(("\n")); + send_bin_term(&buffer); + ei_x_free(&buffer); + goto cleanup; + default: + DEBUGF(("Unexpected message type from peer. Goodbye.\n")); + goto cleanup; + + } + } + } +cleanup: + if (com_sock >= 0) { + closesocket(com_sock); + } + + if (nodename != NULL) { + free(nodename); + } + if (cookie != NULL) { + free(cookie); + } + if (peername != NULL) { + free(peername); + } + CLOSE_DEBUGFILE(); + report(1); +} + +TESTCASE(send_tmo) +{ + char *nodename = NULL; + char *cookie = NULL; + char *peername = NULL; + int com_sock = -1; + ei_cnode nodeinfo; + + + OPEN_DEBUGFILE(4); + + if (decode_request(&nodename,&cookie,&peername) != 0) { + goto cleanup; + } + if (ei_connect_init(&nodeinfo, nodename, cookie, 0) < 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + + if ((com_sock = ei_connect_tmo(&nodeinfo, peername, 5000)) < 0) { + ei_x_buff answer; + DEBUGF(("Got error while connecting.{%d,%d}\n",com_sock,erl_errno)); + ei_x_new(&answer); + ei_x_format(&answer,"{~i,~i,~i}",com_sock,erl_errno,ETIMEDOUT); +#ifdef DEBUG + { + int tlen = 0; + int v; + ei_decode_version(answer.buff,&tlen,&v); + ei_print_term(debugfile,answer.buff,&tlen); + DEBUGF(("\n")); + } +#endif + send_bin_term(&answer); + DEBUGF(("Binary term sent.\n")); + ei_x_free(&answer); + } else { + ei_x_buff answer; + char atom[256]; + erlang_pid pid; + int res, iterations, i; + ei_x_buff send_buffer; + + DEBUGF(("Success when connecting.{%d,%d}\n",com_sock,erl_errno)); + ei_x_new(&answer); + ei_x_format(&answer,"~i",com_sock); + send_bin_term(&answer); + ei_x_free(&answer); + ei_x_new_with_version(&send_buffer); + if ((res = get_message(com_sock, &send_buffer, + atom ,&pid, &iterations)) < 0) { + DEBUGF(("Get_message_failure at line %d\n",__LINE__)); + ei_x_free(&send_buffer); + goto cleanup; + } + DEBUGF(("Get_message success (%d), bindata:\n",res)); +#ifdef DEBUG + { + int ndx = 0; + int v; + ei_decode_version(send_buffer.buff,&ndx,&v); + ei_print_term(debugfile, send_buffer.buff, &ndx); + } +#endif + DEBUGF(("\n")); + switch (res) { + case 1: /* Send to pid in 'pid' */ + ei_x_new(&answer); + for (i=0;i < iterations; ++i) { + res = ei_send_tmo(com_sock, &pid, send_buffer.buff, + send_buffer.index, 5000); + DEBUGF(("Sent bindata (%d):\n",res)); +#ifdef DEBUG + { + int ndx = 0; + int v; + ei_decode_version(send_buffer.buff,&ndx,&v); + ei_print_term(debugfile, send_buffer.buff, &ndx); + } +#endif + DEBUGF(("\n")); + if (res < 0) + break; + } + if (res < 0) { + DEBUGF(("ei_send_tmo failure at line %d\n",__LINE__)); + ei_x_format(&answer,"{~i,~i,~i,~i}",res,erl_errno,i,ETIMEDOUT); + } else { + ei_x_format(&answer,"~i",res); + } + send_bin_term(&answer); + ei_x_free(&answer); + ei_x_free(&send_buffer); + goto cleanup; + case 2: /* Registered name in 'atom' */ + ei_x_new(&answer); + for (i=0;i < iterations; ++i) { + res = ei_reg_send_tmo(&nodeinfo, com_sock, atom, + send_buffer.buff, + send_buffer.index,5000); + if (res < 0) + break; + } + if (res < 0) { + DEBUGF(("ei_reg_send_tmo failure at line %d\n",__LINE__)); + ei_x_format(&answer,"{~i,~i,~i,~i}",res,erl_errno,i,ETIMEDOUT); + } else { + ei_x_format(&answer,"~i",res); + } + send_bin_term(&answer); + ei_x_free(&answer); + ei_x_free(&send_buffer); + goto cleanup; + default: + DEBUGF(("unexpected request number %d at line %d\n",res,__LINE__)); + ei_x_free(&send_buffer); + goto cleanup; + } + } +cleanup: + if (com_sock >= 0) { + closesocket(com_sock); + } + + if (nodename != NULL) { + free(nodename); + } + if (cookie != NULL) { + free(cookie); + } + if (peername != NULL) { + free(peername); + } + CLOSE_DEBUGFILE(); + report(1); +} + + +TESTCASE(connect_tmo) +{ + char *nodename = NULL; + char *cookie = NULL; + char *peername = NULL; + int com_sock = -1; + ei_cnode nodeinfo; + + + + OPEN_DEBUGFILE(3); + + if (decode_request(&nodename,&cookie,&peername) != 0) { + goto cleanup; + } + if (ei_connect_init(&nodeinfo, nodename, cookie, 0) < 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + + if ((com_sock = ei_connect_tmo(&nodeinfo, peername, 5000)) < 0) { + ei_x_buff answer; + DEBUGF(("Got error while connecting.{%d,%d}\n",com_sock,erl_errno)); + ei_x_new(&answer); + + /* On some systems errno gets set to EHOSTUNREACH rather than + ETIMEDOUT, which is ok. Let's check for that and report timeout + if it happens. + Max OS X seems to respond EHOSTDOWN, which should be ok. + */ + + +#if defined(EHOSTUNREACH) + if (errno == EHOSTUNREACH) + ei_x_format(&answer,"{~i,~i,~i}",com_sock,ETIMEDOUT,ETIMEDOUT); + else +#endif + +#if defined(EHOSTDOWN) + if (errno == EHOSTDOWN) + ei_x_format(&answer,"{~i,~i,~i}",com_sock,ETIMEDOUT,ETIMEDOUT); + else +#endif + + ei_x_format(&answer,"{~i,~i,~i}",com_sock,erl_errno,ETIMEDOUT); + +#ifdef DEBUG + { + int tlen = 0; + int v; + ei_decode_version(answer.buff,&tlen,&v); + ei_print_term(debugfile,answer.buff,&tlen); + DEBUGF(("\n")); + } +#endif + send_bin_term(&answer); + DEBUGF(("Binary term sent.\n")); + ei_x_free(&answer); + } else { + ei_x_buff answer; + DEBUGF(("Success when connecting.{%d,%d}\n",com_sock,erl_errno)); + ei_x_new(&answer); + ei_x_format(&answer,"~i",com_sock); + send_bin_term(&answer); + ei_x_free(&answer); + } + +cleanup: + if (com_sock >= 0) { + closesocket(com_sock); + } + + if (nodename != NULL) { + free(nodename); + } + if (cookie != NULL) { + free(cookie); + } + if (peername != NULL) { + free(peername); + } + CLOSE_DEBUGFILE(); + report(1); +} + +TESTCASE(accept_tmo) +{ + char *nodename = NULL; + char *cookie = NULL; + int listen_sock = -1; + int epmd_sock = -1; + int com_sock = -1; + struct sockaddr_in sin; + int sin_siz = sizeof(sin); + ErlConnect peer; + ei_cnode nodeinfo; + + + + OPEN_DEBUGFILE(2); + + putenv("EI_TRACELEVEL=10"); + + if (decode_request(&nodename,&cookie,NULL) != 0) { + goto cleanup; + } + if (ei_connect_init(&nodeinfo, nodename, cookie, 0) < 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + + if ((listen_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + + if (bind(listen_sock,(struct sockaddr *) &sin, sizeof(sin)) != 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + if (getsockname(listen_sock, + (struct sockaddr *) &sin, &sin_siz) != 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + if (listen(listen_sock, 5) != 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + + if ((epmd_sock = ei_publish(&nodeinfo, ntohs(sin.sin_port))) < 0) { + DEBUGF(("Failure at line %d[%d,%d]\n",__LINE__,sin.sin_port,erl_errno)); + goto cleanup; + } + + if ((com_sock = ei_accept_tmo(&nodeinfo, + listen_sock, &peer, 5000)) == ERL_ERROR) { + ei_x_buff answer; + DEBUGF(("Got error while accepting.{%d,%d}\n",com_sock,erl_errno)); + ei_x_new(&answer); + ei_x_format(&answer,"{~i,~i,~i}",com_sock,erl_errno,ETIMEDOUT); +#ifdef DEBUG + { + int tlen = 0; + int v; + ei_decode_version(answer.buff,&tlen,&v); + ei_print_term(debugfile,answer.buff,&tlen); + DEBUGF(("\n")); + } +#endif + send_bin_term(&answer); + DEBUGF(("Binary term sent.\n")); + ei_x_free(&answer); + } else { + ei_x_buff answer; + DEBUGF(("Success when connecting.{%d,%d}\n",com_sock,erl_errno)); + ei_x_new(&answer); + ei_x_format(&answer,"~i",com_sock); + send_bin_term(&answer); + ei_x_free(&answer); + } + +cleanup: + + if (listen_sock >= 0) { + closesocket(listen_sock); + } + if (epmd_sock >= 0) { + closesocket(epmd_sock); + } + if (com_sock >= 0) { + closesocket(com_sock); + } + + if (nodename != NULL) { + free(nodename); + } + if (cookie != NULL) { + free(cookie); + } + CLOSE_DEBUGFILE(); + report(1); +} + diff --git a/lib/erl_interface/test/erl_connect_SUITE.erl b/lib/erl_interface/test/erl_connect_SUITE.erl new file mode 100644 index 0000000000..0d6539d98f --- /dev/null +++ b/lib/erl_interface/test/erl_connect_SUITE.erl @@ -0,0 +1,134 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(erl_connect_SUITE). + +-include("test_server.hrl"). +-include("erl_connect_SUITE_data/erl_connect_test_cases.hrl"). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + erl_send/1,erl_reg_send/1, erl_send_cookie_file/1]). + +-import(runner, [get_term/1,send_term/2]). + +all(suite) -> + [erl_send,erl_reg_send,erl_send_cookie_file]. + +init_per_testcase(_Case, Config) -> + Dog = ?t:timetrap(?t:minutes(0.25)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +erl_send(Config) when is_list(Config) -> + ?line P = runner:start(?interpret), + ?line 1 = erl_connect_init(P, 42, erlang:get_cookie(), 0), + ?line {ok,Fd} = erl_connect(P, node()), + + ?line ok = erl_send(P, Fd, self(), AMsg={a,message}), + ?line receive AMsg -> ok end, + + ?line 0 = erl_close_connection(P,Fd), + ?line runner:send_eot(P), + ?line runner:recv_eot(P), + ok. + +erl_send_cookie_file(Config) when is_list(Config) -> + case os:type() of + vxworks -> + {skip,"Skipped on VxWorks"}; + _ -> + ?line P = runner:start(?interpret), + ?line 1 = erl_connect_init(P, 42, '', 0), + ?line {ok,Fd} = erl_connect(P, node()), + + ?line ok = erl_send(P, Fd, self(), AMsg={a,message}), + ?line receive AMsg -> ok end, + + ?line 0 = erl_close_connection(P,Fd), + ?line runner:send_eot(P), + ?line runner:recv_eot(P), + ok + end. + +erl_reg_send(Config) when is_list(Config) -> + ?line P = runner:start(?interpret), + ?line 1 = erl_connect_init(P, 42, erlang:get_cookie(), 0), + ?line {ok,Fd} = erl_connect(P, node()), + + ARegName = a_strange_registred_name, + ?line register(ARegName, self()), + ?line ok = erl_reg_send(P, Fd, ARegName, AMsg={another,[strange],message}), + ?line receive AMsg -> ok end, + + ?line 0 = erl_close_connection(P,Fd), + ?line runner:send_eot(P), + ?line runner:recv_eot(P), + ok. + + +%%% Interface functions for erl_interface functions. + +erl_connect_init(P, Num, Cookie, Creation) -> + send_command(P, erl_connect_init, [Num,Cookie,Creation]), + case get_term(P) of + {term,Int} when is_integer(Int) -> Int + end. + +erl_connect(P, Node) -> + send_command(P, erl_connect, [Node]), + case get_term(P) of + {term,{Fd,_}} when Fd >= 0 -> {ok,Fd}; + {term,{-1,Errno}} -> {error,Errno} + end. + +erl_close_connection(P, FD) -> + send_command(P, erl_close_connection, [FD]), + case get_term(P) of + {term,Int} when is_integer(Int) -> Int + end. + +erl_send(P, Fd, To, Msg) -> + send_command(P, erl_send, [Fd,To,Msg]), + get_send_result(P). + +erl_reg_send(P, Fd, To, Msg) -> + send_command(P, erl_reg_send, [Fd,To,Msg]), + get_send_result(P). + +get_send_result(P) -> + case get_term(P) of + {term,{1,_}} -> ok; + {term,{-1,Errno}} -> {error,Errno}; + {term,{Res,Errno}}-> + io:format("Return value: ~p\nerl_errno: ~p", [Res,Errno]), + ?t:fail(bad_return_value) + end. + +send_command(P, Name, Args) -> + runner:send_term(P, {Name,list_to_tuple(Args)}). + + + + + diff --git a/lib/erl_interface/test/erl_connect_SUITE_data/Makefile.first b/lib/erl_interface/test/erl_connect_SUITE_data/Makefile.first new file mode 100644 index 0000000000..09c00e7b8c --- /dev/null +++ b/lib/erl_interface/test/erl_connect_SUITE_data/Makefile.first @@ -0,0 +1,21 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +erl_connect_test_decl.c: erl_connect_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run erl_connect_test -s erlang halt diff --git a/lib/erl_interface/test/erl_connect_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_connect_SUITE_data/Makefile.src new file mode 100644 index 0000000000..047a734ecb --- /dev/null +++ b/lib/erl_interface/test/erl_connect_SUITE_data/Makefile.src @@ -0,0 +1,41 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2000-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBERL = $(LIBPATH)/@erl_interface_lib@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = ../all_SUITE_data/runner@obj@ \ + $(LIBERL) $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + @erl_interface_threadlib@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data +OBJS = erl_connect_test@obj@ erl_connect_test_decl@obj@ + +all: erl_connect_test@exe@ + +erl_connect_test@exe@: $(OBJS) $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(OBJS) $(LIBFLAGS) + +clean: + $(RM) $(OBJS) + $(RM) erl_connect_test@exe@ diff --git a/lib/erl_interface/test/erl_connect_SUITE_data/erl_connect_test.c b/lib/erl_interface/test/erl_connect_SUITE_data/erl_connect_test.c new file mode 100644 index 0000000000..02304260b8 --- /dev/null +++ b/lib/erl_interface/test/erl_connect_SUITE_data/erl_connect_test.c @@ -0,0 +1,202 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2000-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* + * Purpose: Tests the functions in erl_connect.c. + * Author: Bjorn Gustavsson + * + * See the erl_connect_SUITE.erl file for a "table of contents". + */ + +#include <stdio.h> +#include <string.h> + +#include "runner.h" + +static void cmd_erl_connect_init(ETERM* args); +static void cmd_erl_connect(ETERM* args); +static void cmd_erl_send(ETERM* args); +static void cmd_erl_reg_send(ETERM* args); +static void cmd_erl_close_connection(ETERM *args); + +static void send_errno_result(int value); + +static struct { + char* name; + int num_args; /* Number of arguments. */ + void (*func)(ETERM* args); +} commands[] = { + "erl_connect_init", 3, cmd_erl_connect_init, + "erl_connect", 1, cmd_erl_connect, + "erl_close_connection", 1, cmd_erl_close_connection, + "erl_send", 3, cmd_erl_send, + "erl_reg_send", 3, cmd_erl_reg_send, +}; + + +/* + * Sends a list contaning all data types to the Erlang side. + */ + +TESTCASE(interpret) +{ + ETERM* term; + + erl_init(NULL, 0); + + outer_loop: + + term = get_term(); + + if (term == NULL) { + report(1); + return; + } else { + ETERM* Func; + ETERM* Args; + int i; + + if (!ERL_IS_TUPLE(term) || ERL_TUPLE_SIZE(term) != 2) { + fail("term should be a tuple of size 2"); + } + + Func = erl_element(1, term); + if (!ERL_IS_ATOM(Func)) { + fail("function name should be an atom"); + } + Args = erl_element(2, term); + if (!ERL_IS_TUPLE(Args)) { + fail("function arguments should be a tuple"); + } + erl_free_term(term); + for (i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) { + int n = strlen(commands[i].name); + if (ERL_ATOM_SIZE(Func) != n) { + continue; + } + if (memcmp(ERL_ATOM_PTR(Func), commands[i].name, n) == 0) { + erl_free_term(Func); + if (ERL_TUPLE_SIZE(Args) != commands[i].num_args) { + fail("wrong number of arguments"); + } + commands[i].func(Args); + erl_free_term(Args); + goto outer_loop; + } + } + fail("bad command"); + } +} + +#define VERIFY_TYPE(Test, Term) \ +if (!Test(Term)) { \ + fail("wrong type for " #Term); \ +} else { \ +} + +static void +cmd_erl_connect_init(ETERM* args) +{ + ETERM* number; + ETERM* res; + ETERM* cookie; + char cookie_buffer[256]; + + number = ERL_TUPLE_ELEMENT(args, 0); + VERIFY_TYPE(ERL_IS_INTEGER, number); + cookie = ERL_TUPLE_ELEMENT(args, 1); + VERIFY_TYPE(ERL_IS_ATOM, cookie); + if (ERL_ATOM_SIZE(cookie) == 0) { + res = erl_mk_int(erl_connect_init(ERL_INT_VALUE(number), 0, 0)); + } else { + memcpy(cookie_buffer, ERL_ATOM_PTR(cookie), ERL_ATOM_SIZE(cookie)); + cookie_buffer[ERL_ATOM_SIZE(cookie)] = '\0'; + res = erl_mk_int(erl_connect_init(ERL_INT_VALUE(number), + cookie_buffer, 0)); + } + send_term(res); + erl_free_term(res); +} + +static void +cmd_erl_connect(ETERM* args) +{ + ETERM* node; + char node_buffer[256]; + + node = ERL_TUPLE_ELEMENT(args, 0); + VERIFY_TYPE(ERL_IS_ATOM, node); + memcpy(node_buffer, ERL_ATOM_PTR(node), ERL_ATOM_SIZE(node)); + node_buffer[ERL_ATOM_SIZE(node)] = '\0'; + send_errno_result(erl_connect(node_buffer)); +} + +static void +cmd_erl_close_connection(ETERM* args) +{ + ETERM* number; + ETERM* res; + + number = ERL_TUPLE_ELEMENT(args, 0); + VERIFY_TYPE(ERL_IS_INTEGER, number); + res = erl_mk_int(erl_close_connection(ERL_INT_VALUE(number))); + send_term(res); + erl_free_term(res); +} + +static void +cmd_erl_send(ETERM* args) +{ + ETERM* fd_term = ERL_TUPLE_ELEMENT(args, 0); + ETERM* to = ERL_TUPLE_ELEMENT(args, 1); + ETERM* msg = ERL_TUPLE_ELEMENT(args, 2); + + VERIFY_TYPE(ERL_IS_INTEGER, fd_term); + send_errno_result(erl_send(ERL_INT_VALUE(fd_term), to, msg)); +} + +static void +cmd_erl_reg_send(ETERM* args) +{ + ETERM* fd_term = ERL_TUPLE_ELEMENT(args, 0); + ETERM* to = ERL_TUPLE_ELEMENT(args, 1); + ETERM* msg = ERL_TUPLE_ELEMENT(args, 2); + char reg_name[256]; + + VERIFY_TYPE(ERL_IS_INTEGER, fd_term); + VERIFY_TYPE(ERL_IS_ATOM, to); + memcpy(reg_name, ERL_ATOM_PTR(to), ERL_ATOM_SIZE(to)); + reg_name[ERL_ATOM_SIZE(to)] = '\0'; + send_errno_result(erl_reg_send(ERL_INT_VALUE(fd_term), reg_name, msg)); +} + +static void +send_errno_result(int value) +{ + ETERM* res_array[2]; + ETERM* res_tuple; + + res_array[0] = erl_mk_int(value); + res_array[1] = erl_mk_int(erl_errno); + res_tuple = erl_mk_tuple(res_array, 2); + send_term(res_tuple); + erl_free_term(res_array[0]); + erl_free_term(res_array[1]); + erl_free_term(res_tuple); +} diff --git a/lib/erl_interface/test/erl_eterm_SUITE.erl b/lib/erl_interface/test/erl_eterm_SUITE.erl new file mode 100644 index 0000000000..634e2f9aa0 --- /dev/null +++ b/lib/erl_interface/test/erl_eterm_SUITE.erl @@ -0,0 +1,1136 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(erl_eterm_SUITE). + +-include("test_server.hrl"). +-include("erl_eterm_SUITE_data/eterm_test_cases.hrl"). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% The tests are organised as follows: +%%% +%%% 1. Basic tests (encoding, decoding, memory allocation). +%%% 2. Constructing terms (the erl_mk_xxx() functions and erl_copy_term()). +%%% 3. Extracting & info functions (erl_hd(), erl_length() etc). +%%% 4. I/O list functions. +%%% 5. Miscellanous functions. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-export([all/1, build_terms/1, round_trip_conversion/1, + decode_terms/1, decode_float/1, + t_erl_mk_int/1, t_erl_mk_list/1, + basic_copy/1, + t_erl_cons/1, + t_erl_mk_atom/1, + t_erl_mk_binary/1, + t_erl_mk_empty_list/1, + t_erl_mk_float/1, + t_erl_mk_pid/1, + t_erl_mk_xpid/1, + t_erl_mk_port/1, + t_erl_mk_xport/1, + t_erl_mk_ref/1, + t_erl_mk_long_ref/1, + t_erl_mk_string/1, + t_erl_mk_estring/1, + t_erl_mk_tuple/1, + t_erl_mk_uint/1, + t_erl_mk_var/1, + t_erl_size/1, + t_erl_var_content/1, + t_erl_element/1, + t_erl_length/1, t_erl_hd/1, t_erl_tl/1, + type_checks/1, extractor_macros/1, + t_erl_iolist_length/1, t_erl_iolist_to_binary/1, + t_erl_iolist_to_string/1, + erl_print_term/1, print_string/1, + t_erl_free_compound/1, + high_chaparal/1, + broken_data/1, + cnode_1/1]). + +-export([start_cnode/1]). + +-import(runner, [get_term/1]). + +%% This test suite controls the running of the C language functions +%% in eterm_test.c and print_term.c. + +all(suite) -> [build_terms, round_trip_conversion, + decode_terms, decode_float, + t_erl_mk_int, t_erl_mk_list, + basic_copy, + t_erl_mk_atom, + t_erl_mk_binary, + t_erl_mk_empty_list, + t_erl_mk_float, + t_erl_mk_pid, + t_erl_mk_xpid, + t_erl_mk_port, + t_erl_mk_xport, + t_erl_mk_ref, + t_erl_mk_long_ref, + t_erl_mk_string, + t_erl_mk_estring, + t_erl_mk_tuple, + t_erl_mk_uint, + t_erl_mk_var, + t_erl_size, + t_erl_var_content, + t_erl_element, + t_erl_cons, + t_erl_length, t_erl_hd, t_erl_tl, + type_checks, extractor_macros, + t_erl_iolist_length, t_erl_iolist_to_binary, + t_erl_iolist_to_string, + erl_print_term, print_string, + t_erl_free_compound, + high_chaparal, + broken_data, + cnode_1]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% +%%% 1. B a s i c t e s t s +%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% This test asks the C function to construct all data types in +%% a list and verifies that the result is as expected. + +build_terms(suite) -> []; +build_terms(Config) when is_list(Config) -> + ?line P = runner:start(?build_terms), + ?line {term, Term} = get_term(P), + ?line io:format("Received: ~p", [Term]), + ?line [ARefLN, ARef, APortLN, APort, APidLN, APid, + {element1, 42, 767}, "A string", + 1, -1, 0, 3.0, ABin, 'I am an atom'] = Term, + ?line "A binary" = binary_to_list(ABin), + ?line case ARef of + R when is_reference(R), node(R) == kalle@localhost -> ok + end, + ?line case ARefLN of + R1 when is_reference(R1), node(R1) == abcdefghijabcdefghij@localhost -> ok + end, + ?line case APort of + Port when is_port(Port), node(Port) == kalle@localhost -> ok + end, + ?line case APortLN of + Port1 when is_port(Port1), node(Port1) == abcdefghijabcdefghij@localhost -> ok + end, + ?line case APid of + Pid when is_pid(Pid), node(Pid) == kalle@localhost -> ok + end, + ?line case APidLN of + Pid1 when is_pid(Pid1), node(Pid1) == abcdefghijabcdefghij@localhost -> ok + end, + + ?line runner:recv_eot(P), + ok. + +%% This test is run entirely in C code. + +round_trip_conversion(suite) -> []; +round_trip_conversion(Config) when is_list(Config) -> + ?line runner:test(?round_trip_conversion), + ok. + +%% This test sends a list of all data types to the C code function, +%% which decodes it and verifies it. + +decode_terms(suite) -> []; +decode_terms(Config) when is_list(Config) -> + ?line Dummy1 = list_to_atom(filename:join(?config(priv_dir, Config), + dummy_file1)), + ?line Dummy2 = list_to_atom(filename:join(?config(priv_dir, Config), + dummy_file2)), + ?line Port1 = open_port(Dummy1, [out]), + ?line Port2 = open_port(Dummy2, [out]), + ?line ABinary = list_to_binary("A binary"), + ?line Terms = [make_ref(), make_ref(), + Port1, Port2, + self(), self(), + {element1, 42, 767}, "A string", + 1, -1, 0, 3.0, ABinary, 'I am an atom'], + + ?line P = runner:start(?decode_terms), + ?line runner:send_term(P, Terms), + ?line runner:recv_eot(P), + + ok. + +%% Decodes the floating point number 3.1415. + +decode_float(suite) -> []; +decode_float(Config) when is_list(Config) -> + ?line P = runner:start(?decode_float), + ?line runner:send_term(P, 3.1415), + ?line runner:recv_eot(P), + ok. + +%% Tests the erl_free_compound() function. + +t_erl_free_compound(suite) -> []; +t_erl_free_compound(Config) when is_list(Config) -> + ?line runner:test(?t_erl_free_compound), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% +%%% 2. C o n s t r u c t i n g t e r m s +%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% This tests the erl_mk_list() function. + +t_erl_mk_list(suite) -> []; +t_erl_mk_list(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_list), + + ?line {term, []} = get_term(P), + ?line {term, [abc]} = get_term(P), + ?line {term, [abcdef, 42]} = get_term(P), + ?line {term, [0.0, 23, [], 3.1415]} = get_term(P), + + ?line runner:recv_eot(P), + ok. + + +%% This tests the erl_mk_int() function. + +t_erl_mk_int(suite) -> []; +t_erl_mk_int(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_int), + + ?line {term, 0} = get_term(P), + ?line {term, 127} = get_term(P), + ?line {term, 128} = get_term(P), + ?line {term, 255} = get_term(P), + ?line {term, 256} = get_term(P), + + ?line {term, 16#FFFF} = get_term(P), + ?line {term, 16#10000} = get_term(P), + + ?line {term, 16#07FFFFFF} = get_term(P), + ?line {term, 16#0FFFFFFF} = get_term(P), + ?line {term, 16#1FFFFFFF} = get_term(P), + ?line {term, 16#3FFFFFFF} = get_term(P), + ?line {term, 16#7FFFFFFF} = get_term(P), + + ?line {term, 16#08000000} = get_term(P), + ?line {term, 16#10000000} = get_term(P), + ?line {term, 16#20000000} = get_term(P), + ?line {term, 16#40000000} = get_term(P), + + + ?line {term, -16#07FFFFFF} = get_term(P), + ?line {term, -16#0FFFFFFF} = get_term(P), + ?line {term, -16#1FFFFFFF} = get_term(P), + ?line {term, -16#3FFFFFFF} = get_term(P), + ?line {term, -16#7FFFFFFF} = get_term(P), + + ?line {term, -16#08000000} = get_term(P), + ?line {term, -16#10000000} = get_term(P), + ?line {term, -16#20000000} = get_term(P), + ?line {term, -16#40000000} = get_term(P), + + ?line {term, -16#08000001} = get_term(P), + ?line {term, -16#10000001} = get_term(P), + ?line {term, -16#20000001} = get_term(P), + ?line {term, -16#40000001} = get_term(P), + + ?line {term, -16#08000002} = get_term(P), + ?line {term, -16#10000002} = get_term(P), + ?line {term, -16#20000002} = get_term(P), + ?line {term, -16#40000002} = get_term(P), + + ?line {term, -1999999999} = get_term(P), + ?line {term, -2000000000} = get_term(P), + ?line {term, -2000000001} = get_term(P), + + ?line runner:recv_eot(P), + ok. + + +%% Basic test of erl_copy_term(). + +basic_copy(suite) -> []; +basic_copy(Config) when is_list(Config) -> + ?line runner:test(?basic_copy), + ok. + + +%% This tests the erl_mk_tuple() function. + +t_erl_mk_tuple(suite) -> []; +t_erl_mk_tuple(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_tuple), + + ?line {term, {madonna, 21, 'mad donna', 12}} = get_term(P), + ?line {term, {'Madonna',21,{children,{"Isabella",2}}, + {'home page',"http://www.madonna.com/"}}} = get_term(P), + + ?line runner:recv_eot(P), + ok. + + +%% This tests the erl_mk_atom() function. + +t_erl_mk_atom(suite) -> []; +t_erl_mk_atom(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_atom), + + ?line {term, madonna} = (get_term(P)), + ?line {term, 'Madonna'} = (get_term(P)), + ?line {term, 'mad donna'} = (get_term(P)), + ?line {term, '_madonna_'} = (get_term(P)), + ?line {term, '/home/madonna/tour_plan'} = (get_term(P)), + ?line {term, 'http://www.madonna.com/tour_plan'} = (get_term(P)), + ?line {term, '\'madonna\''} = (get_term(P)), + ?line {term, '\"madonna\"'} = (get_term(P)), + ?line {term, '\\madonna\\'} = (get_term(P)), + ?line {term, '{madonna,21,\'mad donna\',12}'} = (get_term(P)), + + ?line runner:recv_eot(P), + ok. + + +%% This tests the erl_mk_binary() function. + +t_erl_mk_binary(suite) -> []; +t_erl_mk_binary(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_binary), + + ?line {term, Bin} = (get_term(P)), + ?line "{madonna,21,'mad donna',1234.567.890, !#$%&/()=?+-@, \" \\}" = + binary_to_list(Bin), + + ?line runner:recv_eot(P), + ok. + + +%% This tests the erl_mk_empty_list() function. + +t_erl_mk_empty_list(suite) -> []; +t_erl_mk_empty_list(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_empty_list), + + ?line {term, []} = get_term(P), + + ?line runner:recv_eot(P), + ok. + + +%% This tests the erl_mk_float() function. + +t_erl_mk_float(suite) -> []; +t_erl_mk_float(Config) when is_list(Config) -> + case os:type() of + vxworks -> + {skipped, "Floating point numbers never compare equal on PPC"}; + _ -> + ?line P = runner:start(?t_erl_mk_float), + ?line {term, {3.1415, 1.999999, 2.000000, 2.000001, + 2.000002, 12345.67890}} = + get_term(P), + ?line runner:recv_eot(P), + ok + end. + + +%% This tests the erl_mk_pid() function. + +t_erl_mk_pid(suite) -> []; +t_erl_mk_pid(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_pid), + + ?line {term, A_pid} = (get_term(P)), + ?line {pid, kalle@localhost, 3, 2} = nc2vinfo(A_pid), + + ?line runner:recv_eot(P), + ok. + +t_erl_mk_xpid(suite) -> []; +t_erl_mk_xpid(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_xpid), + + ?line {term, A_pid} = (get_term(P)), + ?line {pid, kalle@localhost, 32767, 8191} = nc2vinfo(A_pid), + + ?line runner:recv_eot(P), + ok. + + +%% This tests the erl_mk_port() function. + +t_erl_mk_port(suite) -> []; +t_erl_mk_port(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_port), + + ?line {term, A_port} = (get_term(P)), + ?line {port, kalle@localhost, 4} = nc2vinfo(A_port), + + ?line runner:recv_eot(P), + ok. + +t_erl_mk_xport(suite) -> []; +t_erl_mk_xport(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_xport), + + ?line {term, A_port} = (get_term(P)), + ?line {port, kalle@localhost, 268435455} = nc2vinfo(A_port), + + ?line runner:recv_eot(P), + ok. + + +%% This tests the erl_mk_ref() function. + +t_erl_mk_ref(suite) -> []; +t_erl_mk_ref(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_ref), + + ?line {term, A_ref} = (get_term(P)), + ?line {ref, kalle@localhost, _Length, [6]} = nc2vinfo(A_ref), + + ?line runner:recv_eot(P), + ok. + +t_erl_mk_long_ref(suite) -> []; +t_erl_mk_long_ref(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_long_ref), + + ?line {term, A_ref} = (get_term(P)), + ?line {ref, kalle@localhost, _Length, [4294967295,4294967295,262143]} + = nc2vinfo(A_ref), + + ?line runner:recv_eot(P), + ok. + + +%% This tests the erl_mk_string() function. + +t_erl_mk_string(suite) -> []; +t_erl_mk_string(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_string), + + ?line {term, "madonna"} = (get_term(P)), + ?line {term, "Madonna"} = (get_term(P)), + ?line {term, "mad donna"} = (get_term(P)), + ?line {term, "_madonna_"} = (get_term(P)), + ?line {term, "/home/madonna/tour_plan"} = (get_term(P)), + ?line {term, "http://www.madonna.com/tour_plan"} = (get_term(P)), + ?line {term, "\'madonna\'"} = (get_term(P)), + ?line {term, "\"madonna\""} = (get_term(P)), + ?line {term, "\\madonna\\"} = (get_term(P)), + ?line {term, "{madonna,21,'mad donna',12}"} = (get_term(P)), + + ?line runner:recv_eot(P), + ok. + + +%% This tests the erl_mk_estring() function. + +t_erl_mk_estring(suite) -> []; +t_erl_mk_estring(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_estring), + + ?line {term, "madonna"} = (get_term(P)), + ?line {term, "Madonna"} = (get_term(P)), + ?line {term, "mad donna"} = (get_term(P)), + ?line {term, "_madonna_"} = (get_term(P)), + ?line {term, "/home/madonna/tour_plan"} = (get_term(P)), + ?line {term, "http://www.madonna.com/tour_plan"} = (get_term(P)), + ?line {term, "\'madonna\'"} = (get_term(P)), + ?line {term, "\"madonna\""} = (get_term(P)), + ?line {term, "\\madonna\\"} = (get_term(P)), + ?line {term, "{madonna,21,'mad donna',12}"} = (get_term(P)), + + ?line runner:recv_eot(P), + ok. + + +%% This tests the erl_mk_uint() function. + +t_erl_mk_uint(suite) -> []; +t_erl_mk_uint(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_uint), + + ?line {term, 54321} = (get_term(P)), + ?line {term, 2147483647} = (get_term(P)), + ?line {term, 2147483648} = (get_term(P)), + ?line {term, 2147483649} = (get_term(P)), + ?line {term, 2147483650} = (get_term(P)), + ?line {term, 4294967295} = (get_term(P)), + + ?line runner:recv_eot(P), + ok. + + +%% This tests the erl_mk_var() function. + +t_erl_mk_var(suite) -> []; +t_erl_mk_var(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_mk_var), + + ?line {term, 1} = (get_term(P)), + ?line {term, 0} = (get_term(P)), + ?line {term, 1} = (get_term(P)), + ?line {term, 0} = (get_term(P)), + ?line {term, 1} = (get_term(P)), + ?line {term, 0} = (get_term(P)), + ?line {term, 1} = (get_term(P)), + + ?line runner:recv_eot(P), + ok. + + +%% This tests the erl_cons() function. + +t_erl_cons(suite) -> []; +t_erl_cons(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_cons), + + ?line {term, [madonna, 21]} = get_term(P), + + ?line runner:recv_eot(P), + ok. + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% +%%% 3. E x t r a c t i n g & i n f o f u n c t i o n s +%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests the erl_length() function. + +t_erl_length(suite) -> []; +t_erl_length(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_length), + + ?line 0 = erl_length(P, []), + ?line 1 = erl_length(P, [a]), + ?line 2 = erl_length(P, [a, b]), + ?line 3 = erl_length(P, [a, b, c]), + + ?line 4 = erl_length(P, [a, [x, y], c, []]), + + ?line -1 = erl_length(P, [a|b]), + ?line -1 = erl_length(P, a), + + ?line runner:finish(P), + ok. + +%% Invokes the erl_length() function. + +erl_length(Port, List) -> + call_erl_function(Port, List). + +%% Tests the erl_hd() function. + +t_erl_hd(suite) -> []; +t_erl_hd(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_hd), + + ?line 'NULL' = erl_hd(P, 42), + ?line 'NULL' = erl_hd(P, abc), + ?line 'NULL' = erl_hd(P, []), + + ?line [] = erl_hd(P, [[], a]), + ?line a = erl_hd(P, [a]), + ?line a = erl_hd(P, [a, b]), + ?line a = erl_hd(P, [a, b, c]), + ?line a = erl_hd(P, [a|b]), + + ?line runner:send_eot(P), + ?line runner:recv_eot(P), + ok. + +%% Invokes the erl_hd() function. + +erl_hd(Port, List) -> + call_erl_function(Port, List). + +%% Tests the erl_tail() function. + +t_erl_tl(suite) -> []; +t_erl_tl(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_tl), + + ?line 'NULL' = erl_tl(P, 42), + ?line 'NULL' = erl_tl(P, abc), + ?line 'NULL' = erl_tl(P, []), + + ?line [] = erl_tl(P, [a]), + ?line [b] = erl_tl(P, [a, b]), + ?line [b, c] = erl_tl(P, [a, b, c]), + + ?line b = erl_tl(P, [a|b]), + + ?line runner:send_eot(P), + ?line runner:recv_eot(P), + ok. + +%% Invokes the erl_tail() function in erl_interface. + +erl_tl(Port, List) -> + call_erl_function(Port, List). + +%% Tests the type checking macros (done in the C program). + +type_checks(suite) -> []; +type_checks(Config) when is_list(Config) -> + ?line runner:test(?type_checks), + ok. + +%% Tests the extractor macros (done in the C program). + +extractor_macros(suite) -> []; +extractor_macros(Config) when is_list(Config) -> + ?line runner:test(?extractor_macros), + ok. + + +%% This tests the erl_size() function. + +t_erl_size(suite) -> []; +t_erl_size(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_size), + + ?line {term, 0} = (get_term(P)), + ?line {term, 4} = (get_term(P)), + + ?line {term, 0} = (get_term(P)), + ?line {term, 27} = (get_term(P)), + + ?line runner:recv_eot(P), + ok. + + +%% This tests the erl_var_content() function. + +t_erl_var_content(suite) -> []; +t_erl_var_content(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_var_content), + + ?line {term, 17} = (get_term(P)), + ?line {term, "http://www.madonna.com"} = (get_term(P)), + ?line {term, 2} = (get_term(P)), + ?line {term, "http://www.madonna.com"} = (get_term(P)), + ?line {term, 2} = (get_term(P)), + + ?line runner:recv_eot(P), + ok. + + +%% This tests the erl_element() function. + +t_erl_element(suite) -> []; +t_erl_element(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_element), + + ?line {term, madonna} = get_term(P), + ?line {term, 21} = get_term(P), + ?line {term, 'mad donna'} = get_term(P), + ?line {term, 12} = get_term(P), + + ?line {term, 'Madonna'} = get_term(P), + ?line {term, 21} = get_term(P), + ?line {term, {children,{"Isabella",2}}} = get_term(P), + ?line {term, {'home page',"http://www.madonna.com/"}} = get_term(P), + + ?line runner:recv_eot(P), + ok. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% +%%% 4. I / O l i s t f u n c t i o n s +%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests the erl_iolist_length() function. + +t_erl_iolist_length(suite) -> []; +t_erl_iolist_length(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_iolist_length), + + %% Flat lists. + + ?line 0 = erl_iolist_length(P, []), + ?line 1 = erl_iolist_length(P, [10]), + ?line 2 = erl_iolist_length(P, [10, 20]), + ?line 3 = erl_iolist_length(P, [10, 20, 30]), + ?line 256 = erl_iolist_length(P, lists:seq(0, 255)), + + %% Deep lists. + + ?line 0 = erl_iolist_length(P, [[]]), + ?line 1 = erl_iolist_length(P, [[], 42]), + ?line 1 = erl_iolist_length(P, [42, []]), + ?line 2 = erl_iolist_length(P, [42, [], 45]), + + ?line 3 = erl_iolist_length(P, [42, [90], 45]), + ?line 3 = erl_iolist_length(P, [[42, [90]], 45]), + ?line 3 = erl_iolist_length(P, [[42, [90]], 45]), + + %% List with binaries. + + ?line 0 = erl_iolist_length(P, [list_to_binary([])]), + ?line 0 = erl_iolist_length(P, [[], list_to_binary([])]), + ?line 1 = erl_iolist_length(P, [[1], list_to_binary([])]), + ?line 1 = erl_iolist_length(P, [[], list_to_binary([2])]), + ?line 2 = erl_iolist_length(P, [[42], list_to_binary([2])]), + ?line 4 = erl_iolist_length(P, [[42], list_to_binary([2, 3, 4])]), + + %% Binaries as tail. + + ?line 0 = erl_iolist_length(P, [[]| list_to_binary([])]), + ?line 1 = erl_iolist_length(P, [[1]| list_to_binary([])]), + ?line 1 = erl_iolist_length(P, [[]| list_to_binary([2])]), + ?line 2 = erl_iolist_length(P, [[42]| list_to_binary([2])]), + + %% Binaries only. + + ?line 0 = erl_iolist_length(P, list_to_binary("")), + ?line 1 = erl_iolist_length(P, list_to_binary([1])), + ?line 2 = erl_iolist_length(P, list_to_binary([1, 2])), + + %% Illegal cases. + + ?line -1 = erl_iolist_length(P, [42|43]), + ?line -1 = erl_iolist_length(P, a), + + ?line -1 = erl_iolist_length(P, [a]), + ?line -1 = erl_iolist_length(P, [256]), + ?line -1 = erl_iolist_length(P, [257]), + ?line -1 = erl_iolist_length(P, [-1]), + ?line -1 = erl_iolist_length(P, [-2]), + ?line -1 = erl_iolist_length(P, [-127]), + ?line -1 = erl_iolist_length(P, [-128]), + + ?line runner:finish(P), + ok. + +%% Invokes the erl_iolist_length() function. + +erl_iolist_length(Port, List) -> + call_erl_function(Port, List). + +%% Tests the erl_iolist_to_binary() function. + +t_erl_iolist_to_binary(suite) -> []; +t_erl_iolist_to_binary(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_iolist_to_binary), + + %% Flat lists. + + ?line [] = iolist_to_list(P, []), + ?line [10] = iolist_to_list(P, [10]), + ?line [10, 20] = iolist_to_list(P, [10, 20]), + ?line [10, 20, 30] = iolist_to_list(P, [10, 20, 30]), + ?line AllBytes = lists:seq(0, 255), + ?line AllBytes = iolist_to_list(P, AllBytes), + + %% Deep lists. + + ?line [] = iolist_to_list(P, [[]]), + ?line [42] = iolist_to_list(P, [[], 42]), + ?line [42] = iolist_to_list(P, [42, []]), + ?line [42, 45] = iolist_to_list(P, [42, [], 45]), + + ?line [42, 90, 45] = iolist_to_list(P, [42, [90], 45]), + ?line [42, 90, 45] = iolist_to_list(P, [[42, [90]], 45]), + ?line [42, 90, 45] = iolist_to_list(P, [[42, [90]], 45]), + + %% List with binaries. + + ?line [] = iolist_to_list(P, [list_to_binary([])]), + ?line [] = iolist_to_list(P, [[], list_to_binary([])]), + ?line [1] = iolist_to_list(P, [[1], list_to_binary([])]), + ?line [2] = iolist_to_list(P, [[], list_to_binary([2])]), + ?line [42, 2] = iolist_to_list(P, [[42], list_to_binary([2])]), + ?line [42, 2, 3, 4] = iolist_to_list(P, [[42], list_to_binary([2, 3, 4])]), + + %% Binaries as tail. + + ?line [] = iolist_to_list(P, [[]| list_to_binary([])]), + ?line [1] = iolist_to_list(P, [[1]| list_to_binary([])]), + ?line [2] = iolist_to_list(P, [[]| list_to_binary([2])]), + ?line [42, 2] = iolist_to_list(P, [[42]| list_to_binary([2])]), + + %% Binaries only. + + ?line [] = iolist_to_list(P, list_to_binary("")), + ?line [1] = iolist_to_list(P, list_to_binary([1])), + ?line [1, 2] = iolist_to_list(P, list_to_binary([1, 2])), + + %% Illegal cases. + + ?line 'NULL' = iolist_to_list(P, [42|43]), + ?line 'NULL' = iolist_to_list(P, a), + + ?line 'NULL' = iolist_to_list(P, [a]), + ?line 'NULL' = iolist_to_list(P, [256]), + ?line 'NULL' = iolist_to_list(P, [257]), + ?line 'NULL' = iolist_to_list(P, [-1]), + ?line 'NULL' = iolist_to_list(P, [-2]), + ?line 'NULL' = iolist_to_list(P, [-127]), + ?line 'NULL' = iolist_to_list(P, [-128]), + + ?line runner:finish(P), + ok. + +iolist_to_list(Port, Term) -> + case call_erl_function(Port, Term) of + 'NULL' -> + 'NULL'; + Bin when is_binary(Bin) -> + binary_to_list(Bin) + end. + +%% Tests the erl_iolist_to_string() function. + +t_erl_iolist_to_string(suite) -> []; +t_erl_iolist_to_string(Config) when is_list(Config) -> + ?line P = runner:start(?t_erl_iolist_to_string), + + %% Flat lists. + + ?line [0] = iolist_to_string(P, []), + ?line [10, 0] = iolist_to_string(P, [10]), + ?line [10, 20, 0] = iolist_to_string(P, [10, 20]), + ?line [10, 20, 30, 0] = iolist_to_string(P, [10, 20, 30]), + ?line AllBytes = lists:seq(1, 255)++[0], + ?line AllBytes = iolist_to_string(P, lists:seq(1, 255)), + + %% Deep lists. + + ?line [0] = iolist_to_string(P, [[]]), + ?line [42, 0] = iolist_to_string(P, [[], 42]), + ?line [42, 0] = iolist_to_string(P, [42, []]), + ?line [42, 45, 0] = iolist_to_string(P, [42, [], 45]), + + ?line [42, 90, 45, 0] = iolist_to_string(P, [42, [90], 45]), + ?line [42, 90, 45, 0] = iolist_to_string(P, [[42, [90]], 45]), + ?line [42, 90, 45, 0] = iolist_to_string(P, [[42, [90]], 45]), + + %% List with binaries. + + ?line [0] = iolist_to_string(P, [list_to_binary([])]), + ?line [0] = iolist_to_string(P, [[], list_to_binary([])]), + ?line [1, 0] = iolist_to_string(P, [[1], list_to_binary([])]), + ?line [2, 0] = iolist_to_string(P, [[], list_to_binary([2])]), + ?line [42, 2, 0] = iolist_to_string(P, [[42], list_to_binary([2])]), + ?line [42, 2, 3, 4, 0] = iolist_to_string(P, [[42], + list_to_binary([2, 3, 4])]), + + %% Binaries as tail. + + ?line [0] = iolist_to_string(P, [[]| list_to_binary([])]), + ?line [1, 0] = iolist_to_string(P, [[1]| list_to_binary([])]), + ?line [2, 0] = iolist_to_string(P, [[]| list_to_binary([2])]), + ?line [42, 2, 0] = iolist_to_string(P, [[42]| list_to_binary([2])]), + + %% Binaries only. + + ?line [0] = iolist_to_string(P, list_to_binary("")), + ?line [1, 0] = iolist_to_string(P, list_to_binary([1])), + ?line [1, 2, 0] = iolist_to_string(P, list_to_binary([1, 2])), + + %% Illegal cases. + + ?line 'NULL' = iolist_to_string(P, [0]), + ?line 'NULL' = iolist_to_string(P, [65, 0, 66]), + ?line 'NULL' = iolist_to_string(P, [65, 66, 67, 0]), + + ?line 'NULL' = iolist_to_string(P, [42|43]), + ?line 'NULL' = iolist_to_string(P, a), + + ?line 'NULL' = iolist_to_string(P, [a]), + ?line 'NULL' = iolist_to_string(P, [256]), + ?line 'NULL' = iolist_to_string(P, [257]), + ?line 'NULL' = iolist_to_string(P, [-1]), + ?line 'NULL' = iolist_to_string(P, [-2]), + ?line 'NULL' = iolist_to_string(P, [-127]), + ?line 'NULL' = iolist_to_string(P, [-128]), + + ?line runner:finish(P), + ok. + +%% Invokes the erl_iolist_to_string() function. + +iolist_to_string(Port, Term) -> + runner:send_term(Port, Term), + case get_term(Port) of + {bytes, Result} -> Result; + 'NULL' -> 'NULL' + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% +%%% 5. M i s c e l l a n o u s T e s t s +%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +erl_print_term(suite) -> []; +erl_print_term(doc) -> "Tests the erl_print_term() function"; +erl_print_term(Config) when is_list(Config) -> + ?line PrintTerm = print_term(Config), + ?line P = open_port({spawn, PrintTerm}, [stream]), + + %% Lists. + + ?line print(P, "[]", []), + ?line print(P, "[a]", [a]), + ?line print(P, "[[a]]", [[a]]), + ?line print(P, "[[]]", [[]]), + ?line print(P, "[a,b,c]", [a,b,c]), + ?line print(P, "[a,b|c]", [a,b|c]), + ?line print(P, "[a,[],c]", [a,[],c]), + ?line print(P, "[a,[1000,1],c]", [a,[1000,1],c]), + + %% Tuples. + + ?line print(P, "{}", {}), + ?line print(P, "{ok}", {ok}), + ?line print(P, "{1,2,3}", {1, 2, 3}), + + %% Pids. + + ?line {_X, Y, Z} = split_pid(self()), + ?line PidString = lists:flatten(io_lib:format("<~s.~w.~w>", + [node(), Y, Z])), + ?line print(P, PidString, self()), + + ?line unlink(P), + ?line exit(P, die), + ok. + +split_pid(Pid) when is_pid(Pid) -> + split_pid(pid_to_list(Pid), 0, []). + +split_pid([$<|Rest], Cur, Result) -> + split_pid(Rest, Cur, Result); +split_pid([Digit|Rest], Cur, Result) when $0 =< Digit, Digit =< $9 -> + split_pid(Rest, 10*Cur+Digit-$0, Result); +split_pid([$.|Rest], Cur, Result) -> + split_pid(Rest, 0, Result++[Cur]); +split_pid([$>], Cur, Result) -> + list_to_tuple(Result++[Cur]). + +print_string(suite) -> []; +print_string(doc) -> "Test printing a string with erl_print_term()"; +print_string(Config) when is_list(Config) -> + ?line PrintTerm = print_term(Config), + ?line P = open_port({spawn, PrintTerm}, [stream]), + + %% Strings. + + ?line print(P, "\"ABC\"", "ABC"), + ?line {11, "\"\\tABC\\r\\n\""} = print(P, "\tABC\r\n"), + + %% Not strings. + + ?line print(P, "[65,66,67,0]", "ABC\000"), + + ?line unlink(P), + ?line exit(P, die), + ok. + +print(Port, TermString, Term) -> + Length = length(TermString), + {Length, TermString} = print(Port, Term). + +%% This function uses the erl_print_term() function in erl_interface +%% to print a term. +%% Returns: {NumChars, Chars} + +print(Port, Term) -> + Bin = term_to_binary(Term), + Size = size(Bin), + Port ! {self(), {command, [Size div 256, Size rem 256, Bin]}}, + collect_line(Port, []). + +collect_line(Port, Result) -> + receive + {Port, {data, Data}} -> + case lists:reverse(Data) of + [$\n|Rest] -> + collect_line1(Rest++Result, []); + Chars -> + collect_line(Port, Chars++Result) + end + after test_server:seconds(5) -> + test_server:fail("No response from C program") + end. + +collect_line1([$\r|Rest], Result) -> + {list_to_integer(Result), lists:reverse(Rest)}; +collect_line1([C|Rest], Result) -> + collect_line1(Rest, [C|Result]). + +%% Test case submitted by Per Lundgren, ERV. + +high_chaparal(suite) -> []; +high_chaparal(Config) when is_list(Config) -> + ?line P = runner:start(?high_chaparal), + ?line {term, [hello, world]} = get_term(P), + ?line runner:recv_eot(P), + ok. + +%% OTP-7448 +broken_data(suite) -> []; +broken_data(Config) when is_list(Config) -> + ?line P = runner:start(?broken_data), + ?line runner:recv_eot(P), + ok. + +%% This calls a C function with one parameter and returns the result. + +call_erl_function(Port, Term) -> + runner:send_term(Port, Term), + case get_term(Port) of + {term, Result} -> Result; + 'NULL' -> 'NULL' + end. + +print_term(Config) when is_list(Config) -> + filename:join(?config(data_dir, Config), "print_term"). + + + +%%% We receive a ref from the cnode, and expect it to be a long ref. +%%% We also send a ref we created ourselves, and expect to get it +%%% back, without having been mutated into short form. We must take +%%% care then to check the actual returned ref, and not the original +%%% one, which is equal to it. +cnode_1(suite) -> []; +cnode_1(doc) -> "Tests involving cnode: sends a long ref from a cnode to us"; +cnode_1(Config) when is_list(Config) -> + ?line Cnode = filename:join(?config(data_dir, Config), "cnode"), + ?line register(mip, self()), + ?line spawn_link(?MODULE, start_cnode, [Cnode]), + ?line Ref1 = get_ref(), + io:format("Ref1 ~p~n", [Ref1]), + ?line check_ref(Ref1), + ?line Ref2 = make_ref(), + ?line receive + Pid -> Pid + end, + ?line Fun1 = fun(X) -> {Pid, X} end, % sneak in a fun test here + %?line Fun1 = {wait_with_funs, new_dist_format}, + ?line Term = {Ref2, Fun1, {1,2,3,4,5,6,7,8,9,10}}, + %% A term which will overflow the original buffer used in 'cnode'. + ?line Pid ! Term, + ?line receive + Term2 -> + io:format("received ~p~n", [Term2]), + case Term2 of + Term -> + {Ref22,_,_} = Term2, + ?line check_ref(Ref22); + X -> + test_server:fail({receive1,X}) + end + after 5000 -> + test_server:fail(receive1) + end, + ?line receive + Pid -> + ok; + Y -> + test_server:fail({receive1,Y}) + after 5000 -> + test_server:fail(receive2) + end, + ?line io:format("ref = ~p~n", [Ref1]), + ?line check_ref(Ref1), + ok. + +check_ref(Ref) -> + case bin_ext_type(Ref) of + 101 -> + test_server:fail(oldref); + 114 -> + ok; + Type -> + test_server:fail({type, Type}) + end. + +bin_ext_type(T) -> + [131, Type | _] = binary_to_list(term_to_binary(T)), + Type. + +get_ref() -> + receive + X when is_reference(X) -> + X + after 5000 -> + test_server:fail({cnode, timeout}) + end. + +start_cnode(Cnode) -> + open_port({spawn, Cnode ++ " " ++ atom_to_list(erlang:get_cookie())}, []), + rec_cnode(). + +rec_cnode() -> + receive + X -> + io:format("from cnode: ~p~n", [X]), + rec_cnode() + end. + +nc2vinfo(Pid) when is_pid(Pid) -> + ?line [_NodeStr, NumberStr, SerialStr] + = string:tokens(pid_to_list(Pid), "<.>"), + ?line Number = list_to_integer(NumberStr), + ?line Serial = list_to_integer(SerialStr), + ?line {pid, node(Pid), Number, Serial}; +nc2vinfo(Port) when is_port(Port) -> + ?line ["#Port", _NodeStr, NumberStr] + = string:tokens(erlang:port_to_list(Port), "<.>"), + ?line Number = list_to_integer(NumberStr), + ?line {port, node(Port), Number}; +nc2vinfo(Ref) when is_reference(Ref) -> + ?line ["#Ref", _NodeStr | NumStrList] + = string:tokens(erlang:ref_to_list(Ref), "<.>"), + ?line {Len, RevNumList} = lists:foldl(fun ("0", {N, []}) -> + {N+1, []}; + (IStr, {N, Is}) -> + {N+1, + [list_to_integer(IStr)|Is]} + end, + {0, []}, + NumStrList), + ?line {ref, node(Ref), Len, lists:reverse(RevNumList)}; +nc2vinfo(Other) -> + ?line {badarg, Other}. + + diff --git a/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.first b/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.first new file mode 100644 index 0000000000..0f25fcc0a9 --- /dev/null +++ b/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.first @@ -0,0 +1,21 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2000-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +eterm_test_decl.c: eterm_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run eterm_test -s erlang halt diff --git a/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.src new file mode 100644 index 0000000000..89931c7701 --- /dev/null +++ b/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.src @@ -0,0 +1,50 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1997-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBERL = $(LIBPATH)/@erl_interface_lib@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = ../all_SUITE_data/runner@obj@ \ + $(LIBERL) $(LIBEI) @erl_interface_sock_libs@ @LIBS@ \ + @erl_interface_threadlib@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data +ETERM_OBJS = eterm_test@obj@ eterm_test_decl@obj@ +CNODE_OBJS = cnode@obj@ +PRINT_OBJS = print_term@obj@ +EXE_FILES = eterm_test@exe@ print_term@exe@ cnode@exe@ + +all: $(EXE_FILES) + +eterm_test@exe@: $(ETERM_OBJS) $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(ETERM_OBJS) $(LIBFLAGS) + +cnode@exe@: $(CNODE_OBJS) $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(CNODE_OBJS) $(LIBFLAGS) + +print_term@exe@: print_term@obj@ $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(PRINT_OBJS) $(LIBFLAGS) + +clean: + $(RM) $(ETERM_OBJS) $(CNODE_OBJS) $(PRINT_OBJS) + $(RM) $(EXE_FILES) diff --git a/lib/erl_interface/test/erl_eterm_SUITE_data/cnode.c b/lib/erl_interface/test/erl_eterm_SUITE_data/cnode.c new file mode 100644 index 0000000000..133f35f4bd --- /dev/null +++ b/lib/erl_interface/test/erl_eterm_SUITE_data/cnode.c @@ -0,0 +1,166 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1999-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#include <stdlib.h> +#include <stdio.h> + +#include "ei.h" +#include "erl_interface.h" + +#define MSGSIZE 13 + +#define SELF(fd) erl_mk_pid(erl_thisnodename(),fd,0,erl_thiscreation()) + +#ifdef VXWORKS +#define MAIN cnode +#else +#define MAIN main +#endif + +/* FIXME uses mix och ei and erl_interface */ + +/* + A small cnode. + To be called from the test case erl_eterm_SUITE:cnode_1. + + 1) Set up connection to node 'test_server' on the same host. + All sends are done to a registered process named 'mip'. + 2) Create a long ref and send it. + 3) Create a pid for ourselves and send it. + 4) Receive a message. + 5) Send back the message part of the message. + 6) Send back the 'to' part of the message. + 7) Exit. +*/ + +MAIN(int argc, char **argv) + +{ + unsigned char *msgbufp; + int msgsize; + ErlMessage msg; + char msgbuf[MSGSIZE]; + char buf[100]; + char buf1[100]; + char buf2[100]; + int ix; + int s; + int fd; + char node[80]; + char server[80]; + char host[80]; + int number; + ETERM *ref, *ref1, *ref2; + + erl_init(NULL, 0); + + number = 1; + if (argc >= 2) { + s = erl_connect_init(number, argv[1], 0); + } else { + s = erl_connect_init(number, (char *) 0, 0); + } + gethostname(host, sizeof(host)); + sprintf(node, "c%d@%s", number, host); + + printf("s = %d\n", s); + + sprintf(server, "test_server@%s", host); + fd = erl_connect(server); + printf("fd = %d\n", fd); + +/* printf("dist = %d\n", erl_distversion(fd)); */ + +#if 1 + ref = erl_mk_long_ref(node, 4711, 113, 98, 0); +#else + ref = erl_mk_ref(node, 4711, 0); +#endif + printf("ref = %d\n", ref); + + s = erl_reg_send(fd, "mip", ref); + printf("s = %d\n", s); + + { + ETERM* emsg; + emsg = SELF(fd); + erl_reg_send(fd,"mip",emsg); + erl_free_term(emsg); + } + + msgsize = 4; + msgbufp = (unsigned char *) malloc(msgsize); + + do { +#if 0 + s = erl_receive_msg(fd, msgbuf, MSGSIZE, &msg); +#else + s = erl_xreceive_msg(fd, &msgbufp, &msgsize, &msg); +#endif + switch (s) { + case ERL_TICK: + printf("tick\n"); + break; + case ERL_ERROR: + printf("error\n"); + break; + case ERL_MSG: + printf("msg %d\n", msgsize); + break; + default: + printf("unknown result %d\n", s); + break; + } + } while (s == ERL_TICK); + + s = erl_reg_send(fd, "mip", msg.msg); + printf("s = %d\n", s); + s = erl_reg_send(fd, "mip", msg.to); + printf("s = %d\n", s); +#if 0 + /* from = NULL! */ + s = erl_reg_send(fd, "mip", msg.from); + printf("s = %d\n", s); +#endif + +#if 0 + /* Unused code which tests refs in some ways. */ + ix = 0; + s = ei_encode_term(buf, &ix, ref); + printf ("ei encode = %d, ix = %d\n", s, ix); + + /* Compare old and new ref equal */ + ref1 = erl_mk_long_ref(node, 4711, 113, 98, 0); + ref2 = erl_mk_ref(node, 4711, 0); + s = erl_encode(ref1, buf1); + printf("enc1 s = %d\n", s); + s = erl_encode(ref2, buf2); + printf("enc2 s = %d\n", s); + s = erl_compare_ext(buf1, buf2); + printf("comp s = %d\n", s); + + /* Compare, in another way */ + s = erl_match(ref1, ref2); + printf("match s = %d\n", s); +#endif + + erl_close_connection(fd); + + return 0; +} diff --git a/lib/erl_interface/test/erl_eterm_SUITE_data/eterm_test.c b/lib/erl_interface/test/erl_eterm_SUITE_data/eterm_test.c new file mode 100644 index 0000000000..6b2ec8f766 --- /dev/null +++ b/lib/erl_interface/test/erl_eterm_SUITE_data/eterm_test.c @@ -0,0 +1,1511 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1997-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* + * Purpose: Tests the functions in erl_eterm.c and erl_malloc.c. + * Author: Bjorn Gustavsson + * + * See the erl_eterm_SUITE.erl file for a "table of contents". + */ + +#include <stdio.h> +#include <string.h> + +#include "runner.h" + +/* + * Find out which version of erl_interface we are using. + */ + +#ifdef ERL_IS_STRING +#undef NEW_ERL_INTERFACE +#else +#define NEW_ERL_INTERFACE +#endif + +void dump_term (FILE *fp, ETERM *t); + +static ETERM* all_types(); + +/*********************************************************************** + * + * 1. B a s i c t e s t s + * + ***********************************************************************/ + +/* + * Sends a list contaning all data types to the Erlang side. + */ + +TESTCASE(build_terms) +{ + ETERM* t; + + erl_init(NULL, 0); + t = all_types(); + send_term(t); + report(1); +} + +/* + * Converts an Erlang term to the external term format and back again. + */ + +TESTCASE(round_trip_conversion) +{ + ETERM* original; + ETERM* new_terms; + char encoded[16*1024]; + int n; + + erl_init(NULL, 0); + original = all_types(); + if (erl_encode(original, encoded) == 0) + { + fail("failed to encode terms"); + } else if ((new_terms = erl_decode(encoded)) == NULL) + { + fail("failed to decode terms"); + } else if (!erl_match(original, new_terms)) + { + fail("decoded terms didn't match original"); + } + + erl_free_term(original); + erl_free_term(new_terms); + report(1); +} + +/* + * Decodes data from the Erlang side and verifies. + */ + +TESTCASE(decode_terms) +{ + ETERM* terms; + char* message; + + erl_init(NULL, 0); + terms = get_term(); + if (terms == NULL) { + fail("unexpected end of file"); + } else { + ETERM* all; + ETERM* p; + ETERM* t; + int i; + + all = p = all_types(); + t = terms; + + /* + * XXX For now, skip the reference, pid, and port, because + * the match will fail. Must write code here to do some other + * validating. + */ + + for (i=0; i<6; i++) { + + p = erl_tl(p); + t = erl_tl(t); + erl_free_term(p); + erl_free_term(t); + + } + + /* + * Match the tail of the lists. + */ + + if (!erl_match(p, t)) + { + fail("Received terms didn't match expected"); + } + erl_free_term(all); + erl_free_term(terms); + report(1); + } +} + +/* + * Decodes a float from the Erlang side and verifies. + */ + +TESTCASE(decode_float) +{ + ETERM* afnum; + ETERM* efnum; + int result; + + erl_init(NULL, 0); + afnum = get_term(); + efnum = erl_mk_float(3.1415); + result = erl_match(efnum, afnum); + erl_free_term(afnum); + erl_free_term(efnum); + report(result); +} + +/* + * Tests the erl_free_compound() function. + */ + +TESTCASE(t_erl_free_compound) +{ + ETERM* t; + + erl_init(NULL, 0); + + t = all_types(); + erl_free_compound(t); + report(1); +} + + +/*********************************************************************** + * + * 2. C o n s t r u c t i n g t e r m s + * + ***********************************************************************/ + +/* + * Makes various integers, and sends them to Erlang for verification. + */ + +TESTCASE(t_erl_mk_int) +{ +#define SEND_INT(i) \ + do { \ + ETERM* t = erl_mk_int(i); \ + send_term(t); \ + } while (0); + + erl_init(NULL, 0); + + SEND_INT(0); + SEND_INT(127); + SEND_INT(128); + SEND_INT(255); + SEND_INT(256); + + SEND_INT(0xFFFF); + SEND_INT(0x10000); + + SEND_INT(0x07FFFFFF); + SEND_INT(0x0FFFFFFF); + SEND_INT(0x1FFFFFFF); + SEND_INT(0x3FFFFFFF); + SEND_INT(0x7FFFFFFF); + + SEND_INT(0x08000000); + SEND_INT(0x10000000); + SEND_INT(0x20000000); + SEND_INT(0x40000000); + + SEND_INT(-0x07FFFFFF); + SEND_INT(-0x0FFFFFFF); + SEND_INT(-0x1FFFFFFF); + SEND_INT(-0x3FFFFFFF); + SEND_INT(-0x7FFFFFFF); + + SEND_INT(-0x08000000); + SEND_INT(-0x10000000); + SEND_INT(-0x20000000); + SEND_INT(-0x40000000); + + SEND_INT(-0x08000001); + SEND_INT(-0x10000001); + SEND_INT(-0x20000001); + SEND_INT(-0x40000001); + + SEND_INT(-0x08000002); + SEND_INT(-0x10000002); + SEND_INT(-0x20000002); + SEND_INT(-0x40000002); + + SEND_INT(-1999999999); + SEND_INT(-2000000000); + SEND_INT(-2000000001); + + report(1); +} + + +/* + * Makes lists of various sizes, and sends them to Erlang for verification. + */ + +TESTCASE(t_erl_mk_list) +{ + ETERM* a[4]; + + erl_init(NULL, 0); + + /* + * Empty list. + */ + + send_term(erl_mk_list(a, 0)); + + /* + * One element: [abc] + */ + + a[0] = erl_mk_atom("abc"); + send_term(erl_mk_list(a, 1)); + erl_free_term(a[0]); + + /* + * Two elements: [abcdef, 42]. + */ + + a[0] = erl_mk_atom("abcdef"); + a[1] = erl_mk_int(42); + send_term(erl_mk_list(a, 2)); + erl_free_term(a[0]); + erl_free_term(a[1]); + + /* + * Four elements. + */ + + a[0] = erl_mk_float(0.0); + a[1] = erl_mk_int(23); + a[2] = erl_mk_empty_list(); + a[3] = erl_mk_float(3.1415); + send_term(erl_mk_list(a, 4)); + erl_free_term(a[0]); + erl_free_term(a[1]); + erl_free_term(a[2]); + erl_free_term(a[3]); + + report(1); +} + +/* + * A basic test of erl_copy_term(). + */ + +TESTCASE(basic_copy) +{ + ETERM* original; + ETERM* copy; + int result; + + erl_init(NULL, 0); + original = all_types(); + copy = erl_copy_term(original); + if (copy == NULL) { + fail("erl_copy_term() failed"); + } else if (!erl_match(original, copy)) + { + fail("copy doesn't match original"); + } + + erl_free_term(original); + erl_free_term(copy); + report(1); +} + + +/* + * A basic test of erl_mk_atom(). + */ + +TESTCASE(t_erl_mk_atom) +{ + erl_init(NULL, 0); + + send_term(erl_mk_atom("madonna")); + send_term(erl_mk_atom("Madonna")); + send_term(erl_mk_atom("mad donna")); + send_term(erl_mk_atom("_madonna_")); + send_term(erl_mk_atom("/home/madonna/tour_plan")); + send_term(erl_mk_atom("http://www.madonna.com/tour_plan")); + send_term(erl_mk_atom("\'madonna\'")); + send_term(erl_mk_atom("\"madonna\"")); + send_term(erl_mk_atom("\\madonna\\")); + send_term(erl_mk_atom("{madonna,21,'mad donna',12}")); + + report(1); +} + + +/* + * A basic test of erl_mk_binary(). + */ + +TESTCASE(t_erl_mk_binary) +{ + + char* string; + erl_init(NULL, 0); + + string = "{madonna,21,'mad donna',1234.567.890, !#$%&/()=?+-@, \" \\}"; + send_term(erl_mk_binary(string,strlen(string))); + + report(1); +} + + +/* + * A basic test of erl_mk_empty_list(). + */ + +TESTCASE(t_erl_mk_empty_list) +{ + erl_init(NULL, 0); + + send_term(erl_mk_empty_list()); + report(1); +} + + +/* + * A basic test of erl_mk_float(). + */ + +TESTCASE(t_erl_mk_float) +{ + ETERM* arr[6]; + ETERM* emsg; + + erl_init(NULL, 0); + + arr[0] = erl_mk_float(3.1415); + arr[1] = erl_mk_float(1.999999); + arr[2] = erl_mk_float(2.000000); + arr[3] = erl_mk_float(2.000001); + arr[4] = erl_mk_float(2.000002); + arr[5] = erl_mk_float(12345.67890); + emsg = (erl_mk_tuple(arr,6)); + + send_term(emsg); + + erl_free_array(arr,6); + /* emsg already freed by send_term() */ + /* erl_free_term(emsg); */ + + report(1); +} + + +/* + * A basic test of erl_mk_pid(). + */ + +TESTCASE(t_erl_mk_pid) +{ + erl_init(NULL, 0); + + send_term(erl_mk_pid("kalle@localhost", 3, 2, 1)); + report(1); +} + +/* + * A basic test of erl_mk_pid(). + */ + +TESTCASE(t_erl_mk_xpid) +{ + erl_init(NULL, 0); + + send_term(erl_mk_pid("kalle@localhost", 32767, 8191, 1)); + report(1); +} + + +/* + * A basic test of erl_mk_port(). + */ + +TESTCASE(t_erl_mk_port) +{ + erl_init(NULL, 0); + + send_term(erl_mk_port("kalle@localhost", 4, 1)); + report(1); +} + +/* + * A basic test of erl_mk_port(). + */ + +TESTCASE(t_erl_mk_xport) +{ + erl_init(NULL, 0); + + send_term(erl_mk_port("kalle@localhost", 268435455, 1)); + report(1); +} + +/* + * A basic test of erl_mk_ref(). + */ + +TESTCASE(t_erl_mk_ref) +{ + erl_init(NULL, 0); + + send_term(erl_mk_ref("kalle@localhost", 6, 1)); + report(1); +} + +/* + * A basic test of erl_mk_long_ref(). + */ + + +TESTCASE(t_erl_mk_long_ref) +{ + erl_init(NULL, 0); + + send_term(erl_mk_long_ref("kalle@localhost", + 4294967295, 4294967295, 262143, + 1)); + report(1); +} + + +/* + * A basic test of erl_mk_string(). + */ + +TESTCASE(t_erl_mk_string) +{ + + erl_init(NULL, 0); + + send_term(erl_mk_string("madonna")); + send_term(erl_mk_string("Madonna")); + send_term(erl_mk_string("mad donna")); + send_term(erl_mk_string("_madonna_")); + send_term(erl_mk_string("/home/madonna/tour_plan")); + send_term(erl_mk_string("http://www.madonna.com/tour_plan")); + send_term(erl_mk_string("\'madonna\'")); + send_term(erl_mk_string("\"madonna\"")); + send_term(erl_mk_string("\\madonna\\")); + send_term(erl_mk_string("{madonna,21,'mad donna',12}")); + + report(1); +} + + +/* + * A basic test of erl_mk_estring(). + */ + +TESTCASE(t_erl_mk_estring) +{ + char* string; + erl_init(NULL, 0); + + string = "madonna"; + send_term(erl_mk_estring(string,strlen(string))); + string = "Madonna"; + send_term(erl_mk_estring(string,strlen(string))); + string = "mad donna"; + send_term(erl_mk_estring(string,strlen(string))); + string = "_madonna_"; + send_term(erl_mk_estring(string,strlen(string))); + string = "/home/madonna/tour_plan"; + send_term(erl_mk_estring(string,strlen(string))); + string = "http://www.madonna.com/tour_plan"; + send_term(erl_mk_estring(string,strlen(string))); + string = "\'madonna\'"; + send_term(erl_mk_estring(string,strlen(string))); + string = "\"madonna\""; + send_term(erl_mk_estring(string,strlen(string))); + string = "\\madonna\\"; + send_term(erl_mk_estring(string,strlen(string))); + string = "{madonna,21,'mad donna',12}"; + send_term(erl_mk_estring(string,strlen(string))); + + report(1); +} + + +/* + * A basic test of erl_mk_tuple(). + */ + +TESTCASE(t_erl_mk_tuple) +{ + ETERM* arr[4]; + ETERM* arr2[2]; + ETERM* arr3[2]; + ETERM* arr4[2]; + + erl_init(NULL, 0); + + /* {madonna,21,'mad donna',12} */ + arr[0] = erl_mk_atom("madonna"); + arr[1] = erl_mk_int(21); + arr[2] = erl_mk_atom("mad donna"); + arr[3] = erl_mk_int(12); + + send_term(erl_mk_tuple(arr,4)); + + erl_free_array(arr,4); + + + /* {'Madonna',21,{children,{"Isabella",2}},{'home page',"http://www.madonna.com/"} */ + arr4[0] = erl_mk_atom("home page"); + arr4[1] = erl_mk_string("http://www.madonna.com/"); + + arr3[0] = erl_mk_string("Isabella"); + arr3[1] = erl_mk_int(2); + + arr2[0] = erl_mk_atom("children"); + arr2[1] = erl_mk_tuple(arr3,2); + + arr[0] = erl_mk_atom("Madonna"); + arr[1] = erl_mk_int(21); + arr[2] = erl_mk_tuple(arr2,2); + arr[3] = erl_mk_tuple(arr4,2); + + send_term(erl_mk_tuple(arr,4)); + + erl_free_array(arr,4); + erl_free_array(arr2,2); + erl_free_array(arr3,2); + erl_free_array(arr4,2); + + + report(1); +} + + +/* + * A basic test of erl_mk_uint(). + */ + +TESTCASE(t_erl_mk_uint) +{ + unsigned i; + + erl_init(NULL, 0); + + send_term(erl_mk_uint(54321)); + i = 2147483647; + send_term(erl_mk_uint(i)); + send_term(erl_mk_uint(i+1)); + send_term(erl_mk_uint(i+2)); + send_term(erl_mk_uint(i+3)); + send_term(erl_mk_uint(i+i+1)); + + report(1); +} + + +/* + * A basic test of erl_mk_var(). + */ + +TESTCASE(t_erl_mk_var) +{ + ETERM* mk_var; + ETERM* term; + ETERM* term2; + ETERM* arr[4]; + ETERM* arr_term[2]; + ETERM* mk_var_tuple; + ETERM* term_tuple; + + erl_init(NULL, 0); + + + /* match unbound/bound variable against an integer */ + term = erl_mk_int(17); + term2 = erl_mk_int(2); + mk_var = erl_mk_var("New_var"); + send_term(erl_mk_int(erl_match(mk_var, term))); /* should be ok */ + send_term(erl_mk_int(erl_match(mk_var, term2))); /* should fail */ + send_term(erl_mk_int(erl_match(mk_var, term))); /* should be ok */ + send_term(erl_mk_int(erl_match(mk_var, term2))); /* should fail */ + erl_free_term(mk_var); + erl_free_term(term); + erl_free_term(term2); + + /* match unbound variable against a tuple */ + arr[0] = erl_mk_atom("madonna"); + arr[1] = erl_mk_int(21); + arr[2] = erl_mk_atom("mad donna"); + arr[3] = erl_mk_int(12); + mk_var = erl_mk_var("New_var"); + term = erl_mk_tuple(arr,4); + send_term(erl_mk_int(erl_match(mk_var, term))); /* should be ok */ + erl_free_term(mk_var); + erl_free_term(term); + erl_free_array(arr,4); + + + /* match (twice) unbound variable against an incorrect tuple */ + arr[0] = erl_mk_var("New_var"); + arr[1] = erl_mk_var("New_var"); + arr_term[0] = erl_mk_int(17); + arr_term[1] = erl_mk_int(27); + mk_var_tuple = erl_mk_tuple(arr,2); + term_tuple = erl_mk_tuple(arr_term,2); + send_term(erl_mk_int(erl_match(mk_var_tuple, term_tuple))); /* should fail */ + erl_free_array(arr,2); + erl_free_array(arr_term,2); + erl_free_term(mk_var_tuple); + erl_free_term(term_tuple); + + + /* match (twice) unbound variable against a correct tuple */ + arr[0] = erl_mk_var("New_var"); + arr[1] = erl_mk_var("New_var"); + arr_term[0] = erl_mk_int(17); + arr_term[1] = erl_mk_int(17); + mk_var_tuple = erl_mk_tuple(arr,2); + term_tuple = erl_mk_tuple(arr_term,2); + send_term(erl_mk_int(erl_match(mk_var_tuple, term_tuple))); /* should be ok */ + erl_free_array(arr,2); + erl_free_array(arr_term,2); + erl_free_term(mk_var_tuple); + erl_free_term(term_tuple); + + report(1); +} + + +/* + * A basic test of erl_size(). + */ + +TESTCASE(t_erl_size) +{ + ETERM* arr[4]; + ETERM* tuple; + ETERM* bin; + char* string; + + erl_init(NULL, 0); + + /* size of a tuple */ + tuple = erl_format("{}"); + send_term(erl_mk_int(erl_size(tuple))); + erl_free_term(tuple); + + arr[0] = erl_mk_atom("madonna"); + arr[1] = erl_mk_int(21); + arr[2] = erl_mk_atom("mad donna"); + arr[3] = erl_mk_int(12); + tuple = erl_mk_tuple(arr,4); + + send_term(erl_mk_int(erl_size(tuple))); + + erl_free_array(arr,4); + erl_free_term(tuple); + + /* size of a binary */ + string = ""; + bin = erl_mk_binary(string,strlen(string)); + send_term(erl_mk_int(erl_size(bin))); + erl_free_term(bin); + + string = "{madonna,21,'mad donna',12}"; + bin = erl_mk_binary(string,strlen(string)); + send_term(erl_mk_int(erl_size(bin))); + erl_free_term(bin); + + report(1); +} + + +/* + * A basic test of erl_var_content(). + */ + +TESTCASE(t_erl_var_content) +{ + ETERM* mk_var; + ETERM* term; + ETERM* tuple; + ETERM* list; + ETERM* a; + ETERM* b; + ETERM* arr[4]; + ETERM* arr2[2]; + ETERM* arr3[2]; + ETERM* arr4[2]; + + erl_init(NULL, 0); + + term = erl_mk_int(17); + mk_var = erl_mk_var("Var"); + + /* unbound, should return NULL */ + if (erl_var_content(mk_var,"Var") != NULL) + fail("t_erl_var_content() failed"); + + erl_match(mk_var, term); + send_term(erl_var_content(mk_var,"Var")); /* should return 17 */ + + /* integer, should return NULL */ + if (erl_var_content(term,"Var") != NULL) + fail("t_erl_var_content() failed"); + + /* unknown variable, should return NULL */ + if (erl_var_content(mk_var,"Unknown_Var") != NULL) + fail("t_erl_var_content() failed"); + + erl_free_term(mk_var); + erl_free_term(term); + + /* {'Madonna',21,{children,{"Name","Age"}},{"Home_page","Tel_no"}} */ + arr4[0] = erl_mk_var("Home_page"); + arr4[1] = erl_mk_var("Tel_no"); + a = erl_mk_string("http://www.madonna.com"); + erl_match(arr4[0], a); + + arr3[0] = erl_mk_var("Name"); + arr3[1] = erl_mk_var("Age"); + b = erl_mk_int(2); + erl_match(arr3[1], b); + + arr2[0] = erl_mk_atom("children"); + arr2[1] = erl_mk_tuple(arr3,2); + + arr[0] = erl_mk_atom("Madonna"); + arr[1] = erl_mk_int(21); + arr[2] = erl_mk_tuple(arr2,2); + arr[3] = erl_mk_tuple(arr4,2); + + tuple = erl_mk_tuple(arr,4); + + /* should return "http://www.madonna.com" */ + send_term(erl_var_content(tuple,"Home_page")); + + /* unbound, should return NULL */ + if (erl_var_content(tuple,"Tel_no") != NULL) + fail("t_erl_var_content() failed"); + + /* unbound, should return NULL */ + if (erl_var_content(tuple,"Name") != NULL) + fail("t_erl_var_content() failed"); + + /* should return 2 */ + send_term(erl_var_content(tuple,"Age")); + + erl_free_array(arr,4); + erl_free_array(arr2,2); + erl_free_array(arr3,2); + erl_free_array(arr4,2); + erl_free_term(tuple); + erl_free_term(a); + erl_free_term(b); + + + /* [] */ + list = erl_mk_empty_list(); + if (erl_var_content(list,"Tel_no") != NULL) + fail("t_erl_var_content() failed"); + erl_free_term(list); + + + /* ['Madonna',[],{children,{"Name","Age"}},{"Home_page","Tel_no"}] */ + arr4[0] = erl_mk_var("Home_page"); + arr4[1] = erl_mk_var("Tel_no"); + a = erl_mk_string("http://www.madonna.com"); + erl_match(arr4[0], a); + + arr3[0] = erl_mk_var("Name"); + arr3[1] = erl_mk_var("Age"); + b = erl_mk_int(2); + erl_match(arr3[1], b); + + arr2[0] = erl_mk_atom("children"); + arr2[1] = erl_mk_tuple(arr3,2); + + arr[0] = erl_mk_atom("Madonna"); + arr[1] = erl_mk_empty_list(); + arr[2] = erl_mk_tuple(arr2,2); + arr[3] = erl_mk_tuple(arr4,2); + + list = erl_mk_list(arr,4); + + /* should return "http://www.madonna.com" */ + send_term(erl_var_content(list,"Home_page")); + + /* unbound, should return NULL */ + if (erl_var_content(list,"Tel_no") != NULL) + fail("t_erl_var_content() failed"); + + /* unbound, should return NULL */ + if (erl_var_content(list,"Name") != NULL) + fail("t_erl_var_content() failed"); + + /* should return 2 */ + send_term(erl_var_content(list,"Age")); + + erl_free_array(arr,4); + erl_free_array(arr2,2); + erl_free_array(arr3,2); + erl_free_array(arr4,2); + erl_free_term(list); + erl_free_term(a); + erl_free_term(b); + + report(1); +} + + +/* + * A basic test of erl_element(). + */ + +TESTCASE(t_erl_element) +{ + ETERM* arr[4]; + ETERM* arr2[2]; + ETERM* arr3[2]; + ETERM* arr4[2]; + ETERM* tuple; + + erl_init(NULL, 0); + + arr[0] = erl_mk_atom("madonna"); + arr[1] = erl_mk_int(21); + arr[2] = erl_mk_atom("mad donna"); + arr[3] = erl_mk_int(12); + tuple = erl_mk_tuple(arr,4); + + send_term(erl_element(1,tuple)); + send_term(erl_element(2,tuple)); + send_term(erl_element(3,tuple)); + send_term(erl_element(4,tuple)); + + erl_free_array(arr,4); + erl_free_term(tuple); + + /* {'Madonna',21,{children,{"Isabella",2}},{'home page',"http://www.madonna.com/"} */ + arr4[0] = erl_mk_atom("home page"); + arr4[1] = erl_mk_string("http://www.madonna.com/"); + + arr3[0] = erl_mk_string("Isabella"); + arr3[1] = erl_mk_int(2); + + arr2[0] = erl_mk_atom("children"); + arr2[1] = erl_mk_tuple(arr3,2); + + arr[0] = erl_mk_atom("Madonna"); + arr[1] = erl_mk_int(21); + arr[2] = erl_mk_tuple(arr2,2); + arr[3] = erl_mk_tuple(arr4,2); + + tuple = erl_mk_tuple(arr,4); + send_term(erl_element(1,tuple)); + send_term(erl_element(2,tuple)); + send_term(erl_element(3,tuple)); + send_term(erl_element(4,tuple)); + + erl_free_term(tuple); + erl_free_array(arr,4); + erl_free_array(arr2,2); + erl_free_array(arr3,2); + erl_free_array(arr4,2); + + report(1); +} + + +/* + * A basic test of erl_cons(). + */ + +TESTCASE(t_erl_cons) +{ + ETERM* list; + ETERM* anAtom; + ETERM* anInt; + + erl_init(NULL, 0); + + anAtom = erl_mk_atom("madonna"); + anInt = erl_mk_int(21); + list = erl_mk_empty_list(); + list = erl_cons(anInt, list); + send_term(erl_cons(anAtom, list)); + + erl_free_term(anAtom); + erl_free_term(anInt); + erl_free_compound(list); + + report(1); +} + + + + +/*********************************************************************** + * + * 3. E x t r a c t i n g & i n f o f u n c t i o n s + * + ***********************************************************************/ + +/* + * Calculates the length of each list sent to it and sends back the result. + */ + +TESTCASE(t_erl_length) +{ + erl_init(NULL, 0); + + for (;;) { + ETERM* term = get_term(); + + if (term == NULL) { + report(1); + return; + } else { + ETERM* len_term; + + len_term = erl_mk_int(erl_length(term)); + erl_free_term(term); + send_term(len_term); + } + } +} + +/* + * Gets the head of each term and sends the result back. + */ + +TESTCASE(t_erl_hd) +{ + erl_init(NULL, 0); + + for (;;) { + ETERM* term = get_term(); + + if (term == NULL) { + report(1); + return; + } else { + ETERM* head; + + head = erl_hd(term); + send_term(head); + erl_free_term(term); + } + } +} + +/* + * Gets the tail of each term and sends the result back. + */ + +TESTCASE(t_erl_tl) +{ + erl_init(NULL, 0); + + for (;;) { + ETERM* term = get_term(); + + if (term == NULL) { + report(1); + return; + } else { + ETERM* tail; + + tail = erl_tl(term); + send_term(tail); + erl_free_term(term); + } + } +} + +/* + * Checks the type checking macros. + */ + +TESTCASE(type_checks) +{ + ETERM* t; + ETERM* atom; + + erl_init(NULL, 0); + atom = erl_mk_atom("an_atom"); + +#define TYPE_CHECK(macro, term) \ + { ETERM* t = term; \ + if (macro(t)) { \ + erl_free_term(t); \ + } else { \ + fail("Macro " #macro " failed on " #term); \ + } \ + } + + TYPE_CHECK(ERL_IS_INTEGER, erl_mk_int(0x7FFFFFFF)); +#ifdef NEW_ERL_INTERFACE + TYPE_CHECK(ERL_IS_UNSIGNED_INTEGER, erl_mk_uint(0x7FFFFFFF)); +#endif + TYPE_CHECK(ERL_IS_FLOAT, erl_mk_float(5.5)); + TYPE_CHECK(ERL_IS_ATOM, erl_mk_atom("another_atom")); + + TYPE_CHECK(ERL_IS_EMPTY_LIST, erl_mk_empty_list()); + TYPE_CHECK(!ERL_IS_EMPTY_LIST, erl_cons(atom, atom)); + +#ifdef NEW_ERL_INTERFACE + TYPE_CHECK(!ERL_IS_CONS, erl_mk_empty_list()); + TYPE_CHECK(ERL_IS_CONS, erl_cons(atom, atom)); +#endif + + TYPE_CHECK(ERL_IS_LIST, erl_mk_empty_list()); + TYPE_CHECK(ERL_IS_LIST, erl_cons(atom, atom)); + + TYPE_CHECK(ERL_IS_PID, erl_mk_pid("a@a", 42, 1, 1)); + TYPE_CHECK(ERL_IS_PORT, erl_mk_port("a@a", 42, 1)); + TYPE_CHECK(ERL_IS_REF, erl_mk_ref("a@a", 42, 1)); + + TYPE_CHECK(ERL_IS_BINARY, erl_mk_binary("a", 1)); + TYPE_CHECK(ERL_IS_TUPLE, erl_mk_tuple(&atom, 1)); +#undef TYPE_CHECK + + erl_free_term(atom); + + report(1); +} + +/* + * Checks the extractor macros. + */ + +TESTCASE(extractor_macros) +{ + ETERM* t; + + erl_init(NULL, 0); + +#ifdef NEW_ERL_INTERFACE +#define MATCH(a, b) ((a) == (b) ? 1 : fail("bad match: " #a)) +#define STR_MATCH(a, b) (strcmp((a), (b)) ? fail("bad match: " #a) : 0) + + { /* Integer */ + int anInt = 0x7FFFFFFF; + t = erl_mk_int(anInt); + MATCH(ERL_INT_VALUE(t), anInt); + MATCH(ERL_INT_UVALUE(t), anInt); + erl_free_term(t); + } + + { /* Float */ + double aFloat = 3.1415; + t = erl_mk_float(aFloat); + MATCH(ERL_FLOAT_VALUE(t), aFloat); + erl_free_term(t); + } + + { /* Atom. */ + char* aString = "nisse"; + t = erl_mk_atom(aString); + if (memcmp(ERL_ATOM_PTR(t), aString, strlen(aString)) != 0) + fail("bad match"); + MATCH(ERL_ATOM_SIZE(t), strlen(aString)); + erl_free_term(t); + } + + { /* Pid. */ + char* node = "arne@strider"; + int number = 42; + int serial = 5; + int creation = 1; + + t = erl_mk_pid(node, number, serial, creation); + STR_MATCH(ERL_PID_NODE(t), node); + MATCH(ERL_PID_NUMBER(t), number); + MATCH(ERL_PID_SERIAL(t), serial); + MATCH(ERL_PID_CREATION(t), creation); + erl_free_term(t); + } + + { /* Port. */ + char* node = "kalle@strider"; + int number = 45; + int creation = 1; + + t = erl_mk_port(node, number, creation); + STR_MATCH(ERL_PORT_NODE(t), node); + MATCH(ERL_PORT_NUMBER(t), number); + MATCH(ERL_PORT_CREATION(t), creation); + erl_free_term(t); + } + + { /* Reference. */ + char* node = "kalle@strider"; + int number = 48; + int creation = 1; + + t = erl_mk_ref(node, number, creation); + STR_MATCH(ERL_REF_NODE(t), node); + MATCH(ERL_REF_NUMBER(t), number); + MATCH(ERL_REF_CREATION(t), creation); + erl_free_term(t); + } + + { /* Tuple. */ + ETERM* arr[2]; + + arr[0] = erl_mk_int(51); + arr[1] = erl_mk_int(52); + t = erl_mk_tuple(arr, ASIZE(arr)); + MATCH(ERL_TUPLE_SIZE(t), ASIZE(arr)); + MATCH(ERL_TUPLE_ELEMENT(t, 0), arr[0]); + MATCH(ERL_TUPLE_ELEMENT(t, 1), arr[1]); + erl_free_array(arr, ASIZE(arr)); + erl_free_term(t); + } + + { /* Binary. */ + static char bin[] = {1, 2, 3, 0, 4, 5}; + + t = erl_mk_binary(bin, ASIZE(bin)); + MATCH(ERL_BIN_SIZE(t), ASIZE(bin)); + if (memcmp(ERL_BIN_PTR(t), bin, ASIZE(bin)) != 0) + fail("bad match"); + erl_free_term(t); + } + + { + ETERM* head = erl_mk_atom("head"); + ETERM* tail = erl_mk_atom("tail"); + + t = erl_cons(head, tail); + MATCH(ERL_CONS_HEAD(t), head); + MATCH(ERL_CONS_TAIL(t), tail); + erl_free_term(head); + erl_free_term(tail); + erl_free_term(t); + } +#undef MATCH +#undef STR_MATCH +#endif + + report(1); +} + + + +/*********************************************************************** + * + * 4. I / O l i s t f u n c t i o n s + * + ***********************************************************************/ + +/* + * Invokes erl_iolist_length() on each term and send backs the result. + */ + +TESTCASE(t_erl_iolist_length) +{ + erl_init(NULL, 0); + + for (;;) { + ETERM* term = get_term(); + + if (term == NULL) { + report(1); + return; + } else { +#ifndef NEW_ERL_INTERFACE + fail("Function not present in this version of erl_interface"); +#else + ETERM* len_term; + + len_term = erl_mk_int(erl_iolist_length(term)); + erl_free_term(term); + send_term(len_term); +#endif + } + } +} + +/* + * Invokes erl_iolist_to_binary() on each term and send backs the result. + */ + +TESTCASE(t_erl_iolist_to_binary) +{ + erl_init(NULL, 0); + + for (;;) { + ETERM* term = get_term(); + + if (term == NULL) { + report(1); + return; + } else { +#ifndef NEW_ERL_INTERFACE + fail("Function not present in this version of erl_interface"); +#else + ETERM* new_term; + + new_term = erl_iolist_to_binary(term); + + erl_free_term(term); + send_term(new_term); +#endif + } + } +} + +/* + * Invokes erl_iolist_to_string() on each term and send backs the result. + */ + +TESTCASE(t_erl_iolist_to_string) +{ + erl_init(NULL, 0); + + for (;;) { + ETERM* term = get_term(); + + if (term == NULL) { + report(1); + return; + } else { +#ifndef NEW_ERL_INTERFACE + fail("Function not present in this version of erl_interface"); +#else + char* result; + + result = erl_iolist_to_string(term); + erl_free_term(term); + if (result != NULL) { + send_buffer(result, strlen(result)+1); + erl_free(result); + } else { + send_term(NULL); + } +#endif + } + } +} + + +/*********************************************************************** + * + * 5. M i s c e l l a n o u s T e s t s + * + ***********************************************************************/ + +/* + * Test some combinations of operations to verify that the reference pointers + * are handled correctly. + * + * "Det verkar vara lite High Chaparal med minneshanteringen i erl_interface" + * Per Lundgren, ERV. + */ + +TESTCASE(high_chaparal) +{ + ETERM *L1, *A1, *L2, *A2, *L3; + + erl_init(NULL, 0); + + L1 = erl_mk_empty_list(); + A1 = erl_mk_atom("world"); + L2 = erl_cons(A1, L1); + A2 = erl_mk_atom("hello"); + L3 = erl_cons(A2, L2); + + erl_free_term(L1); + erl_free_term(A1); + erl_free_term(L2); + erl_free_term(A2); + + send_term(L3); + + /* already freed by send_term() */ + /* erl_free_term(L3);*/ + + report(1); +} + +/* + * Test erl_decode to recover from broken list data (OTP-7448) + */ +TESTCASE(broken_data) +{ + ETERM* original; + ETERM* new_terms; + char encoded[16*1024]; + int n; + + erl_init(NULL, 0); + original = all_types(); + if ((n=erl_encode(original, encoded)) == 0) + { + fail("failed to encode terms"); + } else + { + int offs = n/2; + memset(encoded+offs,0,n-offs); /* destroy */ + + if ((new_terms = erl_decode(encoded)) != NULL) + { + fail("decode accepted broken data"); + erl_free_term(new_terms); + } + } + erl_free_term(original); + report(1); +} + +/* + * Returns a list containing instances of all types. + * + * Be careful changing the contents of the list returned, because both + * the build_terms() and decode_terms() test cases depend on it. + */ + +static ETERM* +all_types(void) +{ + ETERM* t; + ETERM* terms[3]; + int i; + static char a_binary[] = "A binary"; + +#define CONS_AND_FREE(expr, tail) \ + do { \ + ETERM* term = expr; \ + ETERM* nl = erl_cons(term, tail); \ + erl_free_term(term); \ + erl_free_term(tail); \ + tail = nl; \ + } while (0) + + t = erl_mk_empty_list(); + + CONS_AND_FREE(erl_mk_atom("I am an atom"), t); + CONS_AND_FREE(erl_mk_binary("A binary", sizeof(a_binary)-1), t); + CONS_AND_FREE(erl_mk_float(3.0), t); + CONS_AND_FREE(erl_mk_int(0), t); + CONS_AND_FREE(erl_mk_int(-1), t); + CONS_AND_FREE(erl_mk_int(1), t); + + CONS_AND_FREE(erl_mk_string("A string"), t); + + terms[0] = erl_mk_atom("element1"); + terms[1] = erl_mk_int(42); + terms[2] = erl_mk_int(767); + CONS_AND_FREE(erl_mk_tuple(terms, ASIZE(terms)), t); + for (i = 0; i < ASIZE(terms); i++) { + erl_free_term(terms[i]); + } + + CONS_AND_FREE(erl_mk_pid("kalle@localhost", 3, 2, 1), t); + CONS_AND_FREE(erl_mk_pid("abcdefghijabcdefghij@localhost", 3, 2, 1), t); + CONS_AND_FREE(erl_mk_port("kalle@localhost", 4, 1), t); + CONS_AND_FREE(erl_mk_port("abcdefghijabcdefghij@localhost", 4, 1), t); + CONS_AND_FREE(erl_mk_ref("kalle@localhost", 6, 1), t); + CONS_AND_FREE(erl_mk_ref("abcdefghijabcdefghij@localhost", 6, 1), t); + return t; + +#undef CONS_AND_FREE +} + +/* + * Dump (print for debugging) a term. Useful if/when things go wrong. + */ +void +dump_term (FILE *fp, ETERM *t) +{ + if (fp == NULL) return; + + fprintf(fp, "#<%p ", t); + + if(t != NULL) + { + fprintf(fp, "count:%d, type:%d", ERL_COUNT(t), ERL_TYPE(t)); + + switch(ERL_TYPE(t)) + { + case ERL_UNDEF: + fprintf(fp, "==undef"); + break; + case ERL_INTEGER: + fprintf(fp, "==int, val:%d", ERL_INT_VALUE(t)); + break; + case ERL_U_INTEGER: + fprintf(fp, "==uint, val:%u", ERL_INT_UVALUE(t)); + break; + case ERL_FLOAT: + fprintf(fp, "==float, val:%g", ERL_FLOAT_VALUE(t)); + break; + case ERL_ATOM: + fprintf(fp, "==atom, name:%p \"%s\"", + ERL_ATOM_PTR(t), ERL_ATOM_PTR(t)); + break; + case ERL_BINARY: + fprintf(fp, "==binary, data:%p,%u", + ERL_BIN_PTR(t), ERL_BIN_SIZE(t)); + break; + case ERL_PID: + fprintf(fp, "==pid, node:%p \"%s\"", + ERL_PID_NODE(t), ERL_PID_NODE(t)); + break; + case ERL_PORT: + fprintf(fp, "==port, node:%p \"%s\"", + ERL_PORT_NODE(t), ERL_PORT_NODE(t)); + break; + case ERL_REF: + fprintf(fp, "==ref, node:%p \"%s\"", + ERL_REF_NODE(t), ERL_REF_NODE(t)); + break; + case ERL_CONS: + fprintf(fp, "==cons"); + fprintf(fp, ", car:"); + dump_term(fp, ERL_CONS_HEAD(t)); + fprintf(fp, ", cdr:"); + dump_term(fp, ERL_CONS_TAIL(t)); + break; + case ERL_NIL: + fprintf(fp, "==nil"); + break; + case ERL_TUPLE: + fprintf(fp, "==tuple, elems:%p,%u", + ERL_TUPLE_ELEMS(t), ERL_TUPLE_SIZE(t)); + { + size_t i; + for(i = 0; i < ERL_TUPLE_SIZE(t); i++) + { + fprintf(fp, "elem[%u]:", i); + dump_term(fp, ERL_TUPLE_ELEMENT(t, i)); + } + } + break; + case ERL_VARIABLE: + fprintf(fp, "==variable, name:%p \"%s\"", + ERL_VAR_NAME(t), ERL_VAR_NAME(t)); + fprintf(fp, ", value:"); + dump_term(fp, ERL_VAR_VALUE(t)); + break; + + default: + break; + } + } + fprintf(fp, ">"); +} + diff --git a/lib/erl_interface/test/erl_eterm_SUITE_data/print_term.c b/lib/erl_interface/test/erl_eterm_SUITE_data/print_term.c new file mode 100644 index 0000000000..56e2d43d2f --- /dev/null +++ b/lib/erl_interface/test/erl_eterm_SUITE_data/print_term.c @@ -0,0 +1,129 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1997-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* + * Purpose: Test the erl_print_term() function. + * Author: Bjorn Gustavsson + */ + +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#ifndef __WIN32__ +#include <unistd.h> +#endif + +#include "erl_interface.h" + +#ifndef __WIN32__ +#define _O_BINARY 0 +#define _setmode(fd, mode) +#endif + +#define HEADER_SIZE 2 + +static int readn(int, unsigned char*, int); + +/* + * This program doesn't use the runner, because it needs a packet + * on input, but the result will be as a stream of bytes (since + * erl_print_term() prints directly on a file). + * + * Input is a package of with a packet header size of two bytes. + * + * +------------------------------------------------------------+ + * | length | Encoded term... | + * | (2 bytes) | (as given by "length") | + * +------------------------------------------------------------+ + * + * <------------------- length ---------------------> + * + * This program decodes the encoded terms and passes it to + * erl_print_term(). Then this program prints + * + * CR <result> LF + * + * and waits for a new package. <result> is the return value from + * erl_print_term(), formatted as an ASCII string. + */ + +#ifdef VXWORKS +int print_term() +#else +int main() +#endif +{ + _setmode(0, _O_BINARY); + _setmode(1, _O_BINARY); + + erl_init(NULL, 0); + + for (;;) { + char buf[4*1024]; + ETERM* term; + char* message; + int n; + + if (readn(0, buf, 2) <= 0) { + /* fprintf(stderr, "error reading message header\n"); */ + /* actually this is where we leave the infinite loop */ + exit(1); + } + n = buf[0] * 256 + buf[1]; + if (readn(0, buf, n) < 0) { + fprintf(stderr, "error reading message contents\n"); + exit(1); + } + + term = erl_decode(buf); + if (term == NULL) { + fprintf(stderr, "erl_decode() failed\n"); + exit(1); + } + n = erl_print_term(stdout, term); + erl_free_compound(term); + fprintf(stdout,"\r%d\n", n); + fflush(stdout); + } +} + +/* + * Reads len number of bytes. + */ + +static int +readn(fd, buf, len) + int fd; /* File descriptor to read from. */ + unsigned char *buf; /* Store in this buffer. */ + int len; /* Number of bytes to read. */ +{ + int n; /* Byte count in last read call. */ + int sofar = 0; /* Bytes read so far. */ + + do { + if ((n = read(fd, buf+sofar, len-sofar)) <= 0) + /* error or EOF in read */ + return(n); + sofar += n; + } while (sofar < len); + return sofar; +} + diff --git a/lib/erl_interface/test/erl_ext_SUITE.erl b/lib/erl_interface/test/erl_ext_SUITE.erl new file mode 100644 index 0000000000..dbafea0e39 --- /dev/null +++ b/lib/erl_interface/test/erl_ext_SUITE.erl @@ -0,0 +1,81 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(erl_ext_SUITE). + +-include("test_server.hrl"). +-include("erl_ext_SUITE_data/ext_test_cases.hrl"). + +-export([ + all/1, + compare_tuple/1, + compare_list/1, + compare_string/1, + compare_list_string/1, + compare_nc_ext/1 + ]). + +-import(runner, [get_term/1]). + +all(suite) -> [ + compare_tuple, + compare_list, + compare_string, + compare_list_string, + compare_nc_ext + ]. + +compare_tuple(suite) -> []; +compare_tuple(doc) -> []; +compare_tuple(Config) when is_list(Config) -> + ?line P = runner:start(?compare_tuple), + ?line runner:recv_eot(P), + ok. + +compare_list(suite) -> []; +compare_list(doc) -> []; +compare_list(Config) when is_list(Config) -> + ?line P = runner:start(?compare_list), + ?line runner:recv_eot(P), + ok. + +compare_string(suite) -> []; +compare_string(doc) -> []; +compare_string(Config) when is_list(Config) -> + ?line P = runner:start(?compare_string), + ?line runner:recv_eot(P), + ok. + +compare_list_string(suite) -> []; +compare_list_string(doc) -> []; +compare_list_string(Config) when is_list(Config) -> + ?line P = runner:start(?compare_list_string), + ?line runner:recv_eot(P), + ok. + +compare_nc_ext(suite) -> []; +compare_nc_ext(doc) -> []; +compare_nc_ext(Config) when is_list(Config) -> + ?line P = runner:start(?compare_nc_ext), + ?line runner:recv_eot(P), + ok. + + + diff --git a/lib/erl_interface/test/erl_ext_SUITE_data/Makefile.first b/lib/erl_interface/test/erl_ext_SUITE_data/Makefile.first new file mode 100644 index 0000000000..cb7b12cc79 --- /dev/null +++ b/lib/erl_interface/test/erl_ext_SUITE_data/Makefile.first @@ -0,0 +1,21 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2002-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +ext_test_decl.c: ext_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run ext_test -s erlang halt diff --git a/lib/erl_interface/test/erl_ext_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_ext_SUITE_data/Makefile.src new file mode 100644 index 0000000000..6f363ccd6f --- /dev/null +++ b/lib/erl_interface/test/erl_ext_SUITE_data/Makefile.src @@ -0,0 +1,41 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2002-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBERL = $(LIBPATH)/@erl_interface_lib@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = ../all_SUITE_data/runner@obj@ \ + $(LIBERL) $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + @erl_interface_threadlib@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data +EXT_OBJS = ext_test@obj@ ext_test_decl@obj@ + +all: ext_test@exe@ + +clean: + $(RM) $(EXT_OBJS) + $(RM) ext_test@exe@ + +ext_test@exe@: $(EXT_OBJS) $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(EXT_OBJS) $(LIBFLAGS) diff --git a/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c b/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c new file mode 100644 index 0000000000..ba1a6c66da --- /dev/null +++ b/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c @@ -0,0 +1,485 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2002-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +/* + * Author: Rickard Green + * Modified: Bj�rn-Egil Dahlberg + * - compare_tuple + * - compare_string + * - compare_list + * - compare_list and string + */ + +#include "runner.h" +#include "erl_interface.h" +#include <stdio.h> +#include <string.h> + +typedef unsigned int uint; + +#define MAX_NC_EXT_SIZE 100 + +static unsigned char * +write_pid(unsigned char *buf, char *node, uint cre, uint ser, uint num); +static unsigned char * +write_port(unsigned char *buf, char *node, uint cre, uint id); +static unsigned char * +write_ref(unsigned char *buf, char *node, uint cre, uint id[], uint no_ids); +static void +test_compare_ext(char *test_desc, + unsigned char *ext1, + unsigned char *end_ext1, + unsigned char *ext2, + unsigned char *end_ext2, + int exp_res); + +/* + * Test erl_compare_ext with tuples + */ +TESTCASE(compare_tuple) { + // erlang:term_to_binary ({'b'}) + unsigned char term1[] = { 131, 104, 1, 100, 0, 1, 98 }; + // erlang:term_to_binary ({'a', 'a'}) + unsigned char term2[] = { 131, 104, 2, 100, 0, 1, 97, 100, 0, 1, 97 }; + unsigned char *start_a, *start_b, *end_a, *end_b; + + erl_init(NULL, 0); + start_a = term1; + start_b = term2; + end_a = term1 + 7; + end_b = term2 + 11; + + test_compare_ext("tuples", start_a, end_a, start_b, end_b, -1); + + report(1); +} + +/* + * Test erl_compare_ext with lists + */ + +TESTCASE(compare_list) { + unsigned char *start_a, *start_b, *end_a, *end_b; + // erlang:term_to_binary([a,b,[],3412]) + unsigned char term1[] = {131,108,0,0,0,4,100,0,1,97,100,0,1,98,106,98,0,0,13,84,106}; + // erlang:term_to_binary([34,{a,n},a,erlang]) + unsigned char term2[] = {131,108,0,0,0,4,97,34,104,2,100,0,1,97,100,0,1,110,100,0,1,97,100,0,6,101,114,108,97,110,103,106}; + + erl_init(NULL, 0); + start_a = term1; + start_b = term2; + end_a = term1 + 21; + end_b = term2 + 32; + + test_compare_ext("lists", start_a, end_a, start_b, end_b, 1); + + report(1); +} + +/* + * Test erl_compare_ext with strings + */ + +TESTCASE(compare_string) { + unsigned char *start_a, *start_b, *end_a, *end_b; + // erlang:term_to_binary("hej") + unsigned char term1[] = {131,107,0,3,104,101,106}; + // erlang:term_to_binary("erlang") + unsigned char term2[] = {131,107,0,6,101,114,108,97,110,103}; + + erl_init(NULL, 0); + start_a = term1; + start_b = term2; + end_a = term1 + 7; + end_b = term2 + 10; + + test_compare_ext("strings", start_a, end_a, start_b, end_b, 1); + + report(1); +} + +/* + * Test erl_compare_ext with lists and strings + */ + +TESTCASE(compare_list_string) { + unsigned char *start_a, *start_b, *end_a, *end_b; + // erlang:term_to_binary("hej") + unsigned char term1[] = {131,107,0,3,104,101,106}; + // erlang:term_to_binary([a,b,[],3412]) + unsigned char term2[] = {131,108,0,0,0,4,100,0,1,97,100,0,1,98,106,98,0,0,13,84,106}; + + erl_init(NULL, 0); + start_a = term1; + start_b = term2; + end_a = term1 + 7; + end_b = term2 + 21; + + test_compare_ext("strings", start_a, end_a, start_b, end_b, -1); + + report(1); +} + + + +/* + * Test erl_compare_ext with node containers + */ +TESTCASE(compare_nc_ext) +{ + int res; + unsigned char buf_a[MAX_NC_EXT_SIZE], buf_b[MAX_NC_EXT_SIZE]; + unsigned char *end_a, *end_b; + uint id[3]; + + erl_init(NULL, 0); + + + /* + * Test pids ---------------------------------------------------- + * + * Significance (most -> least): + * nodename, creation, serial, number, nodename, creation + * + */ + + end_a = write_pid(buf_a, "b@b", 2, 4711, 1); + + end_b = write_pid(buf_b, "a@b", 1, 4710, 2); + test_compare_ext("pid test 1", buf_a, end_a, buf_b, end_b, -1); + + end_b = write_pid(buf_b, "a@b", 1, 4712, 1); + test_compare_ext("pid test 2", buf_a, end_a, buf_b, end_b, -1); + + end_b = write_pid(buf_b, "c@b", 1, 4711, 1); + test_compare_ext("pid test 3", buf_a, end_a, buf_b, end_b, -1); + + end_b = write_pid(buf_b, "b@b", 3, 4711, 1); + test_compare_ext("pid test 4", buf_a, end_a, buf_b, end_b, -1); + + end_b = write_pid(buf_b, "b@b", 2, 4711, 1); + test_compare_ext("pid test 5", buf_a, end_a, buf_b, end_b, 0); + + + /* + * Test ports --------------------------------------------------- + * + * Significance (most -> least): + * nodename, creation, number + * + * OBS: Comparison between ports has changed in R9. This + * since it wasn't stable in R8 (and eariler releases). + * Significance used to be: dist_slot, number, + * creation. + */ + + end_a = write_port(buf_a, "b@b", 2, 4711), + + end_b = write_port(buf_b, "c@b", 1, 4710); + test_compare_ext("port test 1", buf_a, end_a, buf_b, end_b, -1); + + end_b = write_port(buf_b, "b@b", 3, 4710); + test_compare_ext("port test 2", buf_a, end_a, buf_b, end_b, -1); + + end_b = write_port(buf_b, "b@b", 2, 4712); + test_compare_ext("port test 3", buf_a, end_a, buf_b, end_b, -1); + + end_b = write_port(buf_b, "b@b", 2, 4711); + test_compare_ext("port test 4", buf_a, end_a, buf_b, end_b, 0); + + /* + * Test refs ---------------------------------------------------- + * Significance (most -> least): + * nodename, creation, (number high, number mid), number low, + * + * OBS: Comparison between refs has changed in R9. This + * since it wasn't stable in R8 (and eariler releases). + * Significance used to be: dist_slot, number, + * creation. + * + */ + + /* Long & Long */ + + id[0] = 4711; id[1] = 4711, id[2] = 4711; + end_a = write_ref(buf_a, "b@b", 2, id, 3); + + + id[0] = 4710; id[1] = 4710; id[2] = 4710; + end_b = write_ref(buf_b, "c@b", 1, id, 3); + test_compare_ext("ref test 1", buf_a, end_a, buf_b, end_b, -1); + + id[0] = 4710; id[1] = 4710; id[2] = 4710; + end_b = write_ref(buf_b, "b@b", 3, id, 3); + test_compare_ext("ref test 2", buf_a, end_a, buf_b, end_b, -1); + + id[0] = 4710; id[1] = 4710; id[2] = 4712; + end_b = write_ref(buf_b, "b@b", 2, id, 3); + test_compare_ext("ref test 3", buf_a, end_a, buf_b, end_b, -1); + + id[0] = 4710; id[1] = 4712; id[2] = 4711; + end_b = write_ref(buf_b, "b@b", 2, id, 3); + test_compare_ext("ref test 4", buf_a, end_a, buf_b, end_b, -1); + + id[0] = 4712; id[1] = 4711; id[2] = 4711; + end_b = write_ref(buf_b, "b@b", 2, id, 3); + test_compare_ext("ref test 5", buf_a, end_a, buf_b, end_b, -1); + + id[0] = 4711; id[1] = 4711; id[2] = 4711; + end_b = write_ref(buf_b, "b@b", 2, id, 3); + test_compare_ext("ref test 6", buf_a, end_a, buf_b, end_b, 0); + + /* Long & Short */ + id[0] = 4711; id[1] = 0, id[2] = 0; + end_a = write_ref(buf_a, "b@b", 2, id, 3); + + + id[0] = 4710; + end_b = write_ref(buf_b, "c@b", 1, id, 1); + test_compare_ext("ref test 7", buf_a, end_a, buf_b, end_b, -1); + + id[0] = 4710; + end_b = write_ref(buf_b, "b@b", 3, id, 1); + test_compare_ext("ref test 8", buf_a, end_a, buf_b, end_b, -1); + + id[0] = 4712; + end_b = write_ref(buf_b, "b@b", 2, id, 1); + test_compare_ext("ref test 9", buf_a, end_a, buf_b, end_b, -1); + + id[0] = 4711; + end_b = write_ref(buf_b, "b@b", 2, id, 1); + test_compare_ext("ref test 10", buf_a, end_a, buf_b, end_b, 0); + + /* Short & Long */ + id[0] = 4711; + end_a = write_ref(buf_a, "b@b", 2, id, 1); + + + id[0] = 4710; id[1] = 0, id[2] = 0; + end_b = write_ref(buf_b, "c@b", 1, id, 3); + test_compare_ext("ref test 11", buf_a, end_a, buf_b, end_b, -1); + + id[0] = 4710; id[1] = 0, id[2] = 0; + end_b = write_ref(buf_b, "b@b", 3, id, 3); + test_compare_ext("ref test 12", buf_a, end_a, buf_b, end_b, -1); + + id[0] = 4712; id[1] = 0, id[2] = 0; + end_b = write_ref(buf_b, "b@b", 2, id, 3); + test_compare_ext("ref test 13", buf_a, end_a, buf_b, end_b, -1); + + id[0] = 4711; id[1] = 0, id[2] = 0; + end_b = write_ref(buf_b, "b@b", 2, id, 3); + test_compare_ext("ref test 14", buf_a, end_a, buf_b, end_b, 0); + + /* Short & Short */ + id[0] = 4711; + end_a = write_ref(buf_a, "b@b", 2, id, 1); + + + id[0] = 4710; + end_b = write_ref(buf_b, "c@b", 1, id, 1); + test_compare_ext("ref test 15", buf_a, end_a, buf_b, end_b, -1); + + id[0] = 4710; + end_b = write_ref(buf_b, "b@b", 3, id, 1); + test_compare_ext("ref test 16", buf_a, end_a, buf_b, end_b, -1); + + id[0] = 4712; + end_b = write_ref(buf_b, "b@b", 2, id, 1); + test_compare_ext("ref test 17", buf_a, end_a, buf_b, end_b, -1); + + id[0] = 4711; + end_b = write_ref(buf_b, "b@b", 2, id, 1); + test_compare_ext("ref test 18", buf_a, end_a, buf_b, end_b, 0); + + report(1); +} + +static void +test_compare_ext(char *test_desc, + unsigned char *ext1, + unsigned char *end_ext1, + unsigned char *ext2, + unsigned char *end_ext2, + int exp_res) +{ + int er, ar; + unsigned char *e1, *e2; + int reversed_args; + char ext_str[MAX_NC_EXT_SIZE*4 + 1]; + char *es; + + message("*** %s ***", test_desc); + message(" erl_compare_ext() arguments:", test_desc); + + es = &ext_str[0]; + + e1 = ext1; + while (e1 < end_ext1) + es += sprintf(es, "%d,", *(e1++)); + *(--es) = '\0'; + message(" e1 = <<%s>>", ext_str); + + + es = &ext_str[0]; + + e2 = ext2; + while (e2 < end_ext2) + es += sprintf(es, "%d,", *(e2++)); + *(--es) = '\0'; + message(" e2 = <<%s>>", ext_str); + + message("Starting %s...", test_desc); + + + reversed_args = 0; + er = exp_res; + e1 = ext1; + e2 = ext2; + + reversed_args_start: + + ar = erl_compare_ext(e1, e2); + if (er < 0) { + if (ar > 0) + fail("expected result e1 < e2; actual result e1 > e2\n"); + else if (ar == 0) + fail("expected result e1 < e2; actual result e1 = e2\n"); + } + else if (er > 0) { + if (ar < 0) + fail("expected result e1 > e2; actual result e1 < e2\n"); + else if (ar == 0) + fail("expected result e1 > e2; actual result e1 = e2\n"); + } + else { + if (ar > 0) + fail("expected result e1 = e2; actual result e1 > e2\n"); + else if (ar < 0) + fail("expected result e1 = e2; actual result e1 < e2\n"); + } + + message("%s", "SUCCEEDED!"); + if (!reversed_args) { + message("Starting %s with reversed arguments...", test_desc); + e2 = ext1; + e1 = ext2; + if (exp_res < 0) + er = 1; + else if (exp_res > 0) + er = -1; + reversed_args = 1; + goto reversed_args_start; + } + + message("%s", ""); + +} + + +#define ATOM_EXT (100) +#define REFERENCE_EXT (101) +#define PORT_EXT (102) +#define PID_EXT (103) +#define NEW_REFERENCE_EXT (114) + + +#define PUT_UINT16(E, X) ((E)[0] = ((X) >> 8) & 0xff, \ + (E)[1] = (X) & 0xff) + +#define PUT_UINT32(E, X) ((E)[0] = ((X) >> 24) & 0xff, \ + (E)[1] = ((X) >> 16) & 0xff, \ + (E)[2] = ((X) >> 8) & 0xff, \ + (E)[3] = (X) & 0xff) + +static unsigned char * +write_atom(unsigned char *buf, char *atom) +{ + uint len; + + len = 0; + while(atom[len]) { + buf[len + 3] = atom[len]; + len++; + } + buf[0] = ATOM_EXT; + PUT_UINT16(&buf[1], len); + + return buf + 3 + len; +} + +static unsigned char * +write_pid(unsigned char *buf, char *node, uint cre, uint num, uint ser) +{ + unsigned char *e = buf; + + *(e++) = PID_EXT; + e = write_atom(e, node); + PUT_UINT32(e, num & ((1 << 15) - 1)); + e += 4; + PUT_UINT32(e, ser & ((1 << 3) - 1)); + e += 4; + *(e++) = cre & ((1 << 2) - 1); + + return e; +} + +static unsigned char * +write_port(unsigned char *buf, char *node, uint cre, uint id) +{ + unsigned char *e = buf; + + *(e++) = PORT_EXT; + e = write_atom(e, node); + PUT_UINT32(e, id & ((1 << 15) - 1)); + e += 4; + *(e++) = cre & ((1 << 2) - 1); + + return e; +} + +static unsigned char * +write_ref(unsigned char *buf, char *node, uint cre, uint id[], uint no_ids) +{ + int i; + unsigned char *e = buf; + + if (no_ids == 1) { + *(e++) = REFERENCE_EXT; + e = write_atom(e, node); + PUT_UINT32(e, id[0] & ((1 << 15) - 1)); + e += 4; + *(e++) = cre & ((1 << 2) - 1); + } + else { + *(e++) = NEW_REFERENCE_EXT; + PUT_UINT16(e, no_ids); + e += 2; + e = write_atom(e, node); + *(e++) = cre & ((1 << 2) - 1); + for (i = 0; i < no_ids; i++) { + PUT_UINT32(e, id[i]); + e += 4; + } + } + + return e; +} + diff --git a/lib/erl_interface/test/erl_format_SUITE.erl b/lib/erl_interface/test/erl_format_SUITE.erl new file mode 100644 index 0000000000..81a0bca80f --- /dev/null +++ b/lib/erl_interface/test/erl_format_SUITE.erl @@ -0,0 +1,136 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(erl_format_SUITE). + +-include("test_server.hrl"). +-include("erl_format_SUITE_data/format_test_cases.hrl"). + +-export([all/1, atoms/1, tuples/1, lists/1]). + +-import(runner, [get_term/1]). + +%% This test suite test the erl_format() function. +%% It uses the port program "format_test". + +all(suite) -> [atoms, tuples, lists]. + +%% Tests formatting various atoms. + +atoms(suite) -> []; +atoms(Config) when is_list(Config) -> + ?line P = runner:start(?atoms), + + ?line {term, ''} = get_term(P), + ?line {term, 'a'} = get_term(P), + ?line {term, 'A'} = get_term(P), + ?line {term, 'abc'} = get_term(P), + ?line {term, 'Abc'} = get_term(P), + ?line {term, 'ab@c'} = get_term(P), + ?line {term, 'The rain in Spain stays mainly in the plains'} = + get_term(P), + + ?line {term, a} = get_term(P), + ?line {term, ab} = get_term(P), + ?line {term, abc} = get_term(P), + ?line {term, ab@c} = get_term(P), + ?line {term, abcdefghijklmnopq} = get_term(P), + + ?line {term, ''} = get_term(P), + ?line {term, 'a'} = get_term(P), + ?line {term, 'A'} = get_term(P), + ?line {term, 'abc'} = get_term(P), + ?line {term, 'Abc'} = get_term(P), + ?line {term, 'ab@c'} = get_term(P), + ?line {term, 'The rain in Spain stays mainly in the plains'} = + get_term(P), + + ?line {term, a} = get_term(P), + ?line {term, ab} = get_term(P), + ?line {term, abc} = get_term(P), + ?line {term, ab@c} = get_term(P), + ?line {term, ' abcdefghijklmnopq '} = get_term(P), + + ?line runner:recv_eot(P), + ok. + + + +%% Tests formatting various tuples + +tuples(suite) -> []; +tuples(Config) when is_list(Config) -> + ?line P = runner:start(?tuples), + + ?line {term, {}} = get_term(P), + ?line {term, {a}} = get_term(P), + ?line {term, {a, b}} = get_term(P), + ?line {term, {a, b, c}} = get_term(P), + ?line {term, {1}} = get_term(P), + ?line {term, {[]}} = get_term(P), + ?line {term, {[], []}} = get_term(P), + ?line {term, {[], a, b, c}} = get_term(P), + ?line {term, {[], a, [], b, c}} = get_term(P), + ?line {term, {[], a, '', b, c}} = get_term(P), + + ?line runner:recv_eot(P), + ok. + + + +%% Tests formatting various lists + +lists(suite) -> []; +lists(Config) when is_list(Config) -> + ?line P = runner:start(?lists), + + ?line {term, []} = get_term(P), + ?line {term, [a]} = get_term(P), + ?line {term, [a, b]} = get_term(P), + ?line {term, [a, b, c]} = get_term(P), + ?line {term, [1]} = get_term(P), + ?line {term, [[]]} = get_term(P), + ?line {term, [[], []]} = get_term(P), + ?line {term, [[], a, b, c]} = get_term(P), + ?line {term, [[], a, [], b, c]} = get_term(P), + ?line {term, [[], a, '', b, c]} = get_term(P), + + ?line {term, [{name, 'Madonna'}, {age, 21}, {data, [{addr, "E-street", 42}]}]} = + get_term(P), + case os:type() of + vxworks -> + ?line {term, [{pi, _}, {'cos(70)', _}]} = get_term(P), + ?line {term, [[pi, _], ['cos(70)', _]]} = get_term(P), + ?line {term, [[pi, _], [], ["cos(70)", _]]} = + get_term(P); + _ -> + ?line {term, [{pi, 3.1415}, {'cos(70)', 0.34202}]} = get_term(P), + ?line {term, [[pi, 3.1415], ['cos(70)', 0.34202]]} = get_term(P), + ?line {term, [[pi, 3.1415], [], ["cos(70)", 0.34202]]} = + get_term(P) + end, + + ?line {term, [-1]} = get_term(P), + + ?line runner:recv_eot(P), + ok. + + + diff --git a/lib/erl_interface/test/erl_format_SUITE_data/Makefile.first b/lib/erl_interface/test/erl_format_SUITE_data/Makefile.first new file mode 100644 index 0000000000..2cd313a324 --- /dev/null +++ b/lib/erl_interface/test/erl_format_SUITE_data/Makefile.first @@ -0,0 +1,21 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2000-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +format_test_decl.c: format_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run format_test -s erlang halt diff --git a/lib/erl_interface/test/erl_format_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_format_SUITE_data/Makefile.src new file mode 100644 index 0000000000..0cd1ab512d --- /dev/null +++ b/lib/erl_interface/test/erl_format_SUITE_data/Makefile.src @@ -0,0 +1,43 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1997-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBERL = $(LIBPATH)/@erl_interface_lib@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = ../all_SUITE_data/runner@obj@ \ + $(LIBERL) $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + @erl_interface_threadlib@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data +FORMAT_OBJS = format_test@obj@ format_test_decl@obj@ + +all: format_test@exe@ + +clean: + $(RM) $(FORMAT_OBJS) + $(RM) format_test@exe@ + +format_test@exe@: $(FORMAT_OBJS) $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(FORMAT_OBJS) $(LIBFLAGS) + + diff --git a/lib/erl_interface/test/erl_format_SUITE_data/format_test.c b/lib/erl_interface/test/erl_format_SUITE_data/format_test.c new file mode 100644 index 0000000000..75e73b6df5 --- /dev/null +++ b/lib/erl_interface/test/erl_format_SUITE_data/format_test.c @@ -0,0 +1,132 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1997-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#include "runner.h" + +/* + * Purpose: Tests the erl_format() function. + * Author: Bjorn Gustavsson + */ + +static void +send_format(char* format) +{ + send_term(erl_format(format)); +} + +TESTCASE(atoms) +{ + erl_init(NULL, 0); + + send_format("''"); + send_format("'a'"); + send_format("'A'"); + send_format("'abc'"); + send_format("'Abc'"); + send_format("'ab@c'"); + send_format("'The rain in Spain stays mainly in the plains'"); + + send_format("a"); + send_format("ab"); + send_format("abc"); + send_format("ab@c"); + send_format(" abcdefghijklmnopq "); + + send_term(erl_format("~a", "")); + send_term(erl_format("~a", "a")); + send_term(erl_format("~a", "A")); + send_term(erl_format("~a", "abc")); + send_term(erl_format("~a", "Abc")); + send_term(erl_format("~a", "ab@c")); + send_term(erl_format("~a", "The rain in Spain stays mainly in the plains")); + + send_term(erl_format("~a", "a")); + send_term(erl_format("~a", "ab")); + send_term(erl_format("~a", "abc")); + send_term(erl_format("~a","ab@c")); + send_term(erl_format("~a", " abcdefghijklmnopq ")); + + + report(1); +} + +TESTCASE(tuples) +{ + erl_init(NULL, 0); + + send_format("{}"); + send_format("{a}"); + send_format("{a, b}"); + send_format("{a, b, c}"); + send_format("{1}"); + send_format("{[]}"); + send_format("{[], []}"); + send_format("{[], a, b, c}"); + send_format("{[], a, [], b, c}"); + send_format("{[], a, '', b, c}"); + + report(1); +} + + + +TESTCASE(lists) +{ + ETERM* a; + ETERM* b; + ETERM* c; + + erl_init(NULL, 0); + + send_format("[]"); + send_format("[a]"); + send_format("[a, b]"); + send_format("[a, b, c]"); + send_format("[1]"); + send_format("[[]]"); + send_format("[[], []]"); + send_format("[[], a, b, c]"); + send_format("[[], a, [], b, c]"); + send_format("[[], a, '', b, c]"); + + b = erl_format("[{addr, ~s, ~i}]", "E-street", 42); + a = erl_format("[{name, ~a}, {age, ~i}, {data, ~w}]", "Madonna", 21, b); + send_term(a); + erl_free_term(b); + + send_term(erl_format("[{pi, ~f}, {'cos(70)', ~f}]", 3.1415, 0.34202)); + + a = erl_mk_float(3.1415); + b = erl_mk_float(0.34202); + send_term(erl_format("[[pi, ~w], ['cos(70)', ~w]]", a, b)); + erl_free_term(a); + erl_free_term(b); + + a = erl_mk_float(3.1415); + b = erl_mk_float(0.34202); + c = erl_mk_empty_list(); + send_term(erl_format("[[~a, ~w], ~w, [~s, ~w]]", "pi", a, c, "cos(70)", b)); + erl_free_term(a); + erl_free_term(b); + erl_free_term(c); + + send_term(erl_format("[~i]", -1)); + + report(1); +} diff --git a/lib/erl_interface/test/erl_interface.dynspec b/lib/erl_interface/test/erl_interface.dynspec new file mode 100644 index 0000000000..8af5040d97 --- /dev/null +++ b/lib/erl_interface/test/erl_interface.dynspec @@ -0,0 +1,18 @@ +%% -*- erlang -*- +%% You can test this file using this command. +%% file:script("erl_interface.dynspec", [{'TestCCompiler',{msc | gnuc, undefined}}]). + +case {TestCCompiler, erlang:system_info(c_compiler_used)} of + {{CC, _}, {CC, _}} -> + []; + {{CC1, _}, {CC2, _}} when CC1 == msc; CC2 == msc -> + Comment = + "OTP's static C libraries (compiled with " + ++ atom_to_list(CC2) ++ ") aren't compatible " + "with the C compiler (" ++ atom_to_list(CC1) + ++ ") used for testing.", + StaticLibSuites = [all_SUITE], + lists:map(fun (Suite) -> {skip,{Suite, Comment}} end, StaticLibSuites); + {{CC1, _}, {CC2, _}} -> + [] +end. diff --git a/lib/erl_interface/test/erl_interface.spec b/lib/erl_interface/test/erl_interface.spec new file mode 100644 index 0000000000..2789bd3e2c --- /dev/null +++ b/lib/erl_interface/test/erl_interface.spec @@ -0,0 +1,2 @@ +{topcase, {dir, "../erl_interface_test"}}. + diff --git a/lib/erl_interface/test/erl_interface.spec.vxworks b/lib/erl_interface/test/erl_interface.spec.vxworks new file mode 100644 index 0000000000..7089b3d447 --- /dev/null +++ b/lib/erl_interface/test/erl_interface.spec.vxworks @@ -0,0 +1,5 @@ +{topcase, {dir, "../erl_interface_test"}}. +{skip,{ei_accept_SUITE, ei_threaded_accept, + "Threaded test not yet implemented - FIXME"}}. +{skip,{ei_connect_SUITE, ei_threaded_send, + "Threaded test not yet implemented - FIXME"}}. diff --git a/lib/erl_interface/test/erl_match_SUITE.erl b/lib/erl_interface/test/erl_match_SUITE.erl new file mode 100644 index 0000000000..f506638544 --- /dev/null +++ b/lib/erl_interface/test/erl_match_SUITE.erl @@ -0,0 +1,288 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(erl_match_SUITE). + +-include("test_server.hrl"). +-include("erl_match_SUITE_data/match_test_cases.hrl"). + +-export([all/1, atoms/1, lists/1, tuples/1, references/1, pids/1, ports/1, + bind/1, integers/1, floats/1, binaries/1, strings/1]). + +%% For interactive running of matcher. +-export([start_matcher/0, erl_match/3]). + +%% This test suite tests the erl_match() function. + +all(suite) -> [atoms, lists, tuples, references, pids, ports, bind, + integers, floats, binaries, strings]. + +atoms(suite) -> []; +atoms(Config) when is_list(Config) -> + ?line P = start_matcher(), + + ?line eq(P, '', ''), + ?line eq(P, a, a), + ?line ne(P, a, b), + ?line ne(P, a, aa), + ?line eq(P, kalle, kalle), + ?line ne(P, kalle, arne), + + ?line ne(P, kalle, 42), + ?line ne(P, 42, kalle), + + ?line runner:finish(P), + ok. + +lists(suite) -> []; +lists(Config) when is_list(Config) -> + ?line P = start_matcher(), + ?line eq(P, [], []), + + ?line ne(P, [], [a]), + ?line ne(P, [a], []), + + ?line eq(P, [a], [a]), + ?line ne(P, [a], [b]), + + ?line eq(P, [a|b], [a|b]), + ?line ne(P, [a|b], [a|x]), + + ?line eq(P, [a, b], [a, b]), + ?line ne(P, [a, b], [a, x]), + + ?line eq(P, [a, b, c], [a, b, c]), + ?line ne(P, [a, b|c], [a, b|x]), + ?line ne(P, [a, b, c], [a, b, x]), + ?line ne(P, [a, b|c], [a, b|x]), + ?line ne(P, [a, x|c], [a, b|c]), + ?line ne(P, [a, b, c], [a, x, c]), + + ?line runner:finish(P), + ok. + +tuples(suite) -> []; +tuples(Config) when is_list(Config) -> + ?line P = start_matcher(), + + ?line ne(P, {}, {a, b}), + ?line ne(P, {a, b}, {}), + ?line ne(P, {a}, {a, b}), + ?line ne(P, {a, b}, {a}), + + ?line eq(P, {}, {}), + + ?line eq(P, {a}, {a}), + ?line ne(P, {a}, {b}), + + ?line eq(P, {1}, {1}), + ?line ne(P, {1}, {2}), + + ?line eq(P, {a, b}, {a, b}), + ?line ne(P, {x, b}, {a, b}), + + ?line ne(P, {error, x}, {error, y}), + ?line ne(P, {error, {undefined, {subscriber, last}}}, + {error, {undefined, {subscriber, name}}}), + + ?line runner:finish(P), + ok. + + +references(suite) -> []; +references(Config) when is_list(Config) -> + ?line P = start_matcher(), + ?line Ref1 = make_ref(), + ?line Ref2 = make_ref(), + + ?line eq(P, Ref1, Ref1), + ?line eq(P, Ref2, Ref2), + ?line ne(P, Ref1, Ref2), + ?line ne(P, Ref2, Ref1), + + ?line runner:finish(P), + ok. + + +pids(suite) -> []; +pids(Config) when is_list(Config) -> + ?line P = start_matcher(), + ?line Pid1 = c:pid(0,1,2), + ?line Pid2 = c:pid(0,1,3), + + ?line eq(P, self(), self()), + ?line eq(P, Pid1, Pid1), + ?line ne(P, Pid1, self()), + ?line ne(P, Pid2, Pid1), + + ?line runner:finish(P), + ok. + + +ports(suite) -> []; +ports(Config) when is_list(Config) -> + case os:type() of + vxworks -> + {skipped,"not on vxworks, pucko"}; + _ -> + ?line P = start_matcher(), + ?line P2 = start_matcher(), + + ?line eq(P, P, P), + ?line ne(P, P, P2), + + ?line runner:finish(P), + ?line runner:finish(P2), + ok + end. + +integers(suite) -> []; +integers(Config) when is_list(Config) -> + ?line P = start_matcher(), + ?line I1 = 123, + ?line I2 = 12345, + ?line I3 = -123, + ?line I4 = 2234, + + ?line eq(P, I1, I1), + ?line eq(P, I2, I2), + ?line ne(P, I1, I2), + ?line ne(P, I1, I3), + ?line eq(P, I4, I4), + + ?line runner:finish(P), + ok. + + + +floats(suite) -> []; +floats(Config) when is_list(Config) -> + ?line P = start_matcher(), + ?line F1 = 3.1414, + ?line F2 = 3.1415, + ?line F3 = 3.1416, + + ?line S1 = "string", + ?line S2 = "string2", + + ?line eq(P, F1, F1), + ?line eq(P, F2, F2), + ?line ne(P, F1, F2), + ?line ne(P, F3, F2), + + ?line eq(P, S2, S2), + ?line ne(P, S1, S2), + + ?line runner:finish(P), + ok. + + + +binaries(suite) -> []; +binaries(Config) when is_list(Config) -> + ?line P = start_matcher(), + ?line Bin1 = term_to_binary({kalle, 146015, {kungsgatan, 23}}), + ?line Bin2 = term_to_binary(sune), + ?line Bin3 = list_to_binary("sune"), + + ?line eq(P, Bin1, Bin1), + ?line eq(P, Bin2, Bin2), + ?line eq(P, Bin3, Bin3), + ?line ne(P, Bin1, Bin2), + ?line ne(P, Bin1, Bin3), + ?line ne(P, Bin2, Bin3), + + ?line runner:finish(P), + ok. + + + +strings(suite) -> []; +strings(Config) when is_list(Config) -> + ?line P = start_matcher(), + + ?line S1 = "string", + ?line S2 = "streng", + ?line S3 = "String", + + ?line eq(P, S1, S1), + ?line ne(P, S1, S2), + ?line ne(P, S1, S3), + + ?line runner:finish(P), + ok. + + + +bind(suite) -> []; +bind(Config) when is_list(Config) -> + ?line P = start_bind(), + ?line S = "[X,Y,Z]", + ?line L1 = [301,302,302], + ?line L2 = [65,66,67], + + ?line bind_ok(P, S, L1), + ?line bind_ok(P, S, L2), + + ?line runner:finish(P), + ok. + +start_bind() -> + runner:start(?erl_match_bind). + +bind_ok(Port, Bind, Term) -> + true = erl_bind(Port, Bind, Term). + +%bind_nok(Port, Bind, Term) -> +% false = erl_bind(Port, Bind, Term). + +erl_bind(Port, Pattern, Term) -> + Port ! {self(), {command, [$b, Pattern, 0]}}, + runner:send_term(Port, Term), + case runner:get_term(Port) of + {term, 0} -> false; + {term, 1} -> true + end. + + + + + + +start_matcher() -> + runner:start(?erl_match_server). + +eq(Port, Pattern, Term) -> + true = erl_match(Port, Pattern, Term). + +ne(Port, Pattern, Term) -> + false = erl_match(Port, Pattern, Term). + + + +erl_match(Port, Pattern, Term) -> + runner:send_term(Port, Pattern), + runner:send_term(Port, Term), + case runner:get_term(Port) of + {term, 0} -> false; + {term, 1} -> true + end. + + diff --git a/lib/erl_interface/test/erl_match_SUITE_data/Makefile.first b/lib/erl_interface/test/erl_match_SUITE_data/Makefile.first new file mode 100644 index 0000000000..12141d210c --- /dev/null +++ b/lib/erl_interface/test/erl_match_SUITE_data/Makefile.first @@ -0,0 +1,21 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2000-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +match_test_decl.c: match_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run match_test -s erlang halt diff --git a/lib/erl_interface/test/erl_match_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_match_SUITE_data/Makefile.src new file mode 100644 index 0000000000..8ce6c9c985 --- /dev/null +++ b/lib/erl_interface/test/erl_match_SUITE_data/Makefile.src @@ -0,0 +1,42 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1997-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBERL = $(LIBPATH)/@erl_interface_lib@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = ../all_SUITE_data/runner@obj@ \ + $(LIBERL) $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + @erl_interface_threadlib@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data +MATCH_OBJS = match_test@obj@ match_test_decl@obj@ + +all: match_test@exe@ + +clean: + $(RM) $(MATCH_OBJS) + $(RM) match_test@exe@ + +match_test@exe@: $(MATCH_OBJS) $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(MATCH_OBJS) $(LIBFLAGS) + diff --git a/lib/erl_interface/test/erl_match_SUITE_data/match_test.c b/lib/erl_interface/test/erl_match_SUITE_data/match_test.c new file mode 100644 index 0000000000..153a528b0b --- /dev/null +++ b/lib/erl_interface/test/erl_match_SUITE_data/match_test.c @@ -0,0 +1,113 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1997-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* + * Purpose: Tests the erl_match() function. + * Author: Bjorn Gustavsson + */ + +#include "runner.h" + +TESTCASE(erl_match_server) +{ + erl_init(NULL, 0); + + for (;;) { + ETERM* pattern; + ETERM* term; + + pattern = get_term(); + if (pattern == NULL) { + report(1); + return; + } else { + term = get_term(); + if (term == NULL) { + fail("Unexpected EOF term"); + } else { + send_term(erl_mk_int(erl_match(pattern, term))); + erl_free_term(pattern); + erl_free_term(term); + } + } + } + +} + +TESTCASE(erl_match_bind) +{ + erl_init(NULL, 0); + + for (;;) { + char* pattern; + ETERM* term; + + pattern=read_packet(NULL); + + switch (pattern[0]) { + case 'e': + free(pattern); + report(1); + return; + + case 'b': + { + ETERM* patt_term; + + /* + * Get the pattern string and convert it using erl_format(). + * + * Note that the call to get_term() below destroys the buffer + * that the pattern variable points to. Therefore, it is + * essential to call erl_format() here, before + * calling get_term(). + */ + + message("Pattern: %s", pattern+1); + patt_term = erl_format(pattern+1); + free(pattern); + + if (patt_term == NULL) { + fail("erl_format() failed"); + } + + /* + * Get the term and send back the result of the erl_match() + * call. + */ + + term = get_term(); + if (term == NULL) { + fail("Unexpected eof term"); + } + else { + send_term(erl_mk_int(erl_match(patt_term, term))); + } + erl_free_term(patt_term); + erl_free_term(term); + } + break; + + default: + free(pattern); + fail("Illegal character received"); + } + + } +} diff --git a/lib/erl_interface/test/port_call_SUITE.erl b/lib/erl_interface/test/port_call_SUITE.erl new file mode 100644 index 0000000000..895e29ad2e --- /dev/null +++ b/lib/erl_interface/test/port_call_SUITE.erl @@ -0,0 +1,106 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(port_call_SUITE). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Checks if the dynamic driver and linker loader works. +%%% +%%% These tests can only be run installed (outside clearcase). +%%% +%%% XXX In this suite is missing test cases for reference counts +%%% and that drivers are unloaded when their processes die. +%%% (For me to add :-) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +-export([all/1, basic/1]). +% Private exports +-include("test_server.hrl"). + + +all(suite) -> + [basic]. + +basic(suite) -> []; +basic(Config) when is_list(Config) -> + case os:type() of + {unix, sunos} -> + do_basic(Config); + {win32,_} -> + do_basic(Config); + _ -> + {skipped, "Dynamic linking and erl_interface not fully examined" + " on this platform..."} + end. + +do_basic(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + + ?line erl_ddll:start(), + + %% Load the echo driver and verify that it was loaded. + {ok,L1,L2}=load_port_call_driver(Path), + + %% Verify that the driver works. + + ?line Port = open_port({spawn, port_call_drv}, [eof]), + ?line {hej, "hopp",4711,123445567436543653} = + erlang:port_call(Port,{hej, "hopp",4711,123445567436543653}), + ?line {hej, "hopp",4711,123445567436543653} = + erlang:port_call(Port,0,{hej, "hopp",4711,123445567436543653}), + ?line {[], a, [], b, c} = + erlang:port_call(Port,1,{hej, "hopp",4711,123445567436543653}), + ?line {return, {[], a, [], b, c}} = + erlang:port_call(Port,2,{[], a, [], b, c}), + ?line List = lists:duplicate(200,5), + ?line {return, List} = erlang:port_call(Port,2,List), + ?line {'EXIT',{badarg,_}} = (catch erlang:port_call(Port,4711,[])), + ?line {'EXIT',{badarg,_}} = (catch erlang:port_call(sune,2,[])), + ?line register(gunnar,Port), + ?line {return, List} = erlang:port_call(gunnar,2,List), + ?line {return, a} = erlang:port_call(gunnar,2,a), + ?line erlang:port_close(Port), + %% Unload the driver and verify that it was unloaded. + ok=unload_port_call_driver(L1,L2), + + ?line {error, {already_started, _}} = erl_ddll:start(), + ?line ok = erl_ddll:stop(), + + ?line test_server:timetrap_cancel(Dog), + ok. + +load_port_call_driver(Path) -> + ?line {ok, L1} = erl_ddll:loaded_drivers(), + ?line ok = erl_ddll:load_driver(Path, port_call_drv), + ?line {ok, L2} = erl_ddll:loaded_drivers(), + ?line ["port_call_drv"] = ordsets:to_list(ordsets:subtract(ordsets:from_list(L2), + ordsets:from_list(L1))), + {ok,L1,L2}. + +unload_port_call_driver(L1,L2) -> + ?line {ok, L2} = erl_ddll:loaded_drivers(), + ?line ok = erl_ddll:unload_driver(port_call_drv), + ?line {ok, L3} = erl_ddll:loaded_drivers(), + ?line [] = ordsets:to_list(ordsets:subtract(ordsets:from_list(L3), + ordsets:from_list(L1))), + ok. + diff --git a/lib/erl_interface/test/port_call_SUITE_data/Makefile.src b/lib/erl_interface/test/port_call_SUITE_data/Makefile.src new file mode 100644 index 0000000000..dc7385ba32 --- /dev/null +++ b/lib/erl_interface/test/port_call_SUITE_data/Makefile.src @@ -0,0 +1,39 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBERL = $(LIBPATH)/@erl_interface_lib_drv@ +LIBEI = $(LIBPATH)/@erl_interface_eilib_drv@ + +SHLIB_EXTRA_LDLIBS = $(LIBERL) $(LIBEI) +SHLIB_EXTRA_CFLAGS = -I@erl_interface_include@ -I../all_SUITE_data + + +all: port_call_drv@dll@ + +clean: + $(RM) port_call_drv@obj@ + $(RM) port_call_drv@dll@ + +@SHLIB_RULES@ diff --git a/lib/erl_interface/test/port_call_SUITE_data/port_call_drv.c b/lib/erl_interface/test/port_call_SUITE_data/port_call_drv.c new file mode 100644 index 0000000000..80811fb973 --- /dev/null +++ b/lib/erl_interface/test/port_call_SUITE_data/port_call_drv.c @@ -0,0 +1,103 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#include <stdio.h> +#include "erl_interface.h" +#include "erl_driver.h" + +static ErlDrvPort my_erlang_port; +static ErlDrvData echo_start(ErlDrvPort, char *); +static void from_erlang(ErlDrvData, char*, int); +static int do_call(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen, unsigned *ret_flags); +static ErlDrvEntry echo_driver_entry = { + NULL, /* Init */ + echo_start, + NULL, /* Stop */ + from_erlang, + NULL, /* Ready input */ + NULL, /* Ready output */ + "port_call_drv", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + do_call +}; + +DRIVER_INIT(echo_drv) +{ + return &echo_driver_entry; +} + +static ErlDrvData +echo_start(ErlDrvPort port, char *buf) +{ + return (ErlDrvData) port; +} + +static void +from_erlang(ErlDrvData data, char *buf, int count) +{ + driver_output((ErlDrvPort) data, buf, count); +} + +static int +do_call(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen, unsigned *ret_flags) +{ + int nlen; + ei_x_buff x; + + switch (command) { + case 0: + *rbuf = buf; + *ret_flags |= DRIVER_CALL_KEEP_BUFFER; + return len; + case 1: + ei_x_new(&x); + ei_x_format(&x, "{[], a, [], b, c}"); + nlen = x.index; + if (nlen > rlen) { + *rbuf =driver_alloc(nlen); + } + memcpy(*rbuf,x.buff,nlen); + ei_x_free(&x); + return nlen; + case 2: + ei_x_new(&x); + ei_x_encode_version(&x); + ei_x_encode_tuple_header(&x,2); + ei_x_encode_atom(&x,"return"); + ei_x_append_buf(&x,buf+1,len-1); + nlen = x.index; + if (nlen > rlen) { + *rbuf =driver_alloc(nlen); + } + memcpy(*rbuf,x.buff,nlen); + ei_x_free(&x); + return nlen; + default: + return -1; + } +} + diff --git a/lib/erl_interface/test/runner.erl b/lib/erl_interface/test/runner.erl new file mode 100644 index 0000000000..b72723c6a5 --- /dev/null +++ b/lib/erl_interface/test/runner.erl @@ -0,0 +1,130 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(runner). + +-export([test/1, test/2, + start/1, send_term/2, finish/1, send_eot/1, recv_eot/1, + get_term/1, get_term/2]). + +-define(default_timeout, test_server:seconds(5)). + +%% Executes a test case in a C program. +%% +%% This function is useful for test cases written in C which requires +%% no further input, and only returns a result by calling report(). + +test(Tc) -> + test(Tc, ?default_timeout). + +test(Tc, Timeout) -> + Port = start(Tc), + + case get_term(Port, Timeout) of + eot -> + ok; + Other -> + io:format("In this test case, a success/failure result was"), + io:format("expected from the C program.\n"), + io:format("Received: ~p", [Other]), + test_server:fail() + end. + +%% Executes a test case in a C program. Returns the port. +%% +%% Use get_term/1,2. +%% +%% Returns: {ok, Port} + +start({Prog, Tc}) when is_list(Prog), is_integer(Tc) -> + Port = open_port({spawn, Prog}, [{packet, 4}]), + Command = [Tc div 256, Tc rem 256], + Port ! {self(), {command, Command}}, + Port. + +%% Finishes a test case by send an 'eot' message to the C program +%% and waiting for an 'eot'. +%% +%% If the C program doesn't require an 'eot', use recv_eot/1 instead. + +finish(Port) when is_port(Port) -> + send_eot(Port), + recv_eot(Port). + +%% Sends an Erlang term to a C program. + +send_term(Port, Term) when is_port(Port) -> + Port ! {self(), {command, [$t, term_to_binary(Term)]}}. + +%% Sends an 'eot' (end-of-test) indication to a C progrm. + +send_eot(Port) when is_port(Port) -> + Port ! {self(), {command, [$e]}}. + +%% Waits for an 'eot' indication from the C program. +%% Either returns 'ok' or invokes test_server:fail(). + +recv_eot(Port) when is_port(Port) -> + case get_term(Port) of + eot -> + ok; + Other -> + io:format("Error finishing test case. Expected eof from"), + io:format("C program, but got:"), + io:format("~p", [Other]), + test_server:fail() + end. + +%% Reads a term from the C program. +%% +%% Returns: {term, Term}|eot|'NULL' or calls test_server:fail/1,2. + +get_term(Port) -> + get_term(Port, ?default_timeout). + +get_term(Port, Timeout) -> + case get_reply(Port, Timeout) of + [$b|Bytes] -> + {bytes, Bytes}; + [$f] -> + test_server:fail(); + [$f|Reason] -> + test_server:fail(Reason); + [$t|Term] -> + {term, binary_to_term(list_to_binary(Term))}; + [$N] -> + 'NULL'; + [$e] -> + eot; + [$m|Message] -> + io:format("~s", [Message]), + get_term(Port, Timeout); + Other -> + io:format("Garbage received from C program: ~p", [Other]), + test_server:fail("Illegal response from C program") + end. + +get_reply(Port, Timeout) when is_port(Port) -> + receive + {Port, {data, Reply}} -> + Reply + after Timeout -> + test_server:fail("No response from C program") + end. diff --git a/lib/ic/doc/src/Makefile b/lib/ic/doc/src/Makefile index f00bba2c71..26d0932a95 100644 --- a/lib/ic/doc/src/Makefile +++ b/lib/ic/doc/src/Makefile @@ -73,6 +73,9 @@ XML_CHAPTER_FILES = \ BOOK_FILES = book.xml +XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \ + $(XML_PART_FILES) $(XML_CHAPTER_FILES) + GIF_FILES = \ book.gif \ notes.gif \ diff --git a/lib/ic/doc/src/c-part.xml b/lib/ic/doc/src/c-part.xml index 91c81c8ef3..cef4399960 100644 --- a/lib/ic/doc/src/c-part.xml +++ b/lib/ic/doc/src/c-part.xml @@ -4,23 +4,21 @@ <part> <header> <copyright> - <year>2002</year> - <year>2007</year> - <holder>Ericsson AB, All Rights Reserved</holder> + <year>2002</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - The Initial Developer of the Original Code is Ericsson AB. + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + </legalnotice> <title>IDL to C language Mapping</title> diff --git a/lib/ic/doc/src/ch_c_corba_env.xml b/lib/ic/doc/src/ch_c_corba_env.xml index 557eeffdd4..bd4b52ca34 100644 --- a/lib/ic/doc/src/ch_c_corba_env.xml +++ b/lib/ic/doc/src/ch_c_corba_env.xml @@ -281,7 +281,7 @@ typedef struct { <p>By using the <em>CORBA_Environment_alloc</em>/2 function. </p> <p>The CORBA_Environment_alloc function is defined as:</p> <code type="none"> -\\011 CORBA_Environment *CORBA_Environment_alloc(int inbufsz, + CORBA_Environment *CORBA_Environment_alloc(int inbufsz, int outbufsz); </code> <p>where:</p> diff --git a/lib/ic/doc/src/ch_c_mapping.xml b/lib/ic/doc/src/ch_c_mapping.xml index 58b026ee78..f5a921bfd2 100644 --- a/lib/ic/doc/src/ch_c_mapping.xml +++ b/lib/ic/doc/src/ch_c_mapping.xml @@ -770,24 +770,24 @@ CORBA_Environment* oe_env) <p>While the <c>erlang::binary</c> idl type has the same C-definition as a generated sequence of octets :</p> <code type="none"><![CDATA[ -\011 module erlang -\011 { + module erlang + { -\011 .... + .... -\011 // an erlang binary -\011 typedef sequence<octet> binary; -\011 -\011 }; + // an erlang binary + typedef sequence<octet> binary; + + }; ]]></code> <p>it provides a way on sending trasparent data between C and Erlang.</p> <p>The C-definition (ic.h) for an erlang binary is :</p> <code type="none"> -\011 typedef struct { -\011 CORBA_unsigned_long _maximum; -\011 CORBA_unsigned_long _length; -\011 CORBA_octet* _buffer; -\011 } erlang_binary; /* ERLANG BINARY */ + typedef struct { + CORBA_unsigned_long _maximum; + CORBA_unsigned_long _length; + CORBA_octet* _buffer; + } erlang_binary; /* ERLANG BINARY */ </code> <p>The differences (between <c>erlang::binary</c> and <c><![CDATA[sequence< octet >]]></c>) are :</p> <list type="bulleted"> diff --git a/lib/ic/doc/src/ch_erl_genserv.xml b/lib/ic/doc/src/ch_erl_genserv.xml index 972eff7c17..055b751ba1 100644 --- a/lib/ic/doc/src/ch_erl_genserv.xml +++ b/lib/ic/doc/src/ch_erl_genserv.xml @@ -168,18 +168,18 @@ handle_info(Info, State) -> %% IDL specification produce(State) -> case catch random:uniform() of -\\011{'EXIT',_} -> -\\011 {stop, normal, "random:uniform/0 - EXIT", State}; -\\011RUnif -> + {'EXIT',_} -> + {stop, normal, "random:uniform/0 - EXIT", State}; + RUnif -> {reply, RUnif, State} end. init(State, S1, S2, S3) -> case catch random:seed(S1, S2, S3) of -\\011{'EXIT',_} -> -\\011 {stop, normal, State}; -\\011_ -> + {'EXIT',_} -> + {stop, normal, State}; + _ -> {noreply, State} end. </code> diff --git a/lib/ic/doc/src/ch_erl_plain.xml b/lib/ic/doc/src/ch_erl_plain.xml index 36de46f624..1d6f84b5ea 100644 --- a/lib/ic/doc/src/ch_erl_plain.xml +++ b/lib/ic/doc/src/ch_erl_plain.xml @@ -75,7 +75,7 @@ <item> <p>Main file : "plain.idl"</p> <code type="none"> -\011 + module rmod { interface random { diff --git a/lib/ic/doc/src/ch_ic_protocol.xml b/lib/ic/doc/src/ch_ic_protocol.xml index 678fdc766c..68a01a6a46 100644 --- a/lib/ic/doc/src/ch_ic_protocol.xml +++ b/lib/ic/doc/src/ch_ic_protocol.xml @@ -69,9 +69,9 @@ <title>IDL Operations</title> <p>An IDL operation is declared as follows:</p> <code type="none"> -\011[oneway] RetType Op(in IType1 I1, in IType2 I2, ..., in ITypeN IN, -\011out OType1 O1, out OType2 O2, ..., out OTypeM OM) -\011N, M = 0, 1, 2, ...\011\011(2.1.1) + [oneway] RetType Op(in IType1 I1, in IType2 I2, ..., in ITypeN IN, + out OType1 O1, out OType2 O2, ..., out OTypeM OM) + N, M = 0, 1, 2, ... (2.1.1) </code> <p>`Op' is the operation name, RetType is the return type, and ITypei, i = 1, 2, ..., N, and OTypej, j = 1, 2, ..., M, are the `in' types @@ -146,13 +146,13 @@ <section> <title>Call (Request/Reply, i.e. not oneway)</title> <code type="none"> - request:\011\011 Op\011\011\011atom()\011\011N = 0\011 -\011\011\011 {Op, I1, I2, ..., IN}\011tuple()\011\011N > 0 -\011\011\011\011\011\011\011\011(3.1.1) + request: Op atom() N = 0 + {Op, I1, I2, ..., IN} tuple() N > 0 + (3.1.1) - reply:\011\011 Ret\011\011\011\011\011M = 0 -\011\011\011 {Ret, O1, O2, ..., OM}\011\011\011M > 0 -\011\011\011\011\011\011\011\011(3.1.2) </code> + reply: Ret M = 0 + {Ret, O1, O2, ..., OM} M > 0 + (3.1.2)</code> <p><em>Notice:</em> Even if the RetType of the operation Op is declared to be 'void', a return value 'ok' is returned in the reply message. That @@ -166,9 +166,9 @@ <title>Cast (oneway)</title> <code type="none"> - notification:\011Op\011\011\011atom()\011\011N = 0 -\011\011\011{Op, I1, I2, ..., IN}\011tuple()\011\011N > 0 -\011\011\011\011\011\011\011\011(3.2.1) </code> + notification: Op atom() N = 0 + {Op, I1, I2, ..., IN} tuple() N > 0 + (3.2.1)</code> <p>(There is of course no return message). </p> </section> @@ -184,9 +184,9 @@ <title>Call</title> <code type="none"> - request:\011{'$gen_call', {self(), Ref}, Request}\011\011(4.1.1) + request: {'$gen_call', {self(), Ref}, Request} (4.1.1) - reply:\011{Ref, Reply}\011\011\011\011\011(4.1.2) </code> + reply: {Ref, Reply} (4.1.2)</code> <p>where Request and Reply are the messages defined in the previous chapter. </p> @@ -195,7 +195,7 @@ <section> <title>Cast</title> <code type="none"> - notification: {'$gen_cast', Notification}\011\011(4.2.1) </code> + notification: {'$gen_cast', Notification} (4.2.1) </code> <p>where Notification is the message defined in the previous chapter. </p> </section> @@ -205,7 +205,7 @@ <title>Erlang Distribution Protocol</title> <p>Messages (of interest here) between Erlang nodes are of the form: </p> <code type="none"> - Len(4), Type(1), CtrlBin(N), MsgBin(M)\011\011\011(5.1) </code> + Len(4), Type(1), CtrlBin(N), MsgBin(M) (5.1) </code> <p>Type is equal to 112 = PASS_THROUGH. </p> <p>CtrlBin and MsgBin are Erlang terms in binary form (as if created @@ -215,10 +215,10 @@ <p>CtrlBin (of interest here) contains the SEND and REG_SEND control messages, which are binary forms of the Erlang terms</p> <code type="none"> -\011{2, Cookie, ToPid} ,\011\011\011\011\011(5.2) </code> + {2, Cookie, ToPid} , (5.2) </code> <p>and</p> <code type="none"> -\011{6, FromPid, Cookie, ToName} ,\011\011\011\011(5.3) </code> + {6, FromPid, Cookie, ToName} , (5.3) </code> <p>respectively. </p> <p>The CtrlBin(N) message is read and written by erl_interface code diff --git a/lib/ic/doc/src/ch_java.xml b/lib/ic/doc/src/ch_java.xml index 831850f211..a189daa44b 100644 --- a/lib/ic/doc/src/ch_java.xml +++ b/lib/ic/doc/src/ch_java.xml @@ -711,14 +711,14 @@ public class sHelper { // methods public static s unmarshal(OtpInputStream in) throws java.lang.Exception { -\011: -\011: + : + : }; public static void marshal(OtpOutputStream out, s value) throws java.lang.Exception { -\011: -\011: + : + : }; }; diff --git a/lib/ic/doc/src/erl-part.xml b/lib/ic/doc/src/erl-part.xml index b5041dce7f..8dd7001436 100644 --- a/lib/ic/doc/src/erl-part.xml +++ b/lib/ic/doc/src/erl-part.xml @@ -4,23 +4,21 @@ <part> <header> <copyright> - <year>2002</year> - <year>2007</year> - <holder>Ericsson AB, All Rights Reserved</holder> + <year>2002</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - The Initial Developer of the Original Code is Ericsson AB. + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + </legalnotice> <title>IDL to Erlang language Mapping</title> diff --git a/lib/ic/doc/src/ic_c_protocol.xml b/lib/ic/doc/src/ic_c_protocol.xml index f895fe0723..26862addf9 100644 --- a/lib/ic/doc/src/ic_c_protocol.xml +++ b/lib/ic/doc/src/ic_c_protocol.xml @@ -4,23 +4,21 @@ <cref> <header> <copyright> - <year>2004</year> - <year>2007</year> - <holder>Ericsson AB, All Rights Reserved</holder> + <year>2004</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - The Initial Developer of the Original Code is Ericsson AB. + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + </legalnotice> <title>IC C Protocol Functions</title> diff --git a/lib/ic/doc/src/java-part.xml b/lib/ic/doc/src/java-part.xml index 69cc0f026c..ab4049ee2a 100644 --- a/lib/ic/doc/src/java-part.xml +++ b/lib/ic/doc/src/java-part.xml @@ -4,23 +4,21 @@ <part> <header> <copyright> - <year>2002</year> - <year>2007</year> - <holder>Ericsson AB, All Rights Reserved</holder> + <year>2002</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - The Initial Developer of the Original Code is Ericsson AB. + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + </legalnotice> <title>IDL to Java language Mapping</title> diff --git a/lib/ic/doc/src/notes.xml b/lib/ic/doc/src/notes.xml index 021a1e058f..dbafde7b4b 100644 --- a/lib/ic/doc/src/notes.xml +++ b/lib/ic/doc/src/notes.xml @@ -37,9 +37,21 @@ <title>Fixed Bugs and Malfunctions</title> <list type="bulleted"> <item> + <p>Removed superfluous VT in the documentation.</p> + <p>Own id: OTP-8353 Aux Id:</p> + </item> + <item> <p>The option c_timeout was not correctly documented.</p> <p>Own id: OTP-8307 Aux Id: seq11390</p> </item> + <item> + <p>Removed superfluous backslash in the documentation.</p> + <p>Own id: OTP-8354 Aux Id:</p> + </item> + <item> + <p>The documentation EIX file was not generated.</p> + <p>Own id: OTP-8355 Aux Id:</p> + </item> </list> </section> </section> diff --git a/lib/ic/doc/src/old_notes.xml b/lib/ic/doc/src/old_notes.xml deleted file mode 100644 index 9ba0262573..0000000000 --- a/lib/ic/doc/src/old_notes.xml +++ /dev/null @@ -1,1565 +0,0 @@ -<?xml version="1.0" encoding="latin1" ?> -<!DOCTYPE chapter SYSTEM "chapter.dtd"> - -<chapter> - <header> - <copyright> - <year>2003</year><year>2009</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - </legalnotice> - - <title>IDL Compiler Release Notes</title> - <prepared></prepared> - <docno></docno> - <checked></checked> - <date>2003-11-19</date> - <rev>AB</rev> - </header> - - <section> - <title>IC 4.1.8</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>IDL-files containing <c>result</c> or <c>Result</c> as, - for example, parameter name, caused an exit with reason - <c>bad_match</c>.</p> - <p>Own Id: OTP-4532</p> - </item> - <item> - <p>Uninitialized variables were used in <c>ic_init_ref</c> for - C backends. </p> - <p>Own Id: OTP-4537 <br></br> - - Aux Id: seq7666, ETOtr17107</p> - </item> - <item> - <p><c>CORBA_Environment_alloc()</c> left some fields - uninitialized in the returned pointer to an - <c>CORBA_Environment</c> for C backends.</p> - <p>Own Id: OTP-4538</p> - </item> - <item> - <p>The function <c>ic_compare_refs()</c> for C backends - could find two unequal references to be equal.</p> - <p>Own Id: OTP-4539</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.1.7</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Operation names were always scoped in C server backend, - irrespective of the setting of the option - <c>scoped_op_calls</c>.</p> - <p>Own Id: OTP-4521 <br></br> - - Aux Id: seq7643, ETOtr16925</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.1.6</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>For C backends generated code checks that the - <c>_length</c> field of bounded sequences (i.e. specified - as <c><![CDATA[sequence <TYPE, MAX>]]></c>) does not exceed the - specified maximum length. If so, an exception is raised.</p> - <p>Own Id: OTP-4471</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The <c>_maximum</c> field was not set for sequence structs - generated by the C backends.</p> - <p>Own Id: OTP-4471 <br></br> - - Aux Id: seq7600, ETOtr16308</p> - </item> - <item> - <p>There was a memory leak in C backends in case there was a - decoding error in a sequence with elements of basic type.</p> - <p>Own Id: OTP-4475</p> - </item> - <item> - <p>For for C backends, IDL structs defined within an - interface were not mapped into C structs in appropriate - include files.</p> - <p>Own Id: OTP-4481 <br></br> - - Aux Id: seq7617</p> - </item> - <item> - <p>If the user, incorrectly, trap exit's but did not use the - 'handle_info' compile option it would cause the server to - terminate. The same problem occurred if someone, - illegally, sent a message to the server. It could also - happen for illegal oneway operations.</p> - <p>Own Id: OTP-4488</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.1.5</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Invalid C code was generated for type short. </p> - <p>Own Id: OTP-4450 <br></br> - - Aux Id: seq7582</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.1.4</title> - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Operation functions inherited by an interface were not - placed in the map table in generated code for the C server - backend. As a result such functions were not found by the - switch function of the interface.</p> - <p>Own Id: OTP-4448 <br></br> - - Aux Id: seq7582</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.1.3.1</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>A non-ANSI compliant construct in libic.a was changed.</p> - <p>Own Id: -</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.1.3</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>For Erlang and C back-ends an IC version stamp has been - added to generated source code. This stamp i preserved in - compiled target code.</p> - </item> - <item> - <p>For C backends an <c>assert()</c> expression has been - added to generated code. That expression asserts that the - result of a memory allocation size calculation is strictly - positive. An error will result in a printout and an - <c>abort()</c>. The assertion can be inhibited by defining - the macro <c>NDEBUG</c> (according to ANSI C).</p> - <p>If the assertion is inhibited, and a size calculation error - is detected, an INTERNAL CORBA exception is set. </p> - </item> - <item> - <p>An internal reorganization of C backend generator code has - been done (addition of module <c>ic_cclient</c>). Several - changes has been done in generated C code:</p> - <list type="bulleted"> - <item> - <p>The typedef <c>___generic___</c> has been replaced by - the typedef <c>___exec_function___</c>, which has been - made more strict; for backward compatibility the - <c>___generic___</c> typedef is now an alias for - <c>___exec_function___</c>.</p> - </item> - <item> - <p>Function parameters that are arrays, has been changed - to be pointers to array slices, which are equivalent - according to ANSI C. </p> - </item> - <item> - <p>The storage class specifier <c>extern</c> has been - removed from function prototypes in header files.</p> - </item> - <item> - <p>Redundant type casts have been removed from generated code. - Also some local "generic" variables have been renamed.</p> - </item> - </list> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Module info vsn replaced by app_vsn.</p> - <p>Own Id: OTP-4341</p> - </item> - <item> - <p>IC-4.1.2 disabled the definition of float constants - beginning with a zero (e.g. <c>0.14</c>).</p> - <p>Own Id: OTP-4367</p> - </item> - <item> - <p>IC did not handle constant definitions correctly for - char, string, wchar and wstring.</p> - <p>Own Id: OTP-4067, OTP-3222</p> - </item> - <item> - <p>IC did not recognize all reserved words defined in the - OMG specification (2.3.1). The new keywords are <c>fixed, abstract, custom, factory, local, native, private, public, supports, truncatable, 'ValueBase'</c> and - <c>valuetype</c>. But for now this is only active for the - <c>erl_corba</c> backend and only incorrect usage of - <c>fixed</c>, since this datatype is now supported, - triggers an error for this backend.</p> - <p>Own Id: OTP-4368</p> - </item> - <item> - <p>It was not possible to use wchar or wstring inside a - union body when using the Java backend.</p> - <p>Own Id: - OTP-4365</p> - </item> - <item> - <p>The compile options <c>this</c> and <c>handle_info</c> - did not behave as described in the documentation. The - <c>timeout</c> now behaves as, for example, - <c>handle_info</c>.</p> - <p>Own Id: OTP-4386, OTP-3231</p> - </item> - <item> - <p>If we typedef a sequence, which contains a struct or a union, - the access function <c>id/0</c> returned an incorrect IFR Id - if a prefix pragma was used.</p> - <p>Own Id: OTP-4387</p> - </item> - <item> - <p>If an IDL file contained a prefix pragma, incorrect - IFR-id's was generated in the IFR-registration operation - <c>oe_register</c> for aliases (typedef) and - attributes.</p> - <p>Own Id: OTP-4388, OTP-4392</p> - </item> - <item> - <p>For C back-ends, when encodings/decodings failed, memory - allocated for variable size parameter types was not freed.</p> - <p>Own Id: OTP-4391 - <br></br> -Aux Id: seq7438, ETOtr14009</p> - </item> - <item> - <p>If an IDL file contained a multiple typedef - (e.g. typedef string str1, str2;), the <c>oe_unregister</c> - operation failed to remove all data, in this case str2, - from the IFR.</p> - <p>Own Id: OTP-4393</p> - </item> - <item> - <p>IC did not recognize octet-constants - (e.g. const octet octetmax = 255;).</p> - <p>Own Id: OTP-4400</p> - </item> - <item> - <p>Negative 'long long' constants was not accepted - (e.g. const long long MyConstant = -1;).</p> - <p>Own Id: OTP-4401</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.1.2</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Merging of map's (<em>___map___</em>) using the - <em>___merge___</em> function does not work.</p> - <p>Own Id: OTP-4323</p> - </item> - <item> - <p>Error in generated C decode/encode functions for union's with - discriminator where the union has no value for all discriminator - values. E.g. a union with discriminator boolean where only the - discriminator value TRUE has a corresponding union value. - Here is how such a thing would look in IDL:</p> - <pre> -\011 union OptXList switch(boolean) { -\011 case TRUE: integer val; - }; - </pre> - <p>Own Id: OTP-4322</p> - </item> - <item> - <p>Scoped op calls ('{scoped_op_calls, true}') does not handle - module/function names beginning with capital letter (e.g. - Megaco should be 'Megaco') for oneway operations (handle_cast).</p> - <p>Own Id: OTP-4310</p> - </item> - <item> - <p>A bug is fixed on C-IDL erlang binaries that caused - pointer error when residing inside sequences.</p> - <p>Own Id: OTP-4303</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.1.1</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>A new option 'multiple_be' is added that allows multiple backend - generation for the same IDL file.</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>A bug is fixed on IDL types that contain underscore '_'.</p> - <p>Own Id: OTP-3710</p> - </item> - <item> - <p>A bug is fixed on IDL structs that caused scope confusion - when types and fields of a struct had the same name.</p> - <p>Own Id: OTP-2893</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.0.7</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>The Erlang binary special type is introduced, that - allows efficient transfer of binaries between Erlang and C. </p> - <p>Own Id:OTP-4107</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.0.6</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>A bug is fixed on noc backend which caused generation of erroneous code.</p> - <p>Own Id: OTP-3812</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.0.5</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>The pragma code option is extended to point - specific functions on NOC backend, not only - interfaces.</p> - <p></p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.0.4</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>A bug in pragma prefix when including IDL files is fixed. - This caused problems for Erlang-corba IFR registrations.</p> - <p>Own Id: OTP-3620</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.0.3</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Limited support on multiple file module definitions.</p> - <p>The current version supports multiple file module definitions all - backends except the c oriented backends.</p> - <p>Own Id: OTP-3550</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.0.2</title> - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>A bug is fixed on Erlang backends.</p> - <p>The (recently) introduced generation of files - describing sequence and array files were even - true for included interfaces. In the case of - some Erlang backends this were unnecessary.</p> - <p>Own Id: OTP-3485</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.0.1</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>New functionality added on Java and Erl_genserv backends.</p> - <p></p> - <list type="bulleted"> - <item> - <p>On the Java client stub :</p> - <p></p> - <list type="bulleted"> - <item> - <p>The Java client have now one more constructor function, - that allows to continue with an already started connection.</p> - </item> - <item> - <p><c>void __stop()</c> which sends a stop cast call to the server. - While this causes the Erlang server to terminate, it - sets a stop flag to the Java server environment, requesting the - server to terminate.</p> - </item> - <item> - <p><c>void __reconnect()</c> which closes the current client connection - if open and then connects to the same server.</p> - </item> - </list> - <p>The Environment variable is now declared as <c>public</c>. </p> - </item> - <item> - <p>On the Java server skeleton :</p> - <p></p> - <list type="bulleted"> - <item> - <p><c>boolean __isStopped()</c> which returns true if a <c>stop</c> - message where received, false otherwise. The user must check if - this function returns true, and in this case exit the implemented - server loop.</p> - </item> - </list> - <p>The Environment variable is now declared as <c>protected</c> which - allows the implementation that extends the stub to access it.</p> - </item> - <item> - <p>On the Erlang gen_server stub :</p> - <p></p> - <list type="bulleted"> - <item> - <p><c>stop(Server)</c> which yields to a cast call to the standard - gen_server <c>stop</c> function. This will always terminate the - Erlang gen_server, while it will set the stop flag for the - Java server stub.</p> - </item> - </list> - </item> - </list> - <p>Own Id: OTP-3433</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 4.0</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>New types handled by IC.</p> - <p>The following OMG-IDL types are added in this compiler version :</p> - <list type="bulleted"> - <item> - <p>long long</p> - <p>unsigned long long</p> - <p>wchar</p> - <p>wstring</p> - </item> - </list> - <p>Own Id: OTP-3331</p> - <p></p> - </item> - <item> - <p>TypeCode as built in type and access code files for array and sequence types.</p> - <list type="bulleted"> - <item> - <p>As TypeCode is a <c>pseudo</c>-interface, it is now is a built-in type on IC.</p> - </item> - <item> - <p>Access code files which contain information about TypeCode, ID and Name are - now generated for user defined arrays and sequences.</p> - </item> - </list> - <p>Own Id: OTP-3392</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 3.8.2</title> - <section> - <title>Fixed Bugs and Malfunctions</title> - <p>A bug is fixed on preprocessor directive expansion.</p> - <p>When nested #ifdef - #ifndef directives, a bug caused - improper included file expansion. This is fixed by - repairing the preprocessor expansion function.</p> - <p>Own Id: OTP-3472</p> - </section> - </section> - - <section> - <title>IC 3.8.1</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Build in Erlang types support for java-backends</p> - <p>The built-in Erlang types <c>term, port, ref</c> and <c>pid</c> - are needed in Java backends in order to support an - efficient mapping between the two languages. - The new types are also supported by additional - helpers and holders to match with OMGs Java mapping - As a result of this, the following classes are added to - the <c>com.ericsson.otp.ic</c> interface :</p> - <list type="bulleted"> - <item> - <p><c>Term,TermHelper,TermHolder</c> which represents the - built-in Erlang type <c>term</c></p> - </item> - <item> - <p><c>Ref,RefHelper,RefHolder</c> which represents the - built-in Erlang type <c>ref</c></p> - </item> - <item> - <p><c>Port,PortHelper, PortHolder</c> which represents the - built-in Erlang type <c>port</c></p> - </item> - <item><c>Pid, PidHelper and PidHolder</c> which represents the - built-in Erlang type <c>pid</c></item> - </list> - <p></p> - <p>Own Id: OTP-3348</p> - <p></p> - </item> - <item> - <p>Compile time preprocessor macro variable definitions</p> - <p>The preprocessor lacked possibility to accept user - defined variables other than the one defined in IDL files. - This limited the use of command-ruled IDL specifications. - Now the build-in preprocessor allows the user to set variables - by using the "preproc_flags" option the same way - as using the "gcc" preprocessor.</p> - <p>Supported flags : </p> - <list type="bulleted"> - <item> - <p><c><![CDATA["-D< Variable >"]]></c> which defines a variable</p> - </item> - <item> - <p><c><![CDATA["-U< Variable >"]]></c> which undefines a variable</p> - </item> - </list> - <p></p> - <p>Own Id: OTP-3349</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <p>A bug on comment type expansion is fixed.</p> - <p>The comment type expansion were erroneous when - inherited types (NOC backend). - This is now fixed and the type naming agree with - the scope of the inheritor interface.</p> - <p>Own Id: OTP-3346</p> - </section> - </section> - - <section> - <title>IC 3.8</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>The code generated for java backend is optimized - due to use of streams instead for tuple classes - when (un)marshalling message calls. - Support for building clients using asynchronous - client calls and effective multi-threaded servers.</p> - <p>Own Id: OTP-3310</p> - <p></p> - </item> - <item> - <p>The <c>any</c> type is now supported for java backend.</p> - <p>Own Id: OTP-3311</p> - </item> - </list> - </section> - - <section> - <title>A bug on C generated constants is fixed</title> - <p>While the constants are evaluated and behave well when used - inside an IDL specification their C-export were not working properly. - The constant export definitions were not generated well :</p> - <list type="bulleted"> - <item> - <p>the declared C definition were erroneous ( the name did not always agree - with the scope the constant were declared in ).</p> - </item> - <item> - <p>there were no C- definition generated for the c-server backend when - the constants were declared inside an interface.</p> - </item> - </list> - <p>Own Id: OTP-3219</p> - </section> - - <section> - <title>Incompatibilities</title> - <p>Due to optimizations in java backend, the stub initialization and usage - differs than the previous version.</p> - <p>Client stub interface changes:</p> - <list type="bulleted"> - <item> - <p>Client disconnects by calling the <c>__disconnect()</c> function instead - for the old <c>_closeConnection()</c></p> - <p></p> - </item> - <item> - <p>All <c>marshal</c> operation functions have now the interface :</p> - <p><c><![CDATA[void _< OpName >_marshal(Environment<, Param |, Params >)]]></c></p> - <p>instead for</p> - <p><c><![CDATA[OtpErlangTuple _< OpName >_marshal(< Param, | Params, >OtpErlangPid, OtpErlangRef)]]></c></p> - <p></p> - </item> - <item> - <p>All <c>unmarshal</c> operation functions have now the interface :</p> - <p><c><![CDATA[< Ret value > _< OpName >_unmarshal(Environment<, Param |, Params >)]]></c></p> - <p>instead for</p> - <p><c><![CDATA[< Ret value > _< OpName >_unmarshal(< Param, | Params, >OtpErlangTuple, OtpErlangRef)]]></c></p> - <p></p> - </item> - <item> - <p>Call reference extraction is available by the client function :</p> - <p><c>OtpErlangRef __getRef()</c></p> - <p>instead for previous function :</p> - <p><c>OtpErlangRef _getReference(OtpErlangTuple)</c></p> - <p></p> - </item> - </list> - <p>Server skeleton interface changes:</p> - <list type="bulleted"> - <item> - <p>The implementation function no longer have to contain the - two (2) contractor functions (with <c>super()</c>). This is due - to the fact that there is only one contractor function for each - skeleton file :</p> - <p><c><![CDATA[public _< interface name >ImplBase()]]></c></p> - <p></p> - </item> - <item> - <p>The parameter for the caller identity extraction function <c>_getCallerPid</c> - is now an <c>Environment</c> variable instead for an <c>OtpErlangTuple</c>.</p> - <p></p> - </item> - <item> - <p>There is a new <c>invoke</c> function :</p> - <p><c>OtpOutputStream invoke(OtpInputStream)</c></p> - <p>instead for the old one :</p> - <p><c>OtpErlangTuple invoke(OtpErlangTuple)</c></p> - <p></p> - </item> - <item> - <p>The <c>OtpConnection</c> class function used for receiving messages is now :</p> - <p><c>OtpInputStream receiveBuf()</c></p> - <p>instead for the old one :</p> - <p><c>OtpErlangTuple receive()</c></p> - <p></p> - </item> - <item> - <p>The <c>OtpConnection</c> class function used for sending messages is now :</p> - <p><c>void sendBuf(OtpErlangPid, OtpOutputStream)</c></p> - <p>instead for the old one :</p> - <p><c>void send(OtpErlangPid, OtpErlangTuple)</c></p> - <p></p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 3.7.1</title> - - <section> - <title>Improvements and New Features</title> - <p>Some memory usage optimizations for the compiler were done.</p> - </section> - - <section> - <title>Fixed bugs and malfunctions</title> - <list type="bulleted"> - <item> - <p>A bug is fixed when C backend is used.</p> - <p>When C-union with enumerant discriminator, the size - calculation of the discriminator value were erroneous. - This lead to the side effect that only the first case of the - union were allowed. - The error were fixed by fixing the size calculation of - the discriminator. </p> - <p>Own Id: OTP-3215</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 3.7</title> - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>A bug is fixed when C backend is used.</p> - <p>When unions with enumerant discriminator - were decoded, an error encountered in the - union size calculation. </p> - <p>Own Id: OTP-3209</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 3.6</title> - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>A bug is fixed when NOC backend is used.</p> - <p>When several functions with the same name - were found in the included file tree, - a compile time failure occurred.</p> - <p>Own Id: OTP-3203</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 3.5</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Noc backend optimization</p> - <p>When NOC backend is choosen, the type code - information on the stub functions is reduced - to a single atom "no_tk". - This is the default behavior. The typecode - generation is enabled by the "use_tk" switch.</p> - <p>Own Id: OTP-3196</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>General java backend bug fixes </p> - <p>Protocol errors on user defined structures and - union types are corrected.</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 3.4</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Semantic test enhancements.</p> - <p>The compiler detects now semantic errors when enumerant - values collide with user defined types on the same name scope.</p> - <p>Own Id: OTP-3157 <br></br> -</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>General java backend bug-fixes </p> - <p>Several bugs were fixed on user defined types.</p> - <list type="bulleted"> - <item> - <p>Union discriminators work better when - all possible case values are defined.</p> - </item> - <item> - <p>A bug on Interface inherited operations is - fixed that cause errors on generated server switch.</p> - </item> - <item> - <p>Type definitions on included files are better generated. </p> - </item> - </list> - <p>Own Id: OTP-3156 <br></br> -</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 3.3</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>A new back-end which generates Java code according to the CORBA IDL to Java mapping for - communication with the Erlang distribution protocol has been added to IC. - For the moment there is no support for the Erlang types Pid, Ref, Port and Term - but this will be added later.</p> - <p>Own Id: OTP-2779 <br></br> -</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Fixed the bug that the c code backends sometimes generated incorrect code for - struct arguments. They shall always be pointers. </p> - <p>Own Id: OTP-2732 <br></br> -</p> - </item> - <item> - <p>The code generation is fixed so the array parameters now follow the - CORBA V2.0 C mapping.</p> - <p>Own Id: OTP-2873 <br></br> -</p> - </item> - <item> - <p>Fixed the problem that the checking of the numbers of out-parameters always was true.</p> - <p>Own Id: OTP-2944 <br></br> -</p> - </item> - <item> - <p>Fixed the bug that some temporary variables was not declared when c code.</p> - <p>Own Id: OTP-2950 <br></br> -</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 3.2.2</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Unions are now supported to agree with OMG's C mapping.</p> - <p>Own Id: OTP-2868 <br></br> -</p> - </item> - <item> - <p>There is now a possibility to use pre- and postcondition methods on the server side - for IC generated Corba Objects. The compiler option is documented in the ic reference manual - and an example of how the pre- and postcondition methods should be designed and used is - added to ic example directory (an ReadMe.txt file exists with some instructions for - running the example code).</p> - <p>Own Id: OTP-3068 <br></br> -</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The compiler ignores unknown/non supported pragma directives. A warning is raised - while the generated code will then be the same as if the corresponding - (unknown) pragma directive were missing. </p> - <p>Own Id: OTP-3052 <br></br> -</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 3.2.1</title> - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Wrong C code was generated for limited strings when they where included - from another IDL specification.</p> - <p>Own Id: OTP-3033 <br></br> -</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 3.2</title> - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The buffers for in/output used by C-stubs are now expandable. - This fixes buffer overflow problems when messages received/sent - do not fit in buffers.</p> - <p>Own Id: OTP-3001 <br></br> -</p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <p>The CORBA_Environment structure has now two new fields, the buffers for in/output - must now be dynamically allocated.</p> - </section> - </section> - - <section> - <title>IC 3.1.2</title> - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The generated IFR registration function for constants has been fixed - so the parameters are correct.</p> - <p>Own Id: OTP-2856 <br></br> -</p> - </item> - <item> - <p>Error in the C code generation of ONEWAY operations without parameters - The bug was an decoding error in the operation header. The generated code expected one - parameter instead of zero. This is now fixed.</p> - <p>Own Id: OTP-2909 <br></br> -</p> - </item> - <item> - <p>Type problems on floats and booleans fixed.</p> - <p>Erroneous code for runtime checks on float was removed and - the internal format of the data representing the boolean value - is upgraded.</p> - <p>Own Id: OTP-2925 <br></br> -</p> - </item> - <item> - <p>The generated code for arrays of typedefined strings were - erroneous in the C-backends due to a failure in the compiler internal type - checking.</p> - <p>Own Id: OTP-2936 <br></br> -</p> - </item> - <item> - <p>The generated code for typedefined nested sequences were erroneous - in the C-backends. Pointer mismatches caused compilation failure.</p> - <p>Own Id: OTP-2937 <br></br> -</p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <p>The IDL specifications must be regenerated for C due to changes in the code generation.</p> - <p>One must regenerate IDL specifications for Erlang CORBA if there are constants in the - specification due to previous errors in the IFR registration functions (OTP-2856).</p> - </section> - </section> - - <section> - <title>IC 3.1.1</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Improvements on error report on unsupported types by</p> - <p>propagating warning when declaring unions in C -backends</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>A bug is fixed when arrays that contained variable size data - on C-backends</p> - <p>The compiler generated erroneous code when IDL - defined arrays that contained variable size data such - as strings, variable size structs or sequences.</p> - <p>Own Id: OTP-2900 <br></br> -</p> - </item> - <item> - <p>A bug is fixed when sequences that contained variable size data - on C_backends</p> - <p>The compiler generated erroneous code when IDL - defined arrays that contained variable size data such - as strings, variable size structs or other sequences.</p> - <p>Own Id: OTP-2901 <br></br> -</p> - </item> - <item> - <p>A bug concerning bounded strings on C-backends is fixed.</p> - <p>The compiler generated erroneous code for IDL - defined bounded strings. Syntax errors were generated - in special cases of typdedefined strings.</p> - <p>Own Id: OTP-2898 <br></br> -</p> - </item> - <item> - <p>A runtime error when sequences that contained integer types is fixed.</p> - <p>When C-clients/server that communicated with Erlang clients/servers, - and the data send by Erlang part were a list of small numbers, - the Erlang runtime compacts the list to a string. This caused a - runtime error when sending sequences of integer types and all had - value less than 256.</p> - <p>Own Id: OTP-2899 <br></br> -</p> - </item> - <item> - <p>An OMG IDL - C mapping problem on enumerant values is fixed.</p> - <p>The enumerant values names is now prefixed by the current scope, - as defined in the specification.</p> - <p>Own Id: OTP-2902 <br></br> -</p> - </item> - <item> - <p>A problem when using constants in array declarations is fixed.</p> - <p>Array dimensions declared with constants generated erroneous code.</p> - <p>Own Id: OTP-2864 <br></br> -</p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <list type="bulleted"> - <item> - <p>Changes in C-generation on enumerant values.</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 3.1</title> - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>A bug is fixed on the generated structures. </p> - <p>The generated C code for the structures corresponds now - to direct mapping of C-structs. </p> - <p>Own Id: OTP-2843 <br></br> -</p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <list type="bulleted"> - <item> - <p>Included structures inside a struct are no longer pointers.</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 3.0</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Interface change for C-backends</p> - <p>Major interface change. The new interface is CORBA 2.0 - compliant.</p> - <p>Own Id: OTP-2845 <br></br> -</p> - </item> - <item> - <p>The C-backends functionality is improved</p> - <list type="bulleted"> - <item> - <p>Due to interface change and some unneeded error - checks,the C-generated code is fairly optimized.</p> - </item> - </list> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Several serious bugs on decoding and memory allocation are fixed. </p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <list type="bulleted"> - <item> - <p>Interface change on the C-backends</p> - <p>In order to be CORBA 2.0 compatible, the new version - generates fully incompatible C code.</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 2.5.1</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>A new backend is added : C-server</p> - <p>This back-ends can be used to create servers, - compatible to c-clients, and Erlang genserver clients. - The code produced is a collection of functions for - encoding and decoding messages and a switch that coordinates - them. These parts can be used to create other servers as well. - All functions are exported to header files.</p> - <p>Own Id: OTP-2713 <br></br> -</p> - </item> - <item> - <p>The C-client functionality is improved</p> - <list type="bulleted"> - <item> - <p>The static buffer used for input/output is removed along - with the <c>memset</c> function that initiated it. - The new client is at least 20-30 percent faster.</p> - </item> - <item> - <p>The internal structure of the client is changed. - The client functions are now a collection of encoding - and decoding message functions ruled by a specific - call function. While the basic client generated is - a synchronous client, the exported functions - support the implementation of threaded asynchronous - clients.</p> - </item> - <item> - <p>The static buffer used for input/output is remove along - with the <c>memset</c> function that initiated it. - The new client is at least 20-30 percent faster.</p> - </item> - <item> - <p>The code generated is generally improved, warnings are - (almost) eliminated, while no unidentified variable - errors occur.</p> - </item> - <item> - <p>The IDL types unsigned shorts, shorts, floats are supported now.</p> - </item> - <item> - <p>All generated functions are exported in client header files..</p> - </item> - </list> - <p>Own Id: OTP-2712 <br></br> -</p> - </item> - </list> - </section> - - <section> - <title>Changes in compiler usage and code generation.</title> - <list type="bulleted"> - <item> - <p>A new option is added for the C-server back-end : <c>c_server</c>.</p> - </item> - <item> - <p>A new option is added : <c>scoped_op_calls</c>.</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>A bug oneway operations on erl_corba and erl_genserv that caused - en exit due to internal interface error is fixed. </p> - </item> - <item> - <p>A bug on oneway operations on c_genserv back-end that caused several - variables to be unidentified is fixed. </p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <list type="bulleted"> - <item> - <p>Interface change on the C-client</p> - <p>The client functions are called with two extra variables, a pointer to - an array of char - used for storage and an integer - the array size</p> - </item> - <item> - <p>The IDL type <c>attribute</c> is disabled, due to some implementation problems.</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 2.1</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>The compiler now provides more in depth information (printouts) when errors occur.</p> - <p>In some cases the compiler stops compiling - due to an abnormal exit or incompatible input. - In this situation, a "fatal error" may occur but the compiler will - generate information explaining the problem.</p> - <p>Own Id: OTP-2565 <br></br> -</p> - </item> - </list> - </section> - </section> - - <section> - <title>IC 2.0</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>The IDL compiler is now a separate application and is longer a part of Orber.</p> - </item> - <item> - <p>Pragma handling implementation.</p> - <p>Pragma ID, prefix - and version are implemented to agree with CORBA revision - 2.0. The compiler accepts and applies these on the - behavior of the compiled code. <br></br> - In this implementation, - pragmas are accepted by the parser and applied by the use - of ic_pragma functions. <br></br> - All IFR-identity handling now - passes through pragma table. As pragma handling in OMG-IDL - is affecting the identity of an ifr-object, all identity - handling and registration is now controlled by pragma - functions. A hash table called "pragmatab" contains vital - identity information used under compilation. <br></br> -</p> - <p>There two major pragma categories :</p> - <list type="bulleted"> - <item> - <p>Normal pragmas, are used in the code where - basic definitions and statements appear. </p> - </item> - <item> - <p>Under certain circumstances, ugly pragmas can now - appear inside code, parameter lists, structure - definitions ... etc. <br></br> - It is quite challenging to - allow ugly pragmas, but the effects of unlimited ugly - pragma implementation on the parser can be enormous. - Ugly pragmas can cause the parser source code to - become time consuming and user unreadable. <br></br> - In order - to allow ugly pragmas but not destroy the current - structure of the parser, the use of ugly pragmas is - limited. Multiple pragma directives are allowed - inside parameter lists, unions, exceptions, - enumerated type, structures... as long as they are do not - appear between two keywords or between keywords and - identifiers. </p> - </item> - </list> - <p>The pragma effect is the same for both scope and basic - pragma rules. </p> - <p>When compiling, an IFR-identity - must be looked up several times but by storing identity aliases inside - the pragma table there this an increase in both speed and - flexibility. </p> - <p>Own Id: OTP-2128 <br></br> -</p> - </item> - <item> - <p>Code for interface inheritance registration for the IFR - registration code .</p> - <p>Inherited interfaces can now - be registered as a list of interface descriptions by - entering code for inherited interface registration under - new interface creation. This is achieved by correcting the - function reg2/6 and adding two more functions, - get_base_interfaces/2 and call_fun_str/2 </p> - <p>Own Id: - OTP-2134 <br></br> -</p> - </item> - <item> - <p>IFR registration checks for included IDL files.</p> - <p>All top level definitions (with respect to the scope) - - modules, interfaces, constants, types or exceptions - found - in an IDL file are either defined inside the compiled IDL - file or inside included files. - By having an extended registration of all top level - definitions it becomes possible to simply produce checks - for those included by the current IDL file. - A function call include_reg_test/1 is added in all - OE_* files that checks for IFR-registration on all included - IDL files. The code for that function is added inside the - OE_* file, while the function is called under OE_*:OE_register/0 - operation. </p> - <p>Own Id: OTP-2138 <br></br> -</p> - </item> - <item> - <p>Exception registration under IFR-operation creation.</p> - <p>By entering code for exception registration under operation - creation, the exceptions of an operation can be checked now. - This is done by correcting the function get_exceptions/4 - and adding two more functions, excdef/5 and get_EXC_ID/5 - ( the last two are cooperating with the first one and - all three are defined in the module "ictk" ). </p> - <p>Own Id: OTP-2102 <br></br> -</p> - </item> - <item> - <p>New back-end to IDL compiler : Plain Erlang.</p> - <p>The new back-end just translates IDL specifications - to Erlang module calls. No pragmas are allowed.</p> - <p>Own Id: OTP-2471 <br></br> -</p> - </item> - <item> - <p>New back-end to IDL compiler : generic server.</p> - <p>A new back-end that translates IDL specifications - to a standard OTP generic server.</p> - <p>Own Id: OTP-2482 <br></br> -</p> - </item> - <item> - <p>New back-end to IDL compiler : c client generation</p> - <p>A new back-end that translates IDL specifications - to a C API for accessing servers in Erlang. </p> - <p>Own Id: OTP-1511 <br></br> -</p> - </item> - <item> - <p>All records in generated files reveal own Erlang modules.</p> - <p>In Erlang related back-ends, every structure - which generates definition form is a record, - (such as union, struct, exception.... ). These records are - held in a generated Erlang files which - contain functions that reveal record information. <br></br> - - The Erlang file which contain these functions is - named after the scope of the record (similar - to the generated module and interface files). <br></br> - - Three functions are available :</p> - <list type="bulleted"> - <item> - <p>tc/0 - returns the record type code,</p> - </item> - <item> - <p>id/0 - returns the record id,</p> - </item> - <item> - <p>name - returns the record name.</p> - </item> - </list> - <p>Own Id: OTP-2473 <br></br> -</p> - </item> - <item> - <p>Changes in compiler usage and code generation.</p> - <list type="bulleted"> - <item> - <p>New compilation flags. - New flag be ( = back-end ) which is - used by the compiler to choose back-end. - Default back-end is set to erl_corba.</p> - </item> - <item> - <p>Stub files have an extra function oe_dependency/0 - indicating file dependency. This - helps the user to determine which IDL files should to - be compiled beside the compiled file. </p> - </item> - </list> - <p>Own Id: OTP-2474 <br></br> -</p> - </item> - <item> - <p>The IDL generation for CORBA is changed so standard gen_server return values can be used - from the implementation module. The change is compatible so that old values remain valid.</p> - <p>Own Id: OTP-2485 <br></br> -</p> - </item> - <item> - <p>It's now possible to generate an API to a CORBA object that accepts - timeout values in the calls in the same manner as gen_server. - The option to the compiler is "timeout".</p> - <p>Own Id: OTP-2487 <br></br> -</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Empty file generation problem is fixed. - When the IDL module definition did not contain - constant definitions, the generated stub file for that module - definition was empty. After checking the module body, - these files will not be generated anymore.</p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <list type="bulleted"> - <item> - <p>Changes in generated files.</p> - <p>Stub-files generated by the compiler had - prefix "OE_" and those used by Orber - had also a register/unregister function - called "OE_register"/"OE_unregister" and - a directive "OE_get_interface" passed - to the gen_server. - This made it difficult/irritating to use, - for example call to the register function - in Orber would appear as shown below:</p> - <list type="bulleted"> - <item> - <p>'OE_filename':'OE_register'().</p> - </item> - </list> - <p>This is changed by using the prefix "oe_" - instead for "OE_" for the above. - A registration call in Orber is now written:</p> - <list type="bulleted"> - <item> - <p>oe_filename:oe_register(). </p> - </item> - </list> - <p>Own Id: OTP-2440 <br></br> -</p> - </item> - </list> - </section> - </section> -</chapter> - diff --git a/lib/ic/vsn.mk b/lib/ic/vsn.mk index ec4bb7c3a6..e0fccf4889 100644 --- a/lib/ic/vsn.mk +++ b/lib/ic/vsn.mk @@ -1,6 +1,9 @@ IC_VSN = 4.2.24 -TICKETS = OTP-8307 +TICKETS = OTP-8307 \ + OTP-8353 \ + OTP-8354 \ + OTP-8355 TICKETS_4.2.23 = OTP-8201 diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 018f7f41d2..d4e3f0bcf8 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -1479,13 +1479,12 @@ finish_on_load(Ref, OnLoadRes, #state{on_load=OnLoad0,moddb=Db}=State) -> end. finish_on_load_1(Mod, File, OnLoadRes, WaitingPids, Db) -> - Keep = if - is_boolean(OnLoadRes) -> OnLoadRes; - true -> false - end, + Keep = OnLoadRes =:= ok, erlang:finish_after_on_load(Mod, Keep), Res = case Keep of - false -> {error,on_load_failure}; + false -> + finish_on_load_report(Mod, OnLoadRes), + {error,on_load_failure}; true -> ets:insert(Db, {Mod,File}), {module,Mod} @@ -1493,6 +1492,24 @@ finish_on_load_1(Mod, File, OnLoadRes, WaitingPids, Db) -> [reply(Pid, Res) || Pid <- WaitingPids], ok. +finish_on_load_report(_Mod, Atom) when is_atom(Atom) -> + %% No error reports for atoms. + ok; +finish_on_load_report(Mod, Term) -> + %% Play it very safe here. The error_logger module and + %% modules it depend on may not be loaded yet and there + %% would be a dead-lock if we called it directly + %% from the code_server process. + spawn(fun() -> + F = "The on_load function for module " + "~s returned ~P\n", + + %% Express the call as an apply to simplify + %% the ext_mod_dep/1 test case. + E = error_logger, + E:warning_msg(F, [Mod,Term,10]) + end). + %% ------------------------------------------------------- %% Internal functions. %% ------------------------------------------------------- diff --git a/lib/kernel/src/pg2.erl b/lib/kernel/src/pg2.erl index fc9508a194..cb9fec2ffe 100644 --- a/lib/kernel/src/pg2.erl +++ b/lib/kernel/src/pg2.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% -module(pg2). @@ -334,8 +334,11 @@ local_group_members(Name) -> P <- member_in_group(Pid, Name)]. member_in_group(Pid, Name) -> - [{{member, Name, Pid}, N}] = ets:lookup(pg2_table, {member, Name, Pid}), - lists:duplicate(N, Pid). + case ets:lookup(pg2_table, {member, Name, Pid}) of + [] -> []; + [{{member, Name, Pid}, N}] -> + lists:duplicate(N, Pid) + end. member_groups(Pid) -> [Name || [Name] <- ets:match(pg2_table, {{pid, Pid, '$1'}})]. diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 9fda66711d..38aadac202 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -31,12 +31,17 @@ where_is_file_cached/1, where_is_file_no_cache/1, purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1, code_archive/1, code_archive2/1, on_load/1, - on_load_embedded/1]). + on_load_embedded/1, on_load_errors/1]). -export([init_per_testcase/2, fin_per_testcase/2, init_per_suite/1, end_per_suite/1, sticky_compiler/1]). +%% error_logger +-export([init/1, + handle_event/2, handle_call/2, handle_info/2, + terminate/2]). + all(suite) -> [set_path, get_path, add_path, add_paths, del_path, replace_path, load_file, load_abs, ensure_loaded, @@ -47,7 +52,8 @@ all(suite) -> load_cached, start_node_with_cache, add_and_rehash, where_is_file_no_cache, where_is_file_cached, purge_stacktrace, mult_lib_roots, bad_erl_libs, - code_archive, code_archive2, on_load, on_load_embedded]. + code_archive, code_archive2, on_load, on_load_embedded, + on_load_errors]. init_per_suite(Config) -> %% The compiler will no longer create a Beam file if @@ -671,6 +677,8 @@ check_funs({'$M_EXPR','$F_EXPR',2}, check_funs({'$M_EXPR','$F_EXPR',1}, [{lists,foreach,2}, {hipe_unified_loader,patch_consts,3} | _]) -> 0; +check_funs({'$M_EXPR',warning_msg,2}, + [{code_server,finish_on_load_report,2} | _]) -> 0; %% This is cheating! /raimo %% %% check_funs(This = {M,_,_}, Path) -> @@ -1229,6 +1237,81 @@ is_source_dir() -> filename:basename(code:lib_dir(kernel)) =:= "kernel" andalso filename:basename(code:lib_dir(stdlib)) =:= "stdlib". +on_load_errors(Config) when is_list(Config) -> + Master = on_load_error_test_case_process, + ?line register(Master, self()), + + ?line Data = filename:join([?config(data_dir, Config),"on_load_errors"]), + ?line ok = file:set_cwd(Data), + ?line up_to_date = make:all([{d,'MASTER',Master}]), + + ?line do_on_load_error(an_atom), + + ?line error_logger:add_report_handler(?MODULE, self()), + + ?line do_on_load_error({something,terrible,is,wrong}), + receive + Any1 -> + ?line {_, "The on_load function"++_, + [on_load_error, + {something,terrible,is,wrong},_]} = Any1 + end, + + ?line do_on_load_error(fail), %Cause exception. + receive + Any2 -> + ?line {_, "The on_load function"++_, + [on_load_error,{failed,[_|_]},_]} = Any2 + end, + + %% There should be no more messages. + receive + Unexpected -> + ?line ?t:fail({unexpected,Unexpected}) + after 10 -> + ok + end, + + ok. + +do_on_load_error(ReturnValue) -> + ?line {_,Ref} = spawn_monitor(fun() -> + exit(on_load_error:main()) + end), + receive {on_load_error,ErrorPid} -> ok end, + ?line ErrorPid ! ReturnValue, + receive + {'DOWN',Ref,process,_,Exit} -> + ?line {undef,[{on_load_error,main,[]}|_]} = Exit + end. + +%%----------------------------------------------------------------- +%% error_logger handler. +%% (Copied from stdlib/test/proc_lib_SUITE.erl.) +%%----------------------------------------------------------------- +init(Tester) -> + {ok, Tester}. + +handle_event({error, _GL, {emulator, _, _}}, Tester) -> + {ok, Tester}; +handle_event({error, _GL, Msg}, Tester) -> + Tester ! Msg, + {ok, Tester}; +handle_event(_Event, State) -> + {ok, State}. + +handle_info(_, State) -> + {ok, State}. + +handle_call(_Query, State) -> {ok, {error, bad_query}, State}. + +terminate(_Reason, State) -> + State. + +%%% +%%% Common utility functions. +%%% + start_node(Name, Param) -> ?t:start_node(Name, slave, [{args, Param}]). diff --git a/lib/kernel/test/code_SUITE_data/on_load/on_load_a.erl b/lib/kernel/test/code_SUITE_data/on_load/on_load_a.erl index 660000df46..f6bcb6570b 100644 --- a/lib/kernel/test/code_SUITE_data/on_load/on_load_a.erl +++ b/lib/kernel/test/code_SUITE_data/on_load/on_load_a.erl @@ -13,7 +13,7 @@ on_load() -> LibDir = code:lib_dir(kernel), ?MASTER ! {?MODULE,LibDir}, - true. + ok. data() -> [a|on_load_b:data()]. diff --git a/lib/kernel/test/code_SUITE_data/on_load/on_load_b.erl b/lib/kernel/test/code_SUITE_data/on_load/on_load_b.erl index 5c4d676e2d..947cbd5bcd 100644 --- a/lib/kernel/test/code_SUITE_data/on_load/on_load_b.erl +++ b/lib/kernel/test/code_SUITE_data/on_load/on_load_b.erl @@ -6,7 +6,7 @@ on_load() -> ?MASTER ! {?MODULE,start}, on_load_c:data(), ?MASTER ! {?MODULE,done}, - true. + ok. data() -> [b|on_load_c:data()]. diff --git a/lib/kernel/test/code_SUITE_data/on_load/on_load_c.erl b/lib/kernel/test/code_SUITE_data/on_load/on_load_c.erl index 4b2edbfb5a..6ab7f6402f 100644 --- a/lib/kernel/test/code_SUITE_data/on_load/on_load_c.erl +++ b/lib/kernel/test/code_SUITE_data/on_load/on_load_c.erl @@ -7,7 +7,7 @@ on_load() -> receive go -> ?MASTER ! {?MODULE,done}, - true + ok end. data() -> diff --git a/lib/kernel/test/code_SUITE_data/on_load_app-1.0/src/on_load_embedded.erl b/lib/kernel/test/code_SUITE_data/on_load_app-1.0/src/on_load_embedded.erl index bfc26864d5..a39332f81d 100644 --- a/lib/kernel/test/code_SUITE_data/on_load_app-1.0/src/on_load_embedded.erl +++ b/lib/kernel/test/code_SUITE_data/on_load_app-1.0/src/on_load_embedded.erl @@ -9,7 +9,7 @@ run_me() -> ok end end), - true. + ok. status() -> case whereis(everything_is_fine) of diff --git a/lib/kernel/test/code_SUITE_data/on_load_errors/on_load_error.erl b/lib/kernel/test/code_SUITE_data/on_load_errors/on_load_error.erl new file mode 100644 index 0000000000..0772050aeb --- /dev/null +++ b/lib/kernel/test/code_SUITE_data/on_load_errors/on_load_error.erl @@ -0,0 +1,13 @@ +-module(on_load_error). +-on_load(on_load/0). +-export([main/0]). + +on_load() -> + ?MASTER ! {?MODULE,self()}, + receive + fail -> erlang:error(failed); + Ret -> Ret + end. + +main() -> + ok. diff --git a/lib/observer/src/crashdump_viewer.erl b/lib/observer/src/crashdump_viewer.erl index b323d86ea4..978541e470 100644 --- a/lib/observer/src/crashdump_viewer.erl +++ b/lib/observer/src/crashdump_viewer.erl @@ -1272,6 +1272,9 @@ get_general_info(Fd,GenInfo) -> get_general_info(Fd,GenInfo#general_info{system_vsn=val(Fd)}); "Compiled" -> get_general_info(Fd,GenInfo#general_info{compile_time=val(Fd)}); + "Taints" -> + Val = case val(Fd) of "-1" -> "(none)"; Line -> Line end, + get_general_info(Fd,GenInfo#general_info{taints=Val}); "Atoms" -> get_general_info(Fd,GenInfo#general_info{num_atoms=val(Fd)}); "=" ++ _next_tag -> diff --git a/lib/observer/src/crashdump_viewer.hrl b/lib/observer/src/crashdump_viewer.hrl index 386d3bb423..6ce727cd3e 100644 --- a/lib/observer/src/crashdump_viewer.hrl +++ b/lib/observer/src/crashdump_viewer.hrl @@ -26,6 +26,7 @@ slogan, system_vsn, compile_time, + taints, node_name, num_atoms, num_procs, diff --git a/lib/observer/src/crashdump_viewer_html.erl b/lib/observer/src/crashdump_viewer_html.erl index 5fa829ed37..5e7bbf62a0 100644 --- a/lib/observer/src/crashdump_viewer_html.erl +++ b/lib/observer/src/crashdump_viewer_html.erl @@ -215,6 +215,8 @@ general_info_body(Heading,GenInfo) -> td(GenInfo#general_info.system_vsn)]), tr([th("ALIGN=left BGCOLOR=\"#8899AA\"","Compiled"), td(GenInfo#general_info.compile_time)]), + tr([th("ALIGN=left BGCOLOR=\"#8899AA\"","Taints"), + td(GenInfo#general_info.taints)]), case GenInfo#general_info.mem_tot of "" -> ""; MemTot -> diff --git a/lib/orber/doc/src/Makefile b/lib/orber/doc/src/Makefile index 40f5ef8708..c82db49c9b 100644 --- a/lib/orber/doc/src/Makefile +++ b/lib/orber/doc/src/Makefile @@ -64,7 +64,6 @@ XML_REF3_FILES = \ orber_acl.xml XML_PART_FILES = \ - part_notes_history.xml \ part.xml \ part_notes.xml @@ -85,10 +84,6 @@ XML_CHAPTER_FILES = \ ch_orberweb.xml \ ch_debugging.xml -XML_HTML_FILES = \ - notes_history.xml - - BOOK_FILES = book.xml XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \ @@ -124,7 +119,6 @@ INTERNAL_HTML_FILES = $(TECHNICAL_DESCR_FILES:%.xml=$(HTMLDIR)/%.html) HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \ $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html) \ - $(XML_HTML_FILES:%.xml=$(HTMLDIR)/%.html) \ $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html) INFO_FILE = ../../info diff --git a/lib/orber/doc/src/ch_contents.xml b/lib/orber/doc/src/ch_contents.xml index 65383805b3..602955764d 100644 --- a/lib/orber/doc/src/ch_contents.xml +++ b/lib/orber/doc/src/ch_contents.xml @@ -112,8 +112,8 @@ A concise history of Orber.</p> <title>IDL to Erlang Mapping</title> <p>The OMG IDL mapping for Erlang, which is necessary to access the functionality of Orber, is described, The mapping structure is - included as the\011basic and the constructed OMG IDL types - references, invocations\011and Erlang characteristics. An example is + included as the basic and the constructed OMG IDL types + references, invocations and Erlang characteristics. An example is also provided.</p> </section> diff --git a/lib/orber/doc/src/ch_example.xml b/lib/orber/doc/src/ch_example.xml index d4cc5ceddc..f2ccfcc7e1 100644 --- a/lib/orber/doc/src/ch_example.xml +++ b/lib/orber/doc/src/ch_example.xml @@ -45,7 +45,7 @@ <title>Generating Erlang Code</title> <p>Run the IDL compiler on this file by calling the <c>ic:gen/1</c> function </p> <code type="erl"> -\0111> ic:gen("stack"). + 1> ic:gen("stack"). </code> <p>This will produce the client stub and server skeleton. Among other files a stack API module named <c>StackModule_Stack.erl</c> will be produced. diff --git a/lib/orber/doc/src/ch_idl_to_erlang_mapping.xml b/lib/orber/doc/src/ch_idl_to_erlang_mapping.xml index 0e2b049ab9..a97ad65f0e 100644 --- a/lib/orber/doc/src/ch_idl_to_erlang_mapping.xml +++ b/lib/orber/doc/src/ch_idl_to_erlang_mapping.xml @@ -286,15 +286,15 @@ typedef string<10> myString10; typedef wstring<10> myWString10; ]]></code> <p>If we want to define a char/string or wchar/wstring constant, we can - use octal (\\OOO - one, two or three octal digits), - hexadecimal (\\xHH - one or two hexadecimal digits) and unicode (\\uHHHH - + use octal (\OOO - one, two or three octal digits), + hexadecimal (\xHH - one or two hexadecimal digits) and unicode (\uHHHH - one, two, three or four hexadecimal digits.) representation as well. For example:</p> <code type="none"> -const string SwedensBestSoccerTeam = "\\101" "\\x49" "\\u004B"; -const wstring SwedensBestHockeyTeam = L"\\101\\x49\\u004B"; -const char aChar = '\\u004B'; -const wchar aWchar = L'\\u004C'; +const string SwedensBestSoccerTeam = "\101" "\x49" "\u004B"; +const wstring SwedensBestHockeyTeam = L"\101\x49\u004B"; +const char aChar = '\u004B'; +const wchar aWchar = L'\u004C'; </code> <p>Naturally, we can use <c>"Erlang"</c>, <c>L"Rocks"</c>, <c>'A'</c> and <c>L'A'</c> as well.</p> @@ -697,14 +697,14 @@ module DB { module x { struct y_z { -\011... + ... }; interface y { -\011struct z { -\011 ... -\011}; + struct z { + ... + }; }; }; </code> @@ -815,7 +815,7 @@ module m { const float pi = 3.14; interface i { -\011const float pi = 3.1415; + const float pi = 3.1415; }; }; </code> @@ -1036,19 +1036,19 @@ $> erlc +"{be,erl_template}" DB.idl %% Description: %%---------------------------------------------------------------------- logon(State, ID, PW) -> -\011%% Check if the ID/PW is valid and what -\011%% type of user it is (Common or Administrator). -\011OE_Reply + %% Check if the ID/PW is valid and what + %% type of user it is (Common or Administrator). + OE_Reply = case check_user(ID, PW) of -\011 {ok, administrator} -> -\011 'DB_Administrator':oe_create(); -\011 {ok, common} -> -\011 'DB_CommonUser':oe_create(); -\011 error -> -\011 %% Here we should throw an exception - \011 corba:raise(....) + {ok, administrator} -> + 'DB_Administrator':oe_create(); + {ok, common} -> + 'DB_CommonUser':oe_create(); + error -> + %% Here we should throw an exception + corba:raise(....) end, -\011{reply, OE_Reply, State}. + {reply, OE_Reply, State}. %%====================================================================== %% Internal Functions @@ -1064,7 +1064,7 @@ logon(State, ID, PW) -> %% Description: Initiates the server %%---------------------------------------------------------------------- init(_Env) -> -\011{ok, #state{}}. + {ok, #state{}}. %%---------------------------------------------------------------------- @@ -1076,7 +1076,7 @@ init(_Env) -> %% Description: Invoked when the object is terminating. %%---------------------------------------------------------------------- terminate(_Reason, _State) -> -\011ok. + ok. %%---------------------------------------------------------------------- @@ -1090,7 +1090,7 @@ terminate(_Reason, _State) -> %% due to code replacement. %%---------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> -\011{ok, State}. + {ok, State}. %%---------------------------------------------------------------------- @@ -1104,7 +1104,7 @@ code_change(_OldVsn, State, _Extra) -> %% Description: Invoked when, for example, the server traps exits. %%---------------------------------------------------------------------- handle_info(_Info, State) -> -\011{noreply, State}. + {noreply, State}. ]]></code> <p>Since <c>DB_Administrator</c> inherits from <c>DB_CommonUser</c>, we must implement <c>delete</c> in the <c>DB_Administrator_impl.erl</c> @@ -1421,11 +1421,11 @@ interface i { </row> <row> <cell align="left" valign="middle">{tk_objref, IFRId, Name}</cell> - <cell align="left" valign="middle">{tk_objref, "IDL:M1\\I1:1.0", "I1"}</cell> + <cell align="left" valign="middle">{tk_objref, "IDL:M1\I1:1.0", "I1"}</cell> </row> <row> <cell align="left" valign="middle">{tk_struct, IFRId, Name, [{ElemName, ElemTC}]}</cell> - <cell align="left" valign="middle">{tk_struct, "IDL:M1\\S1:1.0", "S1", [{"a", tk_long}, {"b", tk_char}]}</cell> + <cell align="left" valign="middle">{tk_struct, "IDL:M1\S1:1.0", "S1", [{"a", tk_long}, {"b", tk_char}]}</cell> </row> <row> <cell align="left" valign="middle">{tk_union, IFRId, Name, DiscrTC, DefaultNr, [{Label, ElemName, ElemTC}]} <br></br> diff --git a/lib/orber/doc/src/ch_install.xml b/lib/orber/doc/src/ch_install.xml index eee2b99c92..ab5885954b 100644 --- a/lib/orber/doc/src/ch_install.xml +++ b/lib/orber/doc/src/ch_install.xml @@ -483,7 +483,7 @@ nodeB@hostB> orber:start(). <item>Since Orber domains, they are supposed to communicate via IIOP, <em>MUST</em> have unique names, communication will fail if two domains have the same name. The domain name <em>MAY NOT</em> - contain <c>^G</c> (i.e. <c>\\007</c>).</item> + contain <c>^G</c> (i.e. <c>\007</c>).</item> <tag><em>iiop_port</em></tag> <item>If set to 0 the OS will pick any vacant port. <br></br> @@ -595,7 +595,7 @@ nodeB@hostB> orber:start(). the <c>interceptors</c> parameter.</item> <tag><em>orbInitRef</em></tag> <item>Setting this option, e.g., - <c>erl -orber orbInitRef [\\"NameService=corbaloc::host.com/NameService\\"]</c>, + <c>erl -orber orbInitRef [\"NameService=corbaloc::host.com/NameService\"]</c>, will alter the location from where <c>corba:resolve_initial_references(Key)</c> tries to find an object matching the given Key. The keys will also appear when invoking <c>corba:list_initial_services()</c>. This variable overrides @@ -605,7 +605,7 @@ nodeB@hostB> orber:start(). found, and this variable is set, it determines the location from where <c>orber:resolve_initial_references(Key)</c> tries to find an object matching the given Key. Usage: - <c>erl -orber orbDefaultInitRef \\"corbaloc::host.com\\"</c>.</item> + <c>erl -orber orbDefaultInitRef \"corbaloc::host.com\"</c>.</item> <tag><em>orber_debug_level</em></tag> <item>The range is 0 to 10. Using level 10 is the most verbose configuration. diff --git a/lib/orber/doc/src/ch_interceptors.xml b/lib/orber/doc/src/ch_interceptors.xml index 27b254c4bf..af8c5a45f1 100644 --- a/lib/orber/doc/src/ch_interceptors.xml +++ b/lib/orber/doc/src/ch_interceptors.xml @@ -188,17 +188,17 @@ out_reply_encoded({ObjTable, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) -> %% Interceptor functions. -export([new_out_connection/3, -\011 new_in_connection/3, -\011 closed_in_connection/1, -\011 closed_out_connection/1, -\011 in_request_encoded/6, -\011 in_reply_encoded/6, -\011 out_reply_encoded/6, -\011 out_request_encoded/6, -\011 in_request/6, -\011 in_reply/6, -\011 out_reply/6, -\011 out_request/6]). + new_in_connection/3, + closed_in_connection/1, + closed_out_connection/1, + in_request_encoded/6, + in_reply_encoded/6, + out_reply_encoded/6, + out_request_encoded/6, + in_request/6, + in_reply/6, + out_reply/6, + out_request/6]). new_in_connection(Arg, Host, Port) -> %% Since we only use one interceptor we do not care about the diff --git a/lib/orber/doc/src/ch_naming_service.xml b/lib/orber/doc/src/ch_naming_service.xml index 510ccf2543..5cc50d95ec 100644 --- a/lib/orber/doc/src/ch_naming_service.xml +++ b/lib/orber/doc/src/ch_naming_service.xml @@ -116,7 +116,7 @@ Figure 1: Contextual object relationships using the Naming Service.</icaption> <p>In order to use the naming service you have to fetch an initial reference to it. This is done with:</p> <code type="none"> -\011NS = corba:resolve_initial_references("NameService"). +NS = corba:resolve_initial_references("NameService"). </code> <note> <p>NS in the other use-cases refers to this initial reference.</p> @@ -208,17 +208,17 @@ Sc = corba:string_to_object("corbaname:rir:/NameService#workgroup/services/"). {BList, BIterator} = 'CosNaming_NamingContext':list(Sc, 10). lists:foreach(fun({{Id, Kind},BindingType}) -> case BindingType of -\011nobject -> -\011\011io:format("id: %s, kind: %s, type: object~n", [Id, Kind]); -\011 _ -> -\011\011io:format("id: %s, kind: %s, type: ncontext~n", [Id, Kind]) -\011end end, -\011Blist). + nobject -> + io:format("id: %s, kind: %s, type: object~n", [Id, Kind]); + _ -> + io:format("id: %s, kind: %s, type: ncontext~n", [Id, Kind]) + end end, + Blist). </code> </item> </list> <note> - <p>Normally a <term id="BindingIterator"><termdef>The binding iterator (Like a book mark) indicates which objects have been read from the list.</termdef></term>is helpful in situations where you have a large\011number of objects + <p>Normally a <term id="BindingIterator"><termdef>The binding iterator (Like a book mark) indicates which objects have been read from the list.</termdef></term>is helpful in situations where you have a large number of objects in a list, as the programmer then can traverse it more easily. In Erlang it is not needed, because lists are easily handled in the language itself.</p> @@ -427,7 +427,7 @@ lists:foreach(fun({{Id, Kind},BindingType}) -> case BindingType of <cell align="left" valign="middle">An Id with a trailing '.' is not allowed.</cell> </row> <row> - <cell align="left" valign="middle">"i\\\\/d1/i\\\\.d2"</cell> + <cell align="left" valign="middle">"i\\/d1/i\\.d2"</cell> <cell align="left" valign="middle">[{"i/d1",""},{"i.d2",""}]</cell> <cell align="left" valign="middle">Since '.' and '/' are used to separate the components, these tokens must be escaped to be correctly converted.</cell> </row> diff --git a/lib/orber/doc/src/corba.xml b/lib/orber/doc/src/corba.xml index 6c89279733..cae0e09b0b 100644 --- a/lib/orber/doc/src/corba.xml +++ b/lib/orber/doc/src/corba.xml @@ -99,9 +99,8 @@ <em>MAY ONLY</em> be used during testing and development.</p> <code type="none"> Example: -\011 - corba:create('StackModule_Stack', "IDL:StackModule/Stack:1.0", -\011 {10, test}) + + corba:create('StackModule_Stack', "IDL:StackModule/Stack:1.0", {10, test}) </code> </desc> </func> diff --git a/lib/orber/doc/src/notes.xml b/lib/orber/doc/src/notes.xml index 08bbf4b29c..1185b7658f 100644 --- a/lib/orber/doc/src/notes.xml +++ b/lib/orber/doc/src/notes.xml @@ -33,6 +33,24 @@ </header> <section> + <title>Orber 3.6.15</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Removed superfluous VT in the documentation.</p> + <p>Own id: OTP-8353 Aux Id:</p> + </item> + <item> + <p>Removed superfluous backslash in the documentation.</p> + <p>Own id: OTP-8354 Aux Id:</p> + </item> + </list> + </section> + </section> + + <section> <title>Orber 3.6.14</title> <section> @@ -403,8 +421,6 @@ </item> </list> </section> - <!-- p>For information about older versions see - <url href="part_notes_history_frame.html">release notes history</url>.</p --> </section> </chapter> diff --git a/lib/orber/doc/src/notes_history.xml b/lib/orber/doc/src/notes_history.xml deleted file mode 100644 index b493f0e379..0000000000 --- a/lib/orber/doc/src/notes_history.xml +++ /dev/null @@ -1,1523 +0,0 @@ -<?xml version="1.0" encoding="latin1" ?> -<!DOCTYPE chapter SYSTEM "chapter.dtd"> - -<chapter> - <header> - <copyright> - <year>2004</year><year>2009</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - </legalnotice> - - <title>Orber Release Notes History</title> - <prepared></prepared> - <responsible></responsible> - <docno></docno> - <approved></approved> - <checked></checked> - <date>99-02-12</date> - <rev>A</rev> - </header> - - <section> - <title>Orber 3.5.4</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>In some cases, it was possible for a user to delete the - NameService root context.</p> - <p>Own Id: OTP-5202</p> - </item> - <item> - <p>Invoking two, or more, concurrent oe_register operations - it could corrupt the IFR. If this is the case, the - INTF_REPOS system exception is raised. The risk for this - to occur is rather slim.</p> - <p>Own Id: OTP-5526</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.5.3</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>To avoid malicious attacks, it is now possible to configure - Orber to only accept incoming requests up to a certain size. - To be able to use this option, it must be supported by inet - and SSL.</p> - <p>Own id: OTP-5129</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.5.2</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>If a client tried to connect to Orber and immediately - closed the connection, then the process accepting new - connections could end up with a message in the queue - that would never be removed.</p> - <p>Own id: OTP-5105</p> - </item> - <item> - <p>The INS corbaloc/corbaname URL:s did only accept DNS style host - names. Now it is also possible to use, none compressed, IPv6 - addresses.</p> - <p>Own id: OTP-5108</p> - </item> - <item> - <p>When Orber was configured to use IPv6 for inter-ORB communication, - exported IOR:s did not contain a correct IPv6 address. This did not - cause any problems if Orber was configured to use DNS style hostname - instead.</p> - <p>Own id: OTP-5109</p> - </item> - <item> - <p>Orber used external operations not exported in R9B.</p> - <p>Own id: OTP-5111</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.5.1</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>When using Light IFR it was not possible unregister data - (i.e., invoking 'MyModule':oe_unregister()). - Introduced in Orber-3.5.0.1.</p> - <p>Own id: OTP-5034</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.5.0.1</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>orber_ifr:contents/3 always returned an empty list when using - Light IFR. Little or no effect.</p> - <p>Own id: OTP-5018</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.5</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>It is now possible to configure Orber to use NAT (Network Address - Translation) friendly parameters. A new section in the User's Guide - describes how to handle communication via firewalls.</p> - <p>Own id: OTP-4698</p> - </item> - <item> - <p>A new module called <c>orber_diagnostics</c> have been added, which - is intended to aid a user during the test and development phase. - For more information, see the reference manual.</p> - <p>Own id: OTP-4699</p> - </item> - <item> - <p><c>IPv6</c> supported.</p> - <p>Own id: OTP-4937</p> - </item> - <item> - <p>Possible to configure Orber so that exported IOR:s contain - multiple IIOP components for different interfaces.</p> - <p>Own id: OTP-4938</p> - </item> - <item> - <p>Improved typechecking of typecode supplied to the operations - <c>orber_tc:check_tc/1</c>, <c>any:create/2</c> and - <c>any:set_typecode/2</c>.</p> - <p>Own id: OTP-4939</p> - </item> - <item> - <p>Server objects can now be started as EXIT tolerant.</p> - <p>Own id: OTP-4940</p> - </item> - <item> - <p>Possible to use interceptors for local invocations as well.</p> - <p>Own id: OTP-4941</p> - </item> - <item> - <p>If the IFR is not explicitly used, Orber can be configured - to use a minimal IFR to reduce memory usage and installation - time.</p> - <p>Own id: OTP-5001</p> - </item> - <item> - <p>To avoid malicious attacks it is now possible to configure - Orber to limit the number of concurrent connections and - requests and the amount of IIOP fragments.</p> - <p>Own id: OTP-5002</p> - </item> - <item> - <p>The operation <c>orber:iiop_connections/0</c> now also include - incoming connections.</p> - <p>Own id: OTP-5004</p> - </item> - <item> - <p>The function <c>orber:add_node/2</c> now accepts more options.</p> - <p>Own id: OTP-5006</p> - </item> - <item> - <p>The module <c>orber_diagnostics</c> now exports a function - which list missing modules generated by IC and required by - Orber.</p> - <p>Own id: OTP-5007</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Orber's NameService did not return a NIL object reference if the total - number of existing bindings was less than, or equal to, - the <c>HowMany</c> parameter passed to - <c>'CosNaming_NamingContext':list/2</c> operation. This have now been - changed to be compliant with the OMG standard. Furthermore, the operation - <c>'CosNaming_BindingIterator':next_n/2</c> did not handle the index - correctly in all situations.</p> - <p>Own id: OTP-4700</p> - </item> - <item> - <p>If the Orber internal gen_server orber_iiop_pm was stopped - in such a way that the terminate function was not invoked, - then ghost processes would appear.</p> - <p>Own id: OTP-5003</p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <list type="bulleted"> - <item> - <p>The work-around introduced in version 3.4.1 (OTP-4608) has - now been removed. Make sure you are using IC-4.2 or later.</p> - </item> - <item> - <p>Since the OMG has defined a default port number (2809), - Orber no longer support the bootstrap port.</p> - <p>Own id: OTP-5005</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.4.2.2</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Due to IFR DB lock mechanisms, concurrent creation - of non-anonymous IFR types could still result in duplicated - entries.</p> - <p>Own id: OTP-4781</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.4.2.1</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The operation <c>orber:start()</c> could return before - all Mnesia tables were accessible.</p> - <p>Own id: OTP-4780</p> - </item> - <item> - <p>Concurrent creation of non-anonymous IFR types - could result in duplicates in the DB.</p> - <p>Own id: OTP-4781</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.4.2</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Improved type tests for string, wide string and sequence when - passed via IIOP.</p> - <p>Own id: OTP-4759</p> - </item> - <item> - <p>Less (internal) processes are needed when Orber act as client-side ORB - and communicate with another ORB. Due to this change, closed connections - and socket errors are dealt with in a more gentle way. If the latter - occurs, the error_logger application is used to generate an error - report containing a description of what went wrong.</p> - <p>Own id: OTP-4655</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>When communicating with another ORB, via SSL, and a socket error occurred, - Orber did not recognize the error message. This occurred when Orber - acted as client-side ORB.</p> - <p>Own id: OTP-4656</p> - </item> - <item> - <p>If an out-going connection was closed and the receiving process had not - been scheduled yet, the close connection message was delivered before - the correct message.</p> - <p>Own id: OTP-4657</p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <list type="bulleted"> - <item> - <p>Since strstream is deprecated and not accepted by gcc-3.3, - Orber no longer includes the InitalReference lib. The source - code is still included.</p> - <p>Own id: OTP-4767</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.4.1</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>It is now possible to use IC-versions older than 4.2. But, this is - only temporary so it is still necessary upgrade to a correct - version.</p> - <p>Own id: OTP-4608</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.4</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>If a call-back module illegally caused an EXIT, clients - residing on another ORB was not notified (hanged).</p> - <p>Own id: OTP-4577</p> - </item> - <item> - <p>The stub/skeleton-files generated by IC have been improved, - i.e., depending on the IDL-files, reduced the size of the - erl- and beam-files and decreased dependencies off Orber's - Interface Repository. It is necessary to re-compile all IDL-files - and use COS-applications, including Orber, compiled with - IC-4.2.</p> - <p>Own id: OTP-4576</p> - </item> - <item> - <p>It is now possible to configure Orber to use the host name - in exported IOR:s instead of the IP-number.</p> - <p>Own id: OTP-4541</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>When Orber acted as server-side ORB and one tried to setup a - SSL-connection and using native Interceptors at the same time - it failed.</p> - <p>Own Id: OTP-4542</p> - </item> - <item> - <p>Oneway operations, using a multi-node Orber, failed for inter-node - communication.</p> - <p>Own Id: OTP-4543</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.3</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Orber now supports fragmented IIOP messages for 1.2.</p> - <p>Own Id: OTP-4462</p> - </item> - <item> - <p>Orber now has its own set of unique VMCID:s which - is used for minor codes in system exceptions. All system exceptions raised - by Orber now uses this VMCID base or OMG:s VMCID base. See also the function - <c>orber:exception_info/1</c>.</p> - <p>Own Id: OTP-4463</p> - </item> - <item> - <p>Since some ORB:s, non-compliant with the OMG specification, - have problems using IOR:s which embeds a CodeSet component, it is now - possible to configure Orber to exclude it from exported IOR:s.</p> - <p>Own Id: OTP-4469</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>When combining interceptors and oneway operations, Orber - incorrectly sent a MessageError over the connection to the - client ORB.</p> - <p>Own Id: OTP-4460</p> - </item> - <item> - <p>After (2^32)-1 requests, Orber used the request number 0 twice - in a row.</p> - <p>Own Id: OTP-4461</p> - </item> - <item> - <p>The COMM_FAILURE exception should only be raised when connection - problems occur. Now Orber raises the correct exceptions. Note, when - Orber act as client side ORB you must be able to handle any of the system - exceptions defined by the OMG. Some of the COMM_FAILURE exceptions - have been replaced with the correct TRANSIENT and TIMEOUT exceptions.</p> - <p>Own Id: OTP-4465</p> - </item> - <item> - <p>The default port used for corbaloc and corbaname was - incorrect. Now changed to follow the OMG standard (2809).</p> - <p>Own Id: OTP-4466</p> - </item> - <item> - <p>When Orber acted as a client-side ORB, it failed to encode - unions with a default case (i.e. defined in the IDL-code and a - default label used).</p> - <p>Own Id: OTP-4472</p> - </item> - <item> - <p>The operation corba:print_object/1/2 did not include host/port - data for IIOP-1.0 IOR:s.</p> - <p>Own Id: OTP-4483</p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <list type="bulleted"> - <item> - <p>Some of the COMM_FAILURE exceptions have been replaced with the correct - TRANSIENT and TIMEOUT exceptions. All minor codes used by Orber - is now based on the OMG assigned VMCIDs.</p> - <p>Own Id: OTP-4465, OTP-4463</p> - </item> - <item> - <p>The default port used for corbaloc and corbaname have been changed - to 2809.</p> - <p>Own Id: OTP-4466</p> - </item> - <item> - <p>To reduce extra overhead Orber now uses a flag parameter, - which makes it possible to configure Orber's behavior in different ways. - Hence, the global activation of Local Typechecking, introduced in the previous - version, have now been changed.</p> - <p>Own Id: OTP-4467</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.2.13</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>It is now possible to activate automatic typechecking when - invoking operations on CORBA Objects locally. For more - information, see the configuration and debugging chapters - in the User's Guide regarding the <c>local_typecheck</c> - option.</p> - <p>Own Id: OTP-4410</p> - </item> - <item> - <p>Due to the success of the pre-compiled IIOP-trace interceptor, a less - verbose trace interceptor, called <c>orber_iiop_tracer_silent</c>, - have been added as well.</p> - <p>Own Id: OTP-4257</p> - </item> - <item> - <p>Orber now support the Fixed datatype defined by the OMG. To be able - to define Fixed types in an IDL-specification, check that your current - IC version supports this type as well. If not, the only option is - to encapsulate it in an <c>any</c> type.</p> - <p>Own id: OTP-4375</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>It was not possible to use the function <c>corba:print_object/2</c>, - which was introduced in the previous release, only - <c>corba:print_object/1</c>. Now it is also possible to use - the <c>error_logger</c> or receive the data in string form.</p> - <p>Own Id: OTP-4376</p> - </item> - <item> - <p>The functions <c>orber_tc:principal</c> and <c>orber_tc:exception</c> - returned incorrect.</p> - <p>Own Id: -</p> - </item> - <item> - <p>The function <c>orber_ifr:get_primitive</c> tried to access a - non-existing (primitivdefs) table.</p> - <p>Own Id: -</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.2.12</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Orber now check if an external IOR contains any - TAG_ALTERNATE_IIOP_ADDRESS components when trying to setup - a connection to another ORB.</p> - <p>Own id: OTP-4294</p> - </item> - <item> - <p>It is now possible to add TAG_ALTERNATE_IIOP_ADDRESS components - to a local object reference. See corba:add_alternate_iiop_address/3.</p> - <p>Own id: OTP-4294</p> - </item> - <item> - <p>Orber now allows unions with no default value defined and a - discriminator out of range to be sent via IIOP. The value-field - is set to the atom undefined.</p> - <p>Own id: OTP-4295</p> - </item> - <item> - <p>The corba module now exports a function, print_object/1/2, which - prints IOR's in a more readable form.</p> - <p>Own id: OTP-4296</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Since "all" ORB's accept ISO-8859-1 encoding of chars and strings, - Orber assumed that it could be used at all time to reduce the overhead. - The JDK-1.3 only accepts ISO 646:1991 IRV (US-ASCII), even though - ISO-8859-1 is default, which is why Orber now checks which codeset - is accepted.</p> - <p>Own Id: OTP-4298</p> - </item> - <item> - <p>When invoking a Locate Request, Orber in some cases did not reply - with a Locate Reply header (used a Reply header).</p> - <p>Own Id: OTP-4293</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.2.11</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>If the underlying OS was not configured to allow Erlang to use the - fully qualified host name the result could an incorrect IP-address. - Hence, if you want to upgrade to Orber-3.2.11 and the fully - qualified name must be used you must upgrade your kernel version. - Most likely, this change will NOT cause any problems, but if in doubt - please contact support or use the mailing-list. - See also the release notes for Orber-3.2.6.</p> - <p>Own id: OTP-3966</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>When looking up Initial Service (e.g. using <c>corbaloc</c>, - <c>corbaname</c> or <c>corba:resolve_initial_references_remote/2</c>) - and communicating via SSL, Orber used the wrong port number.</p> - <p>Own Id: OTP-4264</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.2.10</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>It is now possible to add new initial references, which can, - for example, be accessed via <c>corba:resolve_initial_references/1</c> - or the <c>corbaloc</c> schema.</p> - <p>Own Id: OTP-4258</p> - </item> - <item> - <p>The orber module now exports functions, <c>iiop_connections</c> - and <c>iiop_connections_pending</c>, which, respectively, list - all currently open connections to other ORB's and connections - which are in process of being set up to another ORB.</p> - <p>Own Id: OTP-4262</p> - </item> - <item> - <p>Orber now allows the user to define an interval of ports - which Orber is may use (i.e. ports on the local machine) - when trying to connect to another ORB. This behavior is useful - if Orber resides behind a firewall which only allow applications - to use certain ports when communicating with the outside world. - If this option is set, it is absolutely necessary to - set <c>iiop_connection_timeout</c>. If not, there is risk that - Orber run out of ports, which will result in communication failure. - This option cannot be used when using SSL since it does not support - this feature. The default behavior is that any available port - will be used (as before).</p> - <p>Own Id: OTP-4260</p> - </item> - <item> - <p>One can now install Orber's NameService as disc_copies, but - the default behavior is that Orber uses ram_copies.</p> - <p>Own Id: OTP-4259</p> - </item> - <item> - <p>A pre-compiled IIOP-trace interceptor is now - included in the Orber release. For more information, - see the <c>Debugging</c> chapter in the User's Guide.</p> - <p>Own Id: OTP-4257</p> - </item> - <item> - <p>It is now possible to set Orber's configuration parameters - in, for example, an Erlang shell. Consult <c>corba:orb_init/1</c> and - <c>orber:configure/2</c>.</p> - <p>Own Id: OTP-4261</p> - </item> - <item> - <p>The Orber release now include <c>OrberWeb</c>, which is an extension of - the <c>WebTool</c> application (first released in R8B). Hence, - <c>WebTool</c> must be installed to enable this feature. For more - information, see the chapter <c>OrberWeb</c> in the User's Guide. - <c>OrberWeb</c> is intended to be used during test and development.</p> - <p>Own Id: OTP-4257</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>When setting up two Orber ORB's, where one of the ORB's domain - name was a prefix of the other ORB's, communication via IIOP would fail. - To eliminate any further configuration problems, one may not - use <c>^G</c> (i.e. <c>"\\007"</c>) in the domain name. Due to this - change it is not possible to upgrade during run-time.</p> - <p>Own Id: OTP-4229</p> - </item> - <item> - <p>When using a mix of IIOP-versions (1.0 vs 1.1/1.2) and - sending/receiving IOR's to/from Orber could result in a - MARSHAL exception.</p> - <p>Own Id: OTP-4230</p> - </item> - <item> - <p>Encoding/decoding of wchar/wstring when using IIOP-1.2 do now - follow the OMG standard. If your ORB do not follow the - standard, contact support for information how to make a work-around - to solve this problem. In most cases it is sufficient to - configure the ORB's to communicate via IIOP-1.1.</p> - <p>Own Id: OTP-4263</p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <list type="bulleted"> - <item> - <p>The encoding/decoding of wchar/wstring when using IIOP-1.2 - have been updated. See above.</p> - <p>Own Id: OTP-4263</p> - </item> - <item> - <p>Orber no longer returns a 'EXIT' message when trying - to install Orber, i.e., invoking orber:install/1/2, - on a disc-less node. But if if the installation fails due - to any other reason, Orber still return a 'EXIT' message.</p> - <p>Own Id: OTP-4256</p> - </item> - </list> - </section> - - <section> - <title>Known bugs and problems</title> - <list type="bulleted"> - <item> - <p><c>OrberWeb</c> only tested with <c>Netscape-4.75</c>. Furthermore, - until <c>WebTool</c> reaches version 1.0 OrberWeb should also - be considered to be a beta version.</p> - <p>Own Id: OTP-4257</p> - </item> - <item> - <p><c>OrberWeb</c> do not escape arguments passed when, for example, - creating a new context. Hence, for now you are recommended to - only use letters.</p> - <p>Own Id: OTP-4257</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.2.9</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>External IOR:s containing unsupported or incorrectly placed - TaggedComponents was corrupted when Orber forwarded the - IOR via IIOP. This bug was introduced in 3.2.6.</p> - <p>Own Id: OTP-4170</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.2.8</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Orber now support interceptors.</p> - <p>Own Id: -</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.2.7</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>When Orber acted as server-side and communicating via IIOP the overhead - was unreasonably large and memory consuming (depended on the - IDL-specification). This have now been fixed and will, especially, - improve the performance when invoking operations with no, or simple, - arguments on a complex interface. This change will have little effect - on objects started as pseudo since this problem did not affect them.</p> - <p>Own Id: OTP-4063</p> - </item> - <item> - <p>When Orber tried to set up a connection to another ORB which did not - respond all IIOP access where blocked until the TCP protocol - generated a timeout. Now only requests to that particular ORB are - queued.</p> - <p>Own Id: OTP-4060</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>It was not possible to invoke the operation - CosNaming_BindingIterator:next_one via IIOP if no more bindings - existed.</p> - <p>Own id: OTP-4004</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.2.6</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Registering data in the IFR overhead reduced.</p> - <p>Own id: OTP-3904</p> - </item> - <item> - <p>The overhead for the function <c>is_a/1</c> have been reduced, which also - affects remote <c>narrow</c> operations for inherited interfaces - (e.g. using Java or C++ ORBs).</p> - <p>Own id: OTP-3904</p> - </item> - <item> - <p>If the underlying OS was not configured to allow Erlang to - lookup the host-name by using the short-name the result was - always the IP-address 127.0.0.1 (loop-back). Now Orber uses - the full name. Hence, make sure the <c>net_adm:localhost/0</c> and - <c>inet:getaddr/2</c> return proper values.</p> - <p>Own id: OTP-3966</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The CONV_FRAME_CodeSetComponentInfo struct was not placed - correctly in IOR:s. Each profile must be self-sustained - which is why this information must be duplicated in each - profile. Currently this only applies for the IIOP-profile - but will also concern future protocols.</p> - <p>Own id: OTP-3992</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.2.5</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Orber now defines the configuration variable, - <c>iiop_setup_connection_timeout</c>, which makes it possible to - timeout connection attempts to another ORB before the OS TCP timeout - is activated.</p> - <p>Own id: OTP-3961</p> - </item> - <item> - <p>It is now possible to configure Orber to generate reports when abnormal - situations occurs. For more information consult the User's Guide - regarding the configuration parameter <c>orber_debug_level</c>. - Note, it is not recommended to use this option for delivered systems - since some of the reports is not to be considered as errors.</p> - <p>Own id: OTP-3962</p> - </item> - <item> - <p>Orber now accepts a list of addresses as value for the configuration - parameter <c>orbInitRef</c>.</p> - <p>Own id: OTP-3945</p> - </item> - <item> - <p>Orber now includes services defined by the configuration parameter - <c>orbInitRef</c> when invoking <c>corba:list_initial_services/0</c>.</p> - <p>Own id: OTP-3946</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>When using the configuration variable 'orbDefaultInitRef' with - a value pointing to another Orber-ORB it was not possible to - install Orber since Orber used to create default <c>NamingContexts</c>. - Orber no longer add these contexts.</p> - <p>Own id: OTP-3943</p> - </item> - <item> - <p>Orber accessed <c>corbaloc</c> addresses in reverse order. Now fixed.</p> - <p>Own id: OTP-3944</p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <list type="bulleted"> - <item> - <p>When installing Orber no default <c>NamingContext's</c>, i.e., - <c>host</c>, <c>hosts</c>, <c>resources</c>, <c>development</c>, - <c>factories</c> and <c>workgroup</c>, will be added. These contexts - was defined in a cancelled specification.</p> - <p>Own id: OTP-3942</p> - </item> - <item> - <p><c>corbaloc</c> addresses are now accessed in FIFO order (instead of - LIFO).</p> - <p>Own id: OTP-3944</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.2.4</title> - - <section> - <title>Improvements and New Features</title> - <p>-</p> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>When communicating via IIOP using version 1.2 Orber used incorrect - offset for reply bodies containing system exceptions, exceptions and - location forward.</p> - <p>Own id: OTP-3912</p> - </item> - <item> - <p>Orber did not return correct IFR Id:s when raising system exceptions - via IIOP.</p> - <p>Own id: OTP-3911</p> - </item> - <item> - <p>If two different processes concurrently manipulated a - <c>CosNaming::NamingContext</c> the data could become corrupted. - For single-node Orber this error occurred in version 3.2.1, 3.2.2 and - 3.2.3. For multi-node Orber this behavior have been present at all time.</p> - <p>Own id: OTP-3910</p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <list type="bulleted"> - <item> - <p>Since Orber now returns a different, and correct, IFR-id for - systems exceptions other ORB:s and older versions of Orber - might raise a different exception, probably MARSHAL or UNKNOWN. - This only occurs when communicating via IIOP. It is not possible to - upgrade during runtime. Use <c>orber:stop()</c>, load new version and - restart Orber by invoking <c>orber:start()</c>.</p> - <p>Own id: OTP-3911</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.2.3</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Improved performance for all types, simple and complex, when - communicating via IIOP. It is not possible to upgrade during - runtime. Use <c>orber:stop()</c>, load new version and restart - Orber by invoking <c>orber:start()</c>.</p> - <p>Own id: OTP-3905</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>If a pseudo object raises an exception or exits the exception - was only returned, not thrown.</p> - <p>Own id: OTP-3907</p> - </item> - <item> - <p>Orber defined an incorrect ID for CodeSets. This may cause - INV_OBJREF or DATA_CONVERSION exceptions to be thrown, it - depends on the other ORB.</p> - <p>Own id: OTP-3899</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.2.2</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>The behavior of Orber when receiving unsupported or incorrect - messages have now been improved.</p> - <p>Own id: OTP-3903</p> - </item> - <item> - <p>Time consumed by <c>oe_MyModule:oe_register()</c> decreased.</p> - <p>Own id: OTP-3904</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>When Orber received a 'location_forward' reply, the result - from the second invocation was never delivered to the - client. Now fixed.</p> - <p>Own id: OTP-3814</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.2.1</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>It is now possible to use external <c>NamingContexts</c> - when, for example, using - <c>'CosNaming_NamingContextExt':bind_context/3</c>.</p> - <p>Own id: OTP-3902</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.2</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Orber now supports IIOP-version 1.2.</p> - <p>Own id: OTP-3901</p> - </item> - <item> - <p>Improved encoding and decoding performance for IIOP requests containing - <c>struct</c>, <c>union</c> or user defined <c>exceptions</c>.</p> - <p>Own id: OTP-3900</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Setting the <c>bootstrap_port</c> configuration parameter to a value - less than 1024 made it impossible to start Orber properly. - Now fixed.</p> - <p>Own id: OTP-3898</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.1.8</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Orber now accepts <c>Indirection/Repeated</c><c>CORBA::TypeCode</c> as input and/or - return value when communicating via IIOP.</p> - <p>Own id: -</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>When another ORB replied with <c>location forward</c> Orber - failed to decode this. Now fixed.</p> - <p>Own id: OTP-3709</p> - </item> - <item> - <p>Orber failed to encode <c>CORBA::TypeCode</c> containing <c>tk_alias</c>, e.g., - sending an <c>#any{}</c> which encapsulates data defined by <c>typedef</c>.</p> - <p>Own id: OTP-3689</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.1.7</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Earlier, Orber did not use the IIOP/GIOP version specified - in an external object key when invoking an intra-ORB request.</p> - <p>Own id: OTP-3663</p> - </item> - <item> - <p>The OMG standard now support an Interoperable Naming Service. - Initially there where two proposals of which Orber earlier - supported one of them. Now both standards are supported.</p> - <p>Own id: OTP-3664</p> - </item> - <item> - <p>The OMG have redefined the operator, used when encoding requests via IIOP, - for the function <c>corba_object:non_existent/1</c>. CORBA version 2.0 and - 2.2 compliant ORB:s is supposed to support the old definition, while - later versions, i.e., 2.3, is supposed to use the new operator - (<c>_non_existent</c> instead of <c>_not_existent</c>). Orber accepts - both versions.</p> - <p>Own id: OTP-3679</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>If an Orber node crashed and was restarted the object keys could - point to other processes than it should, which may cause problems if, - for example, the other process terminates due to it does not handle - unknown messages. Now Orber GC object keys for objects residing on the - crashed node. If Orber is started as a multi-node ORB of which one or - more nodes runs an older Orber version they can still communicate but - with an increased overhead. Hence, all nodes should be upgraded during - a relatively short time. If Orber is stopped, i.e., orber:stop() or - a shutdown is generated, objects residing on that node will be terminated.</p> - <p>Own id: OTP-3678</p> - </item> - <item> - <p>If an IDL-file contains two interfaces of which the first one - contains an exception and the second interface, which inherits the first - one, contain an operation which raises this exception the IFR - failed since multiple references where found when invoking - orber_ifr:lookup_id/2. Now fixed.</p> - <p>Own id: OTP-3665</p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <list type="bulleted"> - <item> - <p>To be able to start Orber as lightweight the mnesia application - cannot be listed in the "orber.app" file. You might find it - necessary to add 'mnesia' to the applications-list. - For example, you cannot upgrade an older version - of Orber (not started as lightweight) to this version without - adding mnesia to the application dependencies list.</p> - <p>Own id: OTP-3666</p> - </item> - <item> - <p>The function <c>corba_object:non_existent/1</c> have been updated - to follow the CORBA 2.3 standard. Hence, Intra-ORB communication - with ORB:s not supporting this standard will fail. The operation - <c>corba_object:not_existent/1</c> allow users to use the old standard. - Consult the ORB vendor's documentation to decide which function to use.</p> - <p>Own id: OTP-3679</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.1.6</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Cosmetic update of internal functions.</p> - <p>Own id: -</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.1.5</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>When decoding TypeCode for an object reference, e.g., as a part of - an #any{}, Orber failed. This is no longer the case. </p> - <p>Own id: OTP-3631</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.1.4</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>The function <c>start_lightweight/1</c> have been added to the - <c>orber</c> module. This function allow us to start orber as - lightweight without, or override, the configuration parameter - <c>-orber lightweight</c>.</p> - <p>Own id: -</p> - </item> - <item> - <p>A new configuration parameter, 'iiop_connection_timeout Secs', is now - available. This parameter's purpose, is to terminate the socket - connection on the client side if a time span of Secs seconds have passed. - The connection will, however, NOT be terminated if a client still waits - for a reply. For the last scenario to happen, the client have been - configured to use a larger timeout value than the configuration - parameter 'iiop_connection_timeout' have been set to.</p> - <p>Own id: -</p> - </item> - <item> - <p>Up until now, invoking an an operation with an extra Timeout parameter - (using the IC option: ic:gen(IdlFile, [{timeout,"module::interface"}])), - only applied to local Objects. Now, using the IC option above, when - compiling the stubs, and adding the extra Timeout parameter, a timeout - will also be triggered when calling Objects residing on other ORB:s. - The return value, after a timeout has been triggered, have changed from - an EXIT message to raising the system exception COMM_FAILURE. For more - information, about how this feature interacts with the configuration - parameter 'iiop_timeout', consult the documentation.</p> - <p>Own id: -</p> - </item> - <item> - <p>When using invalid intra-ORB configuration, i.e., incorrect - Port/IP-address, when trying to connect to another ORB, - a CRASH REPORT was generated if the configuration - parameter '-boot start_sasl' was used. This behavior has now changed.</p> - <p>Own id: -</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>If a client-side ORB terminated the IIOP connection immediately there - was a possibility that the server responsible detecting this did not.</p> - <p>Own id: OTP-3593</p> - </item> - <item> - <p>Setting the configuration parameter 'iiop_timeout' did not result in a - correct behavior, i.e., no timeout triggered.</p> - <p>Own id: OTP-3555</p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <list type="bulleted"> - <item> - <p>When using the IC option, ic:gen(IdlFile, [{timeout,"module::interface"}]), - an EXIT was the timeout result. Now, the system exception COMM_FAILURE is - raised.</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.1.3</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Orber did not ignore unrecognized TaggedProfiles. Other vendors may have - registered own TAG's with the OMG. These TAG's are valid but not - necessarily handled by other vendors.</p> - <p>Own id: OTP-3514</p> - </item> - <item> - <p>When passing Object references over IIOP, decoding local references could - fail. Now fixed.</p> - <p>Own id: OTP-3515</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.1.2</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Previously the OMG have published two suggestions for <c>Interoperable Name Service</c>, - of which, the <c>CORBA 3</c> specify <c>orbos/98-10-11</c> to be implemented. - Unfortunately, the Interoperable Name Service Orber supports, is the one not chosen. - Hence, the <c>InitialReferences.idl</c> will not be according to the future standard. - The modules name is now changed from <c>CORBA</c> to <c>Orber</c>. This will affect - code which are using this interface. The idl specification must be recompiled and - then <c>CORBA</c> must be changed to <c>Orber</c> in the client.</p> - <p>Own id: OTP-3468, OTP-3155</p> - </item> - <item> - <p>Now possible to run oe_unregister when the IDL-specification contains - exceptions correctly.</p> - <p>Own Id: OTP-3447</p> - </item> - <item> - <p>Now possible to run oe_unregister when the IDL-specification contains - attributes.</p> - <p>Own Id: OTP-3439</p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <p>The change in <c>InitialReferences.idl</c> to clash with the Corba standard implies changes - in code that use this interface. See the OTP-3468 and OTP-3155 in the <c>Fixed Bugs and Malfunctions</c> - chapter above.</p> - </section> - </section> - - <section> - <title>Orber 3.1.1</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>When introducing the configuration parameter <c>ip_address</c> - it was no longer possible to have the same default behavior - as before. Now fixed.</p> - <p>Own Id: OTP-3431</p> - </item> - <item> - <p>The internal request number handling never checked if maximum reached. - Now the counter restart at 0 after reaching max.</p> - <p>Own Id: OTP-3415</p> - </item> - <item> - <p>Orber did not handle locate-requests correctly, i.e., not able to - recognize the new internal representation of object references.</p> - <p>Own Id: OTP-3414</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.1</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>It is now possible to start Orber as lightweight.</p> - <p>Own Id: -</p> - </item> - <item> - <p>It is now possible to create pseudo objects, i.e., not server objects.</p> - <p>Own Id: -</p> - </item> - <item> - <p>One new system exception introduced; 'BAD_QOS'.</p> - <p>Own Id: -</p> - </item> - <item> - <p>Orber now supports the types 'long long' and 'unsigned long long'</p> - <p>Own Id: -</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Encoding typecode for complex exceptions (non-empty body) was not done - correctly.</p> - <p>Own Id: OTP-3390</p> - </item> - <item> - <p>orber_iiop_pm crashed when it received an 'EXIT'. Now fixed.</p> - <p>Own Id: OTP-3391</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.0.1</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Orber is now able to handle upgrade properly.</p> - <p>Own Id: -</p> - </item> - </list> - </section> - </section> - - <section> - <title>Orber 3.0</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>It is now possible to use secure IIOP connections to and from Orber. - Orber currently only supports security with the help of SSL and not SECIOP.</p> - <p>Own Id: OTP-1510</p> - </item> - <item> - <p>It is now possible to start Orber objects as supervisor children using - Module_Interface:oe_create_link/2 or corba:create_link/4 as the start function.</p> - <p>Own Id: -</p> - </item> - <item> - <p>It is now possible to start a Orber object and be able to tell apart if it is in - the process of being restarted or has permanently terminated. This is also the reason - for introducing <c>objectkeys_gc_time</c> configuration parameter.</p> - <p>Own Id: -</p> - </item> - <item> - <p>The service CosEvent has been removed from orber and become its own application, called cosEvent.</p> - <p>Own Id: -</p> - </item> - <item> - <p>The service CosTransactions is now available as a separate application, called cosTransactions.</p> - <p>Own Id: OTP-1741</p> - </item> - <item> - <p>Three new system exceptions, 'TRANSACTION_REQUIRED', 'TRANSACTION_ROLLEDBACK' - and 'INVALID_TRANSACTION', introduced. Required by the cosTransactions application.</p> - <p>Own Id: -</p> - </item> - <item> - <p>An configuration variable ip_address has been added, so it's possible - to listen on a specific ip interface on a multi interface host. - The value is the ip address as a string or a tuple of four integers, - default value is all interfaces.</p> - <p>Own Id: OTP-3294</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>set- and get-operations for the 'any'-module now behaves properly.</p> - <p>Own Id: OTP-3355</p> - </item> - <item> - <p>Orber can now handle IORs which contain more than one "Tagged Profile".</p> - <p>Own Id: OTP-3266</p> - </item> - </list> - </section> - - <section> - <title>Incompatibilities</title> - <list type="bulleted"> - <item> - <p>CosEvent include paths have changed since it is now a separate application, called cosEvent.</p> - </item> - <item> - <p>The internal representation of object references have changed. Orber do, however, - recognize the old representation. But object references (created by Orber 2.2.2 or older) - stored and used through several Orber upgrades may not be supported.</p> - </item> - <item> - <p>The functions oe_create/2 and oe_create_link/2 now take an - options list as its second argument. Orber still allow - oe_create*(Env, {Type,RegName}) to be used, but may not in future releases.</p> - </item> - </list> - </section> - </section> -</chapter> - diff --git a/lib/orber/doc/src/orber.xml b/lib/orber/doc/src/orber.xml index da5fd05f98..05036667cc 100644 --- a/lib/orber/doc/src/orber.xml +++ b/lib/orber/doc/src/orber.xml @@ -558,7 +558,7 @@ <desc> <p>This function installs all the necessary mnesia tables and load default data in some of them. If one or more Orber tables - already exists the installation fails. The function\011 + already exists the installation fails. The function <em>uninstall</em> may be used, if it is safe, i.e., no other application is running Orber.</p> <p>Preconditions:</p> diff --git a/lib/orber/doc/src/part_notes.xml b/lib/orber/doc/src/part_notes.xml index 0ff4453d8c..10b3a64373 100644 --- a/lib/orber/doc/src/part_notes.xml +++ b/lib/orber/doc/src/part_notes.xml @@ -30,8 +30,6 @@ <description> <p>The Orber Application is an Erlang implementation of a CORBA Object Request Broker.</p> - <p>For information about older versions see - <url href="part_notes_history_frame.html">release notes history</url>.</p> </description> <xi:include href="notes.xml"/> </part> diff --git a/lib/orber/doc/src/part_notes_history.xml b/lib/orber/doc/src/part_notes_history.xml deleted file mode 100644 index 624865014e..0000000000 --- a/lib/orber/doc/src/part_notes_history.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="latin1" ?> -<!DOCTYPE part SYSTEM "part.dtd"> - -<part> - <header> - <copyright> - <year>2004</year> - <year>2007</year> - <holder>Ericsson AB, All Rights Reserved</holder> - </copyright> - <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - The Initial Developer of the Original Code is Ericsson AB. - </legalnotice> - - <title>Orber Release Notes History</title> - <prepared>Niclas Eklund</prepared> - <docno></docno> - <date>2004-09-15</date> - <rev>1.0</rev> - </header> - <description> - <p>The Orber Application is an Erlang implementation of a CORBA Object - Request Broker.</p> - </description> - <include file="notes_history"></include> -</part> - diff --git a/lib/orber/vsn.mk b/lib/orber/vsn.mk index 8ccdc9792c..ccba631fb5 100644 --- a/lib/orber/vsn.mk +++ b/lib/orber/vsn.mk @@ -1,7 +1,10 @@ -ORBER_VSN = 3.6.14 +ORBER_VSN = 3.6.15 -TICKETS = OTP-8201 +TICKETS = OTP-8353 \ + OTP-8354 + +TICKETS_3.6.14 = OTP-8201 TICKETS_3.6.13 = OTP-7987 diff --git a/lib/percept/src/egd.erl b/lib/percept/src/egd.erl index 4becfef19b..7972fde597 100644 --- a/lib/percept/src/egd.erl +++ b/lib/percept/src/egd.erl @@ -128,13 +128,13 @@ line(Image, P1, P2, Color) -> %% @spec color( Value | Name ) -> color() %% where -%% Value = {byte(), byte(), byte()} | {byte(), byte(), byte(), byte()} -%% Name = black | silver | gray | white | maroon | red | purple | fuchia | green | lime | olive | yellow | navy | blue | teal | aqua +%% Value = {byte(), byte(), byte()} | {byte(), byte(), byte(), byte()} +%% Name = black | silver | gray | white | maroon | red | purple | fuchia | green | lime | olive | yellow | navy | blue | teal | aqua %% @doc Creates a color reference. -spec(color/1 :: ( - Value :: {byte(), byte(), byte()} | {byte(), byte(), byte(), byte()} | atom()) -> - color()). + Value :: {byte(), byte(), byte()} | {byte(), byte(), byte(), byte()} | atom()) -> + color()). color(Color) -> egd_primitives:color(Color). diff --git a/lib/percept/src/egd_font.erl b/lib/percept/src/egd_font.erl index 2b2a89a0a9..5f0d56dd90 100644 --- a/lib/percept/src/egd_font.erl +++ b/lib/percept/src/egd_font.erl @@ -131,18 +131,18 @@ parse_glyph({Code,W,H,X0,Y0,Xm,Offset}, Bitmasks) -> render_glyph(W, H, X0, Y0, Xm, Bitmask) -> render_glyph(W,{0,H},X0,Y0,Xm,Bitmask, []). render_glyph(_W, {H,H}, _X0, _Y0, _Xm, _Bitmask, Out) -> Out; -render_glyph(W, {Hi,H}, X0, Y0,Xm, Bitmask, LSs) -> +render_glyph(W, {Hi,H}, X0, Y0,Xm, Bitmask , LSs) -> N = ((W+7) div 8), O = N*Hi, <<_:O/binary, Submask/binary>> = Bitmask, - LS = render_glyph_horizontal( + LS = render_glyph_horizontal( Submask, % line glyph bitmask {down, W - 1}, % loop state W - 1, % Width []), % Linespans render_glyph(W,{Hi+1,H},X0,Y0,Xm, Bitmask, [LS|LSs]). -render_glyph_horizontal(Value, {Pr, Px}, 0, Spans) -> +render_glyph_horizontal(Value, {Pr, Px}, 0, Spans) -> Cr = bit_spin(Value, 0), case {Pr,Cr} of {up , up } -> % closure of interval since its last @@ -173,4 +173,3 @@ bit_spin(Value, Cx) -> 1 -> up; 0 -> down end. - diff --git a/lib/percept/src/egd_png.erl b/lib/percept/src/egd_png.erl index 3a0aaeef31..3a0aaeef31 100755..100644 --- a/lib/percept/src/egd_png.erl +++ b/lib/percept/src/egd_png.erl diff --git a/lib/percept/src/egd_primitives.erl b/lib/percept/src/egd_primitives.erl index 245e0d48e2..77c600279f 100644 --- a/lib/percept/src/egd_primitives.erl +++ b/lib/percept/src/egd_primitives.erl @@ -28,6 +28,7 @@ pixel/3, polygon/3, line/4, + line/5, arc/4, arc/5, rectangle/4, @@ -50,7 +51,6 @@ -include("egd.hrl"). - %% API info info(I) -> W = I#image.width, H = I#image.height, @@ -75,13 +75,22 @@ object_info(O) -> %% interface functions line(I, Sp, Ep, Color) -> - I#image{objects = [ + I#image{ objects = [ #image_object{ type = line, points = [Sp, Ep], span = span([Sp, Ep]), color = Color} | I#image.objects]}. +line(I, Sp, Ep, Stroke, Color) -> + I#image{ objects = [ + #image_object{ + type = line, + points = [Sp, Ep], + span = span([Sp, Ep]), + internals = Stroke, + color = Color } | I#image.objects]}. + arc(I, {Sx,Sy} = Sp, {Ex,Ey} = Ep, Color) -> X = Ex - Sx, Y = Ey - Sy, @@ -162,8 +171,6 @@ create(W, H) -> #image{ width = W, height = H}. -%color({crayon, Color}) -> rgba_byte2float(name_to_color({crayon, Color, 255})); -%color({crayon, Color, A}) -> rgba_byte2float(name_to_color({crayon, Color, A})); color(Color) when is_atom(Color) -> rgba_byte2float(name_to_color({Color, 255})); color({Color, A}) when is_atom(Color) -> rgba_byte2float(name_to_color({Color, A})); color({R,G,B}) -> rgba_byte2float({R,G,B, 255}); @@ -314,129 +321,6 @@ name_to_color({ slategray, A}) -> { 112, 128, 144, A}; name_to_color({ dimgray, A}) -> { 105, 105, 105, A}; name_to_color({ darkslategray, A}) -> { 47, 79, 79, A}. -%% Crayons -%name_to_color({crayon, mahogany, A}) -> { 205, 74, 74, A}; -%name_to_color({crayon, 'fuzzy wuzzy brown', A}) -> { 204, 102, 102, A}; -%name_to_color({crayon, chestnut, A}) -> { 188, 93, 88, A}; -%name_to_color({crayon, 'red orange', A}) -> { 255, 83, 73, A}; -%name_to_color({crayon, 'sunset orange', A}) -> { 253, 94, 83, A}; -%name_to_color({crayon, bittersweet, A}) -> { 253, 124, 110, A}; -%name_to_color({crayon, melon, A}) -> { 253, 188, 180, A}; -%name_to_color({crayon, 'outrageous orange', A}) -> { 255, 110, 74, A}; -%name_to_color({crayon, 'vivid tangerine', A}) -> { 255, 160, 137, A}; -%name_to_color({crayon, 'burnt sienna', A}) -> { 234, 126, 93, A}; -%name_to_color({crayon, brown, A}) -> { 180, 103, 77, A}; -%name_to_color({crayon, sepia, A}) -> { 165, 105, 79, A}; -%name_to_color({crayon, orange, A}) -> { 255, 117, 56, A}; -%name_to_color({crayon, 'burnt orange', A}) -> { 255, 127, 73, A}; -%name_to_color({crayon, copper, A}) -> { 221, 148, 117, A}; -%name_to_color({crayon, 'mango tango', A}) -> { 255, 130, 67, A}; -%name_to_color({crayon, 'atomic tangerine', A}) -> { 255, 164, 116, A}; -%name_to_color({crayon, beaver, A}) -> { 159, 129, 112, A}; -%name_to_color({crayon, 'antique brass', A}) -> { 205, 149, 117, A}; -%name_to_color({crayon, 'desert sand', A}) -> { 239, 205, 184, A}; -%name_to_color({crayon, 'raw sienna', A}) -> { 214, 138, 89, A}; -%name_to_color({crayon, tumbleweed, A}) -> { 222, 170, 136, A}; -%name_to_color({crayon, tan, A}) -> { 250, 167, 108, A}; -%name_to_color({crayon, peach, A}) -> { 255, 207, 171, A}; -%name_to_color({crayon, 'macaroni and cheese', A}) -> { 255, 189, 136, A}; -%name_to_color({crayon, apricot, A}) -> { 253, 217, 181, A}; -%name_to_color({crayon, 'neon carrot', A}) -> { 255, 163, 67, A}; -%name_to_color({crayon, almond, A}) -> { 239, 219, 197, A}; -%name_to_color({crayon, 'yellow orange', A}) -> { 255, 182, 83, A}; -%name_to_color({crayon, gold, A}) -> { 231, 198, 151, A}; -%name_to_color({crayon, shadow, A}) -> { 138, 121, 93, A}; -%name_to_color({crayon, 'banana mania', A}) -> { 250, 231, 181, A}; -%name_to_color({crayon, sunglow, A}) -> { 255, 207, 72, A}; -%name_to_color({crayon, goldenrod, A}) -> { 252, 217, 117, A}; -%name_to_color({crayon, dandelion, A}) -> { 253, 219, 109, A}; -%name_to_color({crayon, yellow, A}) -> { 252, 232, 131, A}; -%name_to_color({crayon, 'green yellow', A}) -> { 240, 232, 145, A}; -%name_to_color({crayon, 'spring green', A}) -> { 236, 234, 190, A}; -%name_to_color({crayon, 'olive green', A}) -> { 186, 184, 108, A}; -%name_to_color({crayon, 'laser lemon', A}) -> { 253, 252, 116, A}; -%name_to_color({crayon, 'unmellow yellow', A}) -> { 253, 252, 116, A}; -%name_to_color({crayon, canary, A}) -> { 255, 255, 153, A}; -%name_to_color({crayon, 'yellow green', A}) -> { 197, 227, 132, A}; -%name_to_color({crayon, 'inch worm', A}) -> { 178, 236, 93, A}; -%name_to_color({crayon, asparagus, A}) -> { 135, 169, 107, A}; -%name_to_color({crayon, 'granny smith apple', A}) -> { 168, 228, 160, A}; -%name_to_color({crayon, 'electric lime', A}) -> { 29, 249, 20, A}; -%name_to_color({crayon, 'screamin green', A}) -> { 118, 255, 122, A}; -%name_to_color({crayon, fern, A}) -> { 113, 188, 120, A}; -%name_to_color({crayon, 'forest green', A}) -> { 109, 174, 129, A}; -%name_to_color({crayon, 'sea green', A}) -> { 159, 226, 191, A}; -%name_to_color({crayon, green, A}) -> { 28, 172, 120, A}; -%name_to_color({crayon, 'mountain meadow', A}) -> { 48, 186, 143, A}; -%name_to_color({crayon, shamrock, A}) -> { 69, 206, 162, A}; -%name_to_color({crayon, 'jungle green', A}) -> { 59, 176, 143, A}; -%name_to_color({crayon, 'caribbean green', A}) -> { 28, 211, 162, A}; -%name_to_color({crayon, 'tropical rain forest', A}) -> { 23, 128, 109, A}; -%name_to_color({crayon, 'pine green', A}) -> { 21, 128, 120, A}; -%name_to_color({crayon, 'robin egg blue', A}) -> { 31, 206, 203, A}; -%name_to_color({crayon, aquamarine, A}) -> { 120, 219, 226, A}; -%name_to_color({crayon, 'turquoise blue', A}) -> { 119, 221, 231, A}; -%name_to_color({crayon, 'sky blue', A}) -> { 128, 218, 235, A}; -%name_to_color({crayon, 'outer space', A}) -> { 65, 74, 76, A}; -%name_to_color({crayon, 'blue green', A}) -> { 25, 158, 189, A}; -%name_to_color({crayon, 'pacific blue', A}) -> { 28, 169, 201, A}; -%name_to_color({crayon, cerulean, A}) -> { 29, 172, 214, A}; -%name_to_color({crayon, cornflower, A}) -> { 154, 206, 235, A}; -%name_to_color({crayon, 'midnight blue', A}) -> { 26, 72, 118, A}; -%name_to_color({crayon, 'navy blue', A}) -> { 25, 116, 210, A}; -%name_to_color({crayon, denim, A}) -> { 43, 108, 196, A}; -%name_to_color({crayon, blue, A}) -> { 31, 117, 254, A}; -%name_to_color({crayon, periwinkle, A}) -> { 197, 208, 230, A}; -%name_to_color({crayon, 'cadet blue', A}) -> { 176, 183, 198, A}; -%name_to_color({crayon, indigo, A}) -> { 93, 118, 203, A}; -%name_to_color({crayon, 'wild blue yonder', A}) -> { 162, 173, 208, A}; -%name_to_color({crayon, manatee, A}) -> { 151, 154, 170, A}; -%name_to_color({crayon, 'blue bell', A}) -> { 173, 173, 214, A}; -%name_to_color({crayon, 'blue violet', A}) -> { 115, 102, 189, A}; -%name_to_color({crayon, 'purple heart', A}) -> { 116, 66, 200, A}; -%name_to_color({crayon, 'royal purple', A}) -> { 120, 81, 169, A}; -%name_to_color({crayon, 'purple mountains majesty', A}) -> { 157, 129, 186, A}; -%name_to_color({crayon, violet, A}) -> { 146, 110, 174, A}; -%name_to_color({crayon, wisteria, A}) -> { 205, 164, 222, A}; -%name_to_color({crayon, 'vivid violet', A}) -> { 143, 80, 157, A}; -%name_to_color({crayon, fuchsia, A}) -> { 195, 100, 197, A}; -%name_to_color({crayon, 'shocking pink', A}) -> { 251, 126, 253, A}; -%name_to_color({crayon, 'pink flamingo', A}) -> { 252, 116, 253, A}; -%name_to_color({crayon, plum, A}) -> { 142, 69, 133, A}; -%name_to_color({crayon, 'hot magenta', A}) -> { 255, 29, 206, A}; -%name_to_color({crayon, 'purple pizzazz', A}) -> { 255, 29, 206, A}; -%name_to_color({crayon, 'razzle dazzle rose', A}) -> { 255, 72, 208, A}; -%name_to_color({crayon, orchid, A}) -> { 230, 168, 215, A}; -%name_to_color({crayon, 'red violet', A}) -> { 192, 68, 143, A}; -%name_to_color({crayon, eggplant, A}) -> { 110, 81, 96, A}; -%name_to_color({crayon, cerise, A}) -> { 221, 68, 146, A}; -%name_to_color({crayon, 'wild strawberry', A}) -> { 255, 67, 164, A}; -%name_to_color({crayon, magenta, A}) -> { 246, 100, 175, A}; -%name_to_color({crayon, lavender, A}) -> { 252, 180, 213, A}; -%name_to_color({crayon, 'cotton candy', A}) -> { 255, 188, 217, A}; -%name_to_color({crayon, 'violet red', A}) -> { 247, 83, 148, A}; -%name_to_color({crayon, 'carnation pink', A}) -> { 255, 170, 204, A}; -%name_to_color({crayon, razzmatazz, A}) -> { 227, 37, 107, A}; -%name_to_color({crayon, 'piggy pink', A}) -> { 253, 215, 228, A}; -%name_to_color({crayon, 'jazzberry jam', A}) -> { 202, 55, 103, A}; -%name_to_color({crayon, blush, A}) -> { 222, 93, 131, A}; -%name_to_color({crayon, 'tickle me pink', A}) -> { 252, 137, 172, A}; -%name_to_color({crayon, 'pink sherbet', A}) -> { 247, 128, 161, A}; -%name_to_color({crayon, maroon, A}) -> { 200, 56, 90, A}; -%name_to_color({crayon, red, A}) -> { 238, 32, 77, A}; -%name_to_color({crayon, 'radical red', A}) -> { 255, 73, 108, A}; -%name_to_color({crayon, mauvelous, A}) -> { 239, 152, 170, A}; -%name_to_color({crayon, 'wild watermelon', A}) -> { 252, 108, 133, A}; -%name_to_color({crayon, scarlet, A}) -> { 252, 40, 71, A}; -%name_to_color({crayon, salmon, A}) -> { 255, 155, 170, A}; -%name_to_color({crayon, 'brick red', A}) -> { 203, 65, 84, A}; -%name_to_color({crayon, white, A}) -> { 237, 237, 237, A}; -%name_to_color({crayon, timberwolf, A}) -> { 219, 215, 210, A}; -%name_to_color({crayon, silver, A}) -> { 205, 197, 194, A}; -%name_to_color({crayon, gray, A}) -> { 149, 145, 140, A}; -%name_to_color({crayon, black, A}) -> { 35, 35, 35, A}. - - text(I, {Xs,Ys} = Sp, Font, Text, Color) -> {FW,FH} = egd_font:size(Font), Length = length(Text), diff --git a/lib/percept/src/egd_render.erl b/lib/percept/src/egd_render.erl index f5e32c2a0f..cea9d2d926 100644 --- a/lib/percept/src/egd_render.erl +++ b/lib/percept/src/egd_render.erl @@ -35,7 +35,7 @@ binary(Image, Type) -> parallel_binary(precompile(Image),Type). parallel_binary(Image = #image{ height = Height },Type) -> - case lists:min([erlang:system_info(schedulers), Height]) of + case erlang:min(erlang:system_info(schedulers), Height) of 1 -> % if the height or the number of schedulers is 1 % do the scanlines in this process. @@ -120,27 +120,15 @@ receive_binaries(H, Bins) when H > 0 -> scanline(Y, Os, {_,_,Width,_}=LSB, Type) -> - OLSs = parse_objects_on_line(Y-1, Width, Os), - URLSs = resulting_line_spans([LSB|OLSs],Type), - - % FIXME: Can we keep the list sorted instead of sorting it? - % sort descending - RLSs = lists:reverse(URLSs), - - resulting_scanline(RLSs,Width). - -resulting_scanline(RLSs, Width) -> resulting_scanline(RLSs, Width, []). -resulting_scanline([], _, Scanlines) -> Scanlines; -resulting_scanline([{_,Xl, Xr, C} | RLSs], Width, Scanlines) -> - {R,G,B,_} = rgb_float2byte(C), - Scanline = lists:duplicate(trunc(Xr - Xl + 1), <<R:8,G:8,B:8>>), - resulting_scanline(RLSs, Width, [Scanline|Scanlines]). + OLSs = parse_objects_on_line(Y-1, Width, Os), + RLSs = resulting_line_spans([LSB|OLSs],Type), + [ lists:duplicate(Xr - Xl + 1, <<(trunc(R*255)):8,(trunc(G*255)):8,(trunc(B*255)):8>>) || {_,Xl, Xr, {R,G,B,_}} <- RLSs ]. resulting_line_spans(LSs,Type) -> %% Build a list of "transitions" from left to right. Trans = line_spans_to_trans(LSs), %% Convert list of "transitions" to linespans. - trans_to_line_spans(Trans,Type). + trans_to_line_spans(Trans,Type). line_spans_to_trans(LSs) -> line_spans_to_trans(LSs,[],0). @@ -194,19 +182,14 @@ color([{_,C}|_],opaque) -> C; color(Layers,alpha) -> color1({0,0,0,0},Layers). color1(Color,[]) -> Color; -color1(Color,[{_,C}|Layers]) -> color1(blend(Color,C),Layers). - -blend(C1,C2) -> alpha_blend(C1,C2). +color1(Color,[{_,C}|Layers]) -> color1(alpha_blend(Color,C),Layers). modify_layers(Layers,[]) -> Layers; -modify_layers(Layers,[{{_,Z,Op},C}|Trans]) -> - modify_layers(case Op of - start -> - add_layer(Layers,Z,C); - stop -> - remove_layer(Layers,Z,C) - end, - Trans). +modify_layers(Layers,[{{_,Z,start},C}|Trans]) -> + modify_layers(add_layer(Layers, Z, C), Trans); +modify_layers(Layers,[{{_,Z,stop },C}|Trans]) -> + modify_layers(remove_layer(Layers, Z, C), Trans). + add_layer([{Z1,_}=H|Layers],Z,C) when Z1 > Z -> [H|add_layer(Layers,Z,C)]; @@ -216,7 +199,7 @@ add_layer(Layers,Z,C) -> remove_layer(Layers,Z,C) -> Layers -- [{Z,C}]. -alpha_blend({R1,G1,B1,A1}, {R2,G2,B2,A2}) -> +alpha_blend({R1,G1,B1,A1}, {R2,G2,B2,A2}) when is_float(A1), is_float(A2)-> Beta = A2*(1.0 - A1), A = A1 + Beta, R = R1*A1 + R2*Beta, @@ -232,7 +215,7 @@ parse_objects_on_line(Y, Z, Width, [O|Os], Out) -> false -> parse_objects_on_line(Y, Z + 1, Width, Os, Out); true -> - OLs = object_line_data(Y, Z, O), + OLs = object_line_data(Y, Z, O), TOLs = trim_object_line_data(OLs, Width), parse_objects_on_line(Y, Z + 1, Width, Os, [TOLs|Out]) end. @@ -240,15 +223,13 @@ parse_objects_on_line(Y, Z, Width, [O|Os], Out) -> trim_object_line_data(OLs, Width) -> trim_object_line_data(OLs, Width, []). trim_object_line_data([], _, Out) -> Out; + +trim_object_line_data([{_, Xl, _, _}|OLs], Width, Out) when Xl > Width -> + trim_object_line_data(OLs, Width, Out); +trim_object_line_data([{_, _, Xr, _}|OLs], Width, Out) when Xr < 0 -> + trim_object_line_data(OLs, Width, Out); trim_object_line_data([{Z, Xl, Xr, C}|OLs], Width, Out) -> - if - Xl > Width -> - trim_object_line_data(OLs, Width, Out); - Xr < 0 -> - trim_object_line_data(OLs, Width, Out); - true -> - trim_object_line_data(OLs, Width, [{Z, lists:max([0,Xl]), lists:min([Xr,Width]), C}|Out]) - end. + trim_object_line_data(OLs, Width, [{Z, erlang:max(0,Xl), erlang:min(Xr,Width), C}|Out]). % object_line_data % In: @@ -264,7 +245,8 @@ trim_object_line_data([{Z, Xl, Xr, C}|OLs], Width, Out) -> % Calculate the length (start and finish index) of an objects horizontal % line given the height index. -object_line_data(Y, Z, Object) -> object_line_data(Y, Z, Object, Object#image_object.type). +object_line_data(Y, Z, Object) -> + object_line_data(Y, Z, Object, Object#image_object.type). object_line_data(Y, Z, #image_object{ span = {X0, Y0, X1, Y1}, color = C}, rectangle) -> if Y0 =:= Y ; Y1 =:= Y -> @@ -277,70 +259,43 @@ object_line_data(Y, Z, #image_object{ span = {X0, Y0, X1, Y1}, color = C}, recta object_line_data(_Y, Z, #image_object{ span = {X0, _, X1, _}, color = C}, filled_rectangle) -> [{Z, X0, X1, C}]; -object_line_data(Y, Z, #image_object{ span = {X0,Y0,X1,Y1}, color = C}, filled_ellipse) -> +object_line_data(Y, Z, #image_object{ internals={Xr,Yr,Yr2}, span = {X0,Y0,X1,Y1}, color = C}, filled_ellipse) -> if - X1 - X0 == 0 -> % if the width is exactly one pixel - [{Z, X1, X0, C}]; - X1 - X0 < 0 -> throw(bad_ellipse_width); - Y1 - Y0 == 0 -> % Height exactly one pixel, get width + X1 - X0 == 0; Y1 - Y0 == 0 -> [{Z, X0, X1, C}]; true -> - Xr = (X1 - X0)/2, - Yr = (Y1 - Y0)/2, - Yo = trunc(Y - Y0 - Yr), + Yo = trunc(Y - Y0 - Yr), Yo2 = Yo*Yo, - Yr2 = Yr*Yr, - Xo = math:sqrt((1 - Yo2/Yr2))*Xr, + Xo = math:sqrt((1 - Yo2/Yr2))*Xr, [{Z, round(X0 - Xo + Xr), round(X0 + Xo + Xr), C}] end; object_line_data(Y, Z, #image_object{ intervals = Is, color = C}, filled_triangle) -> - case lists:keysearch(Y, 1, Is) of - {value, {Y, Xl, Xr}} -> [{Z, Xl, Xr, C}]; + case lists:keyfind(Y, 1, Is) of + {Y, Xl, Xr} -> [{Z, Xl, Xr, C}]; false -> [] end; object_line_data(Y, Z, #image_object{ intervals = Is, color = C}, line) -> case dict:find(Y, Is) of - %{ok, {Xl, Xr}} -> [{Z, Xl, Xr, C}]; {ok, Ls} -> [{Z, Xl, Xr, C}||{Xl,Xr} <- Ls]; _ -> [] end; -object_line_data(Y, Z, O, polygon) -> - Is = lists:filter( - fun({Yp,_,_}) -> - if Yp == Y -> true; true -> false end - end, O#image_object.intervals), - [ {Z, Xl, Xr, O#image_object.color} || {_, Xl, Xr} <- Is]; - -object_line_data(Y, Z, #image_object{ color = C, intervals = Is }, text_horizontal) -> - % FIXME: optimize! - lists:foldl( - fun ({Yg,Xl,Xr}, Out) -> - if - Yg == Y -> - [{Z, Xl, Xr, C}|Out]; - true -> - Out - end - end, [], Is); +object_line_data(Y, Z, #image_object{ color = C, intervals = Is}, polygon) -> + [{Z, Xl, Xr, C} || {Yp, Xl, Xr} <- Is, Yp =:= Y]; + +object_line_data(Y, Z, #image_object{ color = C, intervals = Is}, text_horizontal) -> + [{Z, Xl, Xr, C} || {Yg, Xl, Xr} <- Is, Yg =:= Y]; + object_line_data(_, Z, #image_object{ span = {X0,_,X1,_}, color = C}, _) -> - % faked [{Z, X0, X1, C}]. -is_object_on_line(Y, Object) -> - is_object_bounds_on_line(Y, Object#image_object.span). +is_object_on_line(Y, #image_object{ span = Span }) -> + is_object_bounds_on_line(Y, Span). -is_object_bounds_on_line(Y, {_,Y0,_,Y1}) -> - if - Y < Y0 -> false; - Y > Y1 -> false; - true -> true - end. - -rgb_float2byte({R,G,B,A}) -> - {trunc(R*255), trunc(G*255), trunc(B*255), trunc(A*255)}. +is_object_bounds_on_line(Y, {_,Y0,_,Y1}) when Y < Y0 ; Y > Y1 -> false; +is_object_bounds_on_line(_, _) -> true. %%% primitives to line_spans @@ -360,6 +315,12 @@ precompile_objects([O = #image_object{ type = filled_triangle, points = [P0,P1,P precompile_objects([O = #image_object{ type = polygon, points = Pts } | Os], Out) -> precompile_objects(Os, [O#image_object{ intervals = polygon_ls(Pts) } | Out]); + +precompile_objects([O = #image_object{ type = filled_ellipse, span = {X0,Y0,X1,Y1} } | Os], Out) -> + Xr = (X1 - X0)/2, + Yr = (Y1 - Y0)/2, + Yr2 = Yr*Yr, + precompile_objects(Os, [ O#image_object{ internals={Xr,Yr,Yr2} } | Out]); precompile_objects([O = #image_object{ type = arc, points = [P0,P1], internals = D }| Os], Out) -> Es = egd_primitives:arc_to_edges(P0, P1, D), @@ -579,13 +540,7 @@ line_ls({Xi0, Yi0},{Xi1,Yi1}) -> true -> 1; false -> -1 end, - case Steep of - false -> - line_ls_step_not_steep({X0, X1},Y0, DX, DY, Ystep, Error, X0, []); - true -> - line_ls_step_steep({X0, X1},Y0, DX, DY, Ystep, Error, X0, []) - end. - + line_ls_step(X0, X1,Y0, DX, DY, Ystep, Error, X0, Steep, []). %% line_ls_step_(not)_steep %% In: @@ -594,27 +549,17 @@ line_ls({Xi0, Yi0},{Xi1,Yi1}) -> %% Purpose: %% Produce an line_interval for each Yi (Y index) -% Iterating the X-axis - -line_ls_step_not_steep({X,X1},Y,Dx,Dy,Ys,E, X0, LSs) when X < X1 -> - case E >= 0 of - true -> - line_ls_step_not_steep({X+1,X1},Y+Ys,Dx,Dy,Ys, E - Dx + Dy, X+1,[{Y,X0,X}|LSs]); - false -> - line_ls_step_not_steep({X+1,X1},Y,Dx,Dy,Ys, E + Dy, X0, LSs) - end; -line_ls_step_not_steep({X,_},Y,_Dx,_Dy,_Ystep,_E,X0,LSs) -> - [{Y,X0,X}|LSs]. - -% Iterating the Y-axis -line_ls_step_steep({X,X1},Y,Dx,Dy,Ystep,E, X0, LSs) when X =< X1 -> - case E >= 0 of - true -> - line_ls_step_steep({X + 1,X1},Y+Ystep,Dx,Dy,Ystep,E - Dx + Dy,X,[{X,Y,Y}|LSs]); - false -> - line_ls_step_steep({X + 1,X1},Y,Dx,Dy,Ystep,E + Dy,X0, [{X,Y,Y}|LSs]) - end; -line_ls_step_steep({_X,_},_Y,_Dx,_Dy,_Ystep,_E,_X0,LSs) -> +line_ls_step(X, X1, Y, Dx, Dy, Ys, E, X0, false = Steep, LSs) when X < X1, E >= 0 -> + line_ls_step(X+1,X1,Y+Ys,Dx,Dy,Ys, E - Dx + Dy, X+1, Steep, [{Y,X0,X}|LSs]); +line_ls_step(X, X1, Y, Dx, Dy, Ys, E, X0, false = Steep, LSs) when X < X1 -> + line_ls_step(X+1,X1,Y,Dx,Dy,Ys, E + Dy, X0, Steep, LSs); +line_ls_step(X, _X1, Y, _Dx, _Dy, _Ys, _E, X0, false, LSs) -> + [{Y,X0,X}|LSs]; +line_ls_step(X, X1, Y, Dx, Dy, Ys, E, _X0, true = Steep, LSs) when X =< X1, E >= 0 -> + line_ls_step(X+1,X1,Y+Ys,Dx,Dy,Ys, E - Dx + Dy, X, Steep, [{X,Y,Y}|LSs]); +line_ls_step(X, X1, Y, Dx, Dy, Ys, E, X0, true = Steep, LSs) when X =< X1 -> + line_ls_step(X+1,X1,Y,Dx,Dy,Ys,E + Dy, X0, Steep, [{X,Y,Y}|LSs]); +line_ls_step(_X,_,_Y,_Dx,_Dy,_Ys,_E,_X0,_,LSs) -> LSs. % Text @@ -707,3 +652,4 @@ eps_header(W,H) -> eps_footer() -> "%%EOF\n". + diff --git a/lib/percept/test/egd_SUITE.erl b/lib/percept/test/egd_SUITE.erl index 603ad628d3..a2595400dd 100644 --- a/lib/percept/test/egd_SUITE.erl +++ b/lib/percept/test/egd_SUITE.erl @@ -29,6 +29,7 @@ -export([ image_create_and_destroy/1, image_shape/1, + image_primitives/1, image_colors/1, image_font/1, image_png_compliant/1 @@ -38,8 +39,7 @@ -define(default_timeout, ?t:minutes(1)). init_per_suite(Config) when is_list(Config) -> - {A1,A2,A3} = now(), - random:seed(A1, A2, A3), + random:seed(now()), Config. end_per_suite(Config) when is_list(Config) -> @@ -59,6 +59,7 @@ all(suite) -> [ image_create_and_destroy, image_shape, + image_primitives, image_colors, image_font, image_png_compliant @@ -145,7 +146,43 @@ image_shape(Config) when is_list(Config) -> ?line ok = egd:destroy(Im), erase(image_size), ok. - + +image_primitives(suite) -> + []; +image_primitives(doc) -> + ["Image shape api test."]; +image_primitives(Config) when is_list(Config) -> + {W,H} = get_size(?config(max_size, Config)), + put(image_size, {W,H}), + + ?line Im0 = egd_primitives:create(W, H), + ?line Fgc = egd:color({25,25,255}), + ?line Bgc = egd:color({0,250,25}), + + ?line Im1 = lists:foldl(fun + ({Function, Arguments}, Im) -> + ?line erlang:apply(egd_primitives, Function, [Im|Arguments]) + end, Im0, + [{Fs, [get_point(), get_point(), Bgc]} || Fs <- [line, rectangle, filledEllipse, arc]] ++ + [{pixel, [get_point(), Bgc]}, + {filledTriangle, [get_point(), get_point(), get_point(), Bgc]}]), + + Pt1 = get_point(), + Pt2 = get_point(), + + ?line Im2 = egd_primitives:filledRectangle(Im1, Pt1, Pt2, Fgc), + + ?line Bitmap = egd_render:binary(Im2, opaque), + + ?line ok = bitmap_point_has_color(Bitmap, {W,H}, Pt2, Fgc), + ?line ok = bitmap_point_has_color(Bitmap, {W,H}, Pt1, Fgc), + + erase(image_size), + ok. + + + + image_font(suite) -> []; image_font(doc) -> diff --git a/lib/public_key/doc/src/cert_records.xml b/lib/public_key/doc/src/cert_records.xml index 8fb4ea5fd0..8cfe57f670 100644 --- a/lib/public_key/doc/src/cert_records.xml +++ b/lib/public_key/doc/src/cert_records.xml @@ -41,10 +41,18 @@ </p> <p>Use the following include directive to get access to the - records and constant macros described in the following sections.</p> + records and constant macros (OIDs) described in the following sections.</p> <code> -include_lib("public_key/include/public_key.hrl"). </code> + <p>The used specification is available in <c>OTP-PKIX.asn1</c>, + which is an amelioration of + the <c>PKIX1Explicit88.asn1</c>, <c>PKIX1Implicit88.asn1</c> + and <c>PKIX1Algorithms88.asn1</c> modules. + You find all these modules in the <c>asn1</c> subdirectory + of the application <c>public_key</c>. + </p> + <section> <title>Common Data Types</title> @@ -148,8 +156,7 @@ oid names see table below. Ex: ?'id-dsa-with-sha1'</p> }. </code> -<p><c>id_attributes() = ?oid_name_as_erlang_atom</c> -for available oid names see table below. Ex: ?'id-at-name'</p> +<p><c>id_attributes() </c></p> <table> <row> <cell align="left" valign="middle">OID name</cell> @@ -231,8 +238,7 @@ for available oid names see table below. Ex: ?'id-at-name'</p> }. </code> -<p><c> id_public_key_algorithm() = ?oid_name_as_erlang_atom</c> for available -oid names see table below. Ex: ?'id-dsa'</p> +<p><c> id_public_key_algorithm() </c></p> <table> <row> <cell align="left" valign="middle">OID name</cell> @@ -264,14 +270,11 @@ oid names see table below. Ex: ?'id-dsa'</p> }. </code> -<p><c>id_extensions() = ?oid_name_as_erlang_atom</c> for -available oid names see tables. Ex: ?'id-ce-authorityKeyIdentifier'<seealso -marker="#StdCertExt">Standard Certificate Extensions</seealso>, - <seealso - marker="#PrivIntExt">Private Internet Extensions</seealso>, <seealso - marker="#CRLCertExt">CRL Extensions</seealso> and - <seealso - marker="#CRLEntryExt">CRL Entry Extensions</seealso>. +<p><c>id_extensions()</c> + <seealso marker="#StdCertExt">Standard Certificate Extensions</seealso>, + <seealso marker="#PrivIntExt">Private Internet Extensions</seealso>, + <seealso marker="#CRLCertExt">CRL Extensions</seealso> and + <seealso marker="#CRLEntryExt">CRL Entry Extensions</seealso>. </p> </section> @@ -368,9 +371,8 @@ marker="#StdCertExt">Standard Certificate Extensions</seealso>, decipherOnly </c></p> - <p><c> id_key_purpose() = ?oid_name_as_erlang_atom</c> for available -oid names see table below. Ex: ?'id-kp-serverAuth'</p> - + <p><c> id_key_purpose()</c></p> + <table> <row> <cell align="left" valign="middle">OID name</cell> diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile index d2907a39d7..e02f04e7ad 100644 --- a/lib/ssh/doc/src/Makefile +++ b/lib/ssh/doc/src/Makefile @@ -53,8 +53,8 @@ XML_REF3_FILES = \ ssh_sftp.xml \ ssh_sftpd.xml \ -XML_PART_FILES = part_notes.xml part_notes_history.xml -XML_CHAPTER_FILES = notes.xml notes_history.xml +XML_PART_FILES = part_notes.xml +XML_CHAPTER_FILES = notes.xml BOOK_FILES = book.xml @@ -70,8 +70,6 @@ EXTRA_FILES = \ $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \ $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html) -# notes_history.html \ - MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3) diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index 54e0cf9059..ef49bb8b3d 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -29,6 +29,19 @@ <file>notes.xml</file> </header> + <section><title>Ssh 1.1.8</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Old release notes removed.</p> + <p>Own Id: OTP-8356 Aux Id:</p> + </item> + </list> + </section> + + </section> + <section><title>Ssh 1.1.7</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -581,8 +594,6 @@ </list> </section> - <!-- p>For information about older versions see - <url href="part_notes_history_frame.html">release notes history</url>.</p --> </section> </chapter> diff --git a/lib/ssh/doc/src/notes_history.xml b/lib/ssh/doc/src/notes_history.xml deleted file mode 100644 index bfebcd4bf4..0000000000 --- a/lib/ssh/doc/src/notes_history.xml +++ /dev/null @@ -1,737 +0,0 @@ -<?xml version="1.0" encoding="latin1" ?> -<!DOCTYPE chapter SYSTEM "chapter.dtd"> - -<chapter> - <header> - <copyright> - <year>2009</year> - <year>2009</year> - <holder>Ericsson AB, All Rights Reserved</holder> - </copyright> - <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - The Initial Developer of the Original Code is Ericsson AB. - </legalnotice> - - <title>SSH Release Notes History</title> - <prepared></prepared> - <responsible></responsible> - <docno></docno> - <approved></approved> - <checked></checked> - <date></date> - <rev>A</rev> - <file>notes_history.xml</file> - </header> - - <section><title>Ssh 0.9.9.6</title> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - Updated asn1 file due to change in the asn1 compiler. - This has no semantical effect on the ssh application.</p> - <p> - Own Id: OTP-7246</p> - </item> - <item> - <p> - Allows for the option {fd, FD} in listen and connect - calls. The option is passed on to gen_tcp:listen and - gen_tcp:connect</p> - <p> - Own Id: OTP-7247</p> - </item> - </list> - </section> -</section> - - <section><title>Ssh 0.9.9.5</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - Putty version 0.60 sends ignore messages, which hanged - the OTP ssh server.</p> - <p> - Own Id: OTP-7076</p> - </item> - <item> - <p> - ssh_cm hanged when connection was closed during - handshake. (Triggered by putty 0.60 client.)</p> - <p> - Own Id: OTP-7089</p> - </item> - <item> - <p> - Fixed crash in server when receiving an empty ignore-msg. - (From the putty 0.60 client.)</p> - <p> - Own Id: OTP-7135</p> - </item> - </list> - </section> - - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - Now uses the base 64 encode/decode function in stdlib.</p> - <p> - Own Id: OTP-6486</p> - </item> - <item> - <p> - Removed runtime dependency on asn1.</p> - <p> - Own Id: OTP-6570</p> - </item> - <item> - <p> - Documentation update of ssh.</p> - <p> - Own Id: OTP-7063 Aux Id: seq10789 </p> - </item> - <item> - <p> - Same listener is used for both sshd and sftpd. Previously - the sftpd server had to be run on a separate port, now - the sshd listener will start an sftpd server when an sftp - client connects.</p> - <p> - Own Id: OTP-7090 Aux Id: seq10675 </p> - </item> - <item> - <p> - Kebord-interactive support, according to rfc 4256, has - been added to the ssh client. Also the option - <c>quiet_mode</c> has been added so that unwanted banners - may be suppressed.</p> - <p> - Own Id: OTP-7106 Aux Id: seq10841 </p> - </item> - </list> - </section> - - </section> - - <section><title>Ssh 0.9.9.4</title> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - [sftpd] - Root parameter now behaves as expected, - instead of making sftpd malfunction.</p> - <p> - Own Id: OTP-7057 Aux Id: seq10830 </p> - </item> - </list> - </section> - </section> - - <section><title>Ssh 0.9.9.3</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - The sftp-server could crash if a "ls" was done on the - client, and a file was removed while ssh_sftpd:list_dir - was reading the directory, an error code from - read_file_info wasn't handled properly. This fix makes ls - return an error code instead.</p> - <p> - Own Id: OTP-6854 Aux Id: seq10740 </p> - </item> - <item> - <p> - Fixed bugs in prompting in ssl_cli. Prompts like \003> - were written as \300>. Also, newlines and returns was - removed.</p> - <p> - Own Id: OTP-6917 Aux Id: seq10773 </p> - </item> - </list> - </section> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - [sftpd] - New option "root" to set the root of the - sftp-server and the callback module for file handling now - has a state parameter.</p> - <p> - Own Id: OTP-7075 Aux Id: seq10675 </p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssh 0.9.9.2</title> - <section> - <title>Better error-handling in ssh_sshd:listen</title> - <list type="bulleted"> - <item> - <p>The caller was hanged when listening with ssh_sshd:listen - (or ssh_sftpd:listen) on a port and IP already in use. - Now an error is returned instead.</p> - <p>Own Id: OTP-6727</p> - </item> - </list> - </section> - - <section> - <title>Fix in ssh_sftpd</title> - <list type="bulleted"> - <item> - <p>Cd ../.. didn't work when connecting to a ssh_sftpd server.</p> - <p>Own Id: OTP-6727</p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssh 0.9.9.1</title> - - <section> - <title>Minor Makefile changes</title> - <list type="bulleted"> - <item> - <p>Removed use of <c><![CDATA[erl_flags]]></c> from Makefile.</p> - <p>Own Id: OTP-6689</p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssh 0.9.9</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>A race condition that could make the server crash if a - client sent a SSH_MSG_USERAUTH_REQUEST packet immediately - after its SSH_MSG_SERVICE_REQUEST, is removed.</p> - <p>Own Id: OTP-6379 Aux Id: seq10523 </p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssh 0.9.8</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Corrected minor bugs and removed dead code found by - dialyzer.</p> - <p>Own Id: OTP-6524</p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssh 0.9.7</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>[sftp] - The function ssh_sftp:make_symlink/3 was not - fully implemented.</p> - <p>Own Id: OTP-6446</p> - </item> - <item> - <p>[ssh] - An internal value was, due to a bug, always set - to undefined even when it was not, this could lead to - connections being wrongly refused.</p> - <p>Own Id: OTP-6450</p> - </item> - <item> - <p>A pattern matching was missing "/binary" resulting in - that the internal function ssh_xfer:decode_acl/2 did not - work as expected.</p> - <p>Own Id: OTP-6458</p> - </item> - <item> - <p>[sftp] - read_link/2 did not return the documented value</p> - <p>Own Id: OTP-6471</p> - </item> - <item> - <p>Removed debugg printouts from ssh_cli.erl</p> - <p>Own Id: OTP-6483</p> - </item> - <item> - <p>[sftp, ssh] - The connection timeout was overridden by an - internal gen_server default timeout.</p> - <p>Own Id: OTP-6488 Aux Id: seq10569 </p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssh 0.9.6</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Removed debug printout from production code.</p> - <p>Own Id: OTP-6348 Aux Id: seq10510 </p> - </item> - <item> - <p>[sftpd] - When the sftp client ends the session the - server will now behave correctly and not leave the client - hanging.</p> - <p>Own Id: OTP-6349 Aux Id: seq10510 </p> - </item> - <item> - <p>[sftpd] - No longer used files were not closed until the - session was ended.</p> - <p>Own Id: OTP-6350 Aux Id: seq10514 </p> - </item> - <item> - <p>[sftpd] - File rename requests sent by sftp version 3 - clients were not handled.</p> - <p>Own Id: OTP-6352 Aux Id: seq10513 </p> - </item> - <item> - <p>[sftpd] - Request that did not fit into one ssh message - were not handled.</p> - <p>Own Id: OTP-6353 Aux Id: seq10515 </p> - </item> - <item> - <p>Removed error logging of auth method none, as this is not - an error but rather a feature, that is used to get - initial information from the server.</p> - <p>Own Id: OTP-6414</p> - </item> - </list> - </section> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>[sftpd] - Added new option to specify a callback module - for the sftpd-server file handling. The default callback - module uses file and filelib.</p> - <p>Own Id: OTP-6356 Aux Id: seq10519 </p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssh 0.9.5</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The data window in SSH wasn't resized in the ssh_cli - receive data, this made the ssh_cli-server hang if more - than 64K data was received at one time. The option - tcp_nodelay was added, for nodelay in tcp connections.</p> - <p>Own Id: OTP-6231</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSH 0.9.4</title> - - <section> - <title>Reported Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Unnecessary explicit start of crypto application - in ssh application. This has been removed. The - app-file specifies that ssh depends on the crypto app. - This is enough. See also the - <seealso marker="ssh">ssh</seealso> module.</p> - <p>Also changed some error reports to info reports.</p> - <p>Own Id: OTP-6183</p> - <p>Aux Id: Seq 10383</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSH 0.9.3</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Added way for cli to get peer name</p> - <p>Own Id: OTP-6138</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSH 0.9.2</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Added some options to listen</p> - <p>Own Id: OTP-6070</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSH 0.9.1</title> - <section><title>Ssh 0.9.9.4</title> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - [sftpd] - Root parameter now behaves as expected, - instead of making sftpd malfunction.</p> - <p> - Own Id: OTP-7057 Aux Id: seq10830 </p> - </item> - </list> - </section> - </section> - - <section><title>Ssh 0.9.9.3</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - The sftp-server could crash if a "ls" was done on the - client, and a file was removed while ssh_sftpd:list_dir - was reading the directory, an error code from - read_file_info wasn't handled properly. This fix makes ls - return an error code instead.</p> - <p> - Own Id: OTP-6854 Aux Id: seq10740 </p> - </item> - <item> - <p> - Fixed bugs in prompting in ssl_cli. Prompts like \003> - were written as \300>. Also, newlines and returns was - removed.</p> - <p> - Own Id: OTP-6917 Aux Id: seq10773 </p> - </item> - </list> - </section> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - [sftpd] - New option "root" to set the root of the - sftp-server and the callback module for file handling now - has a state parameter.</p> - <p> - Own Id: OTP-7075 Aux Id: seq10675 </p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssh 0.9.9.2</title> - <section> - <title>Better error-handling in ssh_sshd:listen</title> - <list type="bulleted"> - <item> - <p>The caller was hanged when listening with ssh_sshd:listen - (or ssh_sftpd:listen) on a port and IP already in use. - Now an error is returned instead.</p> - <p>Own Id: OTP-6727</p> - </item> - </list> - </section> - - <section> - <title>Fix in ssh_sftpd</title> - <list type="bulleted"> - <item> - <p>Cd ../.. didn't work when connecting to a ssh_sftpd server.</p> - <p>Own Id: OTP-6727</p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssh 0.9.9.1</title> - - <section> - <title>Minor Makefile changes</title> - <list type="bulleted"> - <item> - <p>Removed use of <c><![CDATA[erl_flags]]></c> from Makefile.</p> - <p>Own Id: OTP-6689</p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssh 0.9.9</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>A race condition that could make the server crash if a - client sent a SSH_MSG_USERAUTH_REQUEST packet immediately - after its SSH_MSG_SERVICE_REQUEST, is removed.</p> - <p>Own Id: OTP-6379 Aux Id: seq10523 </p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssh 0.9.8</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Corrected minor bugs and removed dead code found by - dialyzer.</p> - <p>Own Id: OTP-6524</p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssh 0.9.7</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>[sftp] - The function ssh_sftp:make_symlink/3 was not - fully implemented.</p> - <p>Own Id: OTP-6446</p> - </item> - <item> - <p>[ssh] - An internal value was, due to a bug, always set - to undefined even when it was not, this could lead to - connections being wrongly refused.</p> - <p>Own Id: OTP-6450</p> - </item> - <item> - <p>A pattern matching was missing "/binary" resulting in - that the internal function ssh_xfer:decode_acl/2 did not - work as expected.</p> - <p>Own Id: OTP-6458</p> - </item> - <item> - <p>[sftp] - read_link/2 did not return the documented value</p> - <p>Own Id: OTP-6471</p> - </item> - <item> - <p>Removed debugg printouts from ssh_cli.erl</p> - <p>Own Id: OTP-6483</p> - </item> - <item> - <p>[sftp, ssh] - The connection timeout was overridden by an - internal gen_server default timeout.</p> - <p>Own Id: OTP-6488 Aux Id: seq10569 </p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssh 0.9.6</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Removed debug printout from production code.</p> - <p>Own Id: OTP-6348 Aux Id: seq10510 </p> - </item> - <item> - <p>[sftpd] - When the sftp client ends the session the - server will now behave correctly and not leave the client - hanging.</p> - <p>Own Id: OTP-6349 Aux Id: seq10510 </p> - </item> - <item> - <p>[sftpd] - No longer used files were not closed until the - session was ended.</p> - <p>Own Id: OTP-6350 Aux Id: seq10514 </p> - </item> - <item> - <p>[sftpd] - File rename requests sent by sftp version 3 - clients were not handled.</p> - <p>Own Id: OTP-6352 Aux Id: seq10513 </p> - </item> - <item> - <p>[sftpd] - Request that did not fit into one ssh message - were not handled.</p> - <p>Own Id: OTP-6353 Aux Id: seq10515 </p> - </item> - <item> - <p>Removed error logging of auth method none, as this is not - an error but rather a feature, that is used to get - initial information from the server.</p> - <p>Own Id: OTP-6414</p> - </item> - </list> - </section> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>[sftpd] - Added new option to specify a callback module - for the sftpd-server file handling. The default callback - module uses file and filelib.</p> - <p>Own Id: OTP-6356 Aux Id: seq10519 </p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssh 0.9.5</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The data window in SSH wasn't resized in the ssh_cli - receive data, this made the ssh_cli-server hang if more - than 64K data was received at one time. The option - tcp_nodelay was added, for nodelay in tcp connections.</p> - <p>Own Id: OTP-6231</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSH 0.9.4</title> - - <section> - <title>Reported Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Unnecessary explicit start of crypto application - in ssh application. This has been removed. The - app-file specifies that ssh depends on the crypto app. - This is enough. See also the - <seealso marker="ssh">ssh</seealso> module.</p> - <p>Also changed some error reports to info reports.</p> - <p>Own Id: OTP-6183</p> - <p>Aux Id: Seq 10383</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSH 0.9.3</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Added way for cli to get peer name</p> - <p>Own Id: OTP-6138</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSH 0.9.2</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Added some options to listen</p> - <p>Own Id: OTP-6070</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSH 0.9.1</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>Fixes in ssh_sftp, changes of timeout handling, - expand_fun moved to io:setopts</p> - <p>Own Id: OTP-5877 Aux Id: OTP-5781 </p> - </item> - </list> - </section> - </section> - - <section> - <title>SSH 0.9</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>The previously undocumented and UNSUPPORTED <c><![CDATA[ssh]]></c> - application has been updated and documented. This release - of the <c><![CDATA[ssh]]></c> application is still considered to be a - beta release and (if necessary) there could still be - changes in its API before it reaches 1.0.</p> - <p>Also, more cryptographic algorithms have been added to - the <c><![CDATA[crypto]]></c> application.</p> - <p>*** POTENTIAL INCOMPATIBILITY ***</p> - <p>Own Id: OTP-5631</p> - </item> - </list> - </section> - </section> - </section> - -</chapter> - - diff --git a/lib/ssh/doc/src/part_notes.xml b/lib/ssh/doc/src/part_notes.xml index f87efffe5c..700f76200c 100644 --- a/lib/ssh/doc/src/part_notes.xml +++ b/lib/ssh/doc/src/part_notes.xml @@ -31,8 +31,7 @@ <description> <p>This document describes the changes made to the SSH application. </p> - <p>For information about older versions see - <url href="part_notes_history_frame.html">release notes history</url>.</p> </description> + </description> <xi:include file="notes.xml"/> </part> diff --git a/lib/ssh/doc/src/part_notes_history.xml b/lib/ssh/doc/src/part_notes_history.xml deleted file mode 100644 index 49f72fd3db..0000000000 --- a/lib/ssh/doc/src/part_notes_history.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="latin1" ?> -<!DOCTYPE part SYSTEM "part.dtd"> - -<part> - <header> - <copyright> - <year>2004</year> - <year>2007</year> - <holder>Ericsson AB, All Rights Reserved</holder> - </copyright> - <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - The Initial Developer of the Original Code is Ericsson AB. - </legalnotice> - - <title>Ssh</title> - <prepared>Ingela Anderton Andin</prepared> - <docno></docno> - <date></date> - <rev></rev> - <file>part_notes.xml</file> - </header> - <include file="notes_history"></include> -</part> - - diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index 016fb30c69..2b9df4ae60 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,9 +1,11 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 1.1.7 +SSH_VSN = 1.1.8 APP_VSN = "ssh-$(SSH_VSN)" -TICKETS = OTP-8121 \ +TICKETS = OTP-8356 + +TICKETS_1.1.7 = OTP-8121 \ OTP-8277 \ OTP-8278 \ OTP-8201 diff --git a/lib/ssl/doc/src/create_certs.xml b/lib/ssl/doc/src/create_certs.xml index 15958ee457..79cc8a0537 100644 --- a/lib/ssl/doc/src/create_certs.xml +++ b/lib/ssl/doc/src/create_certs.xml @@ -98,12 +98,12 @@ <title>Creating the Erlang root CA</title> <p>The Erlang root CA is created with the command</p> <code type="none"> -\011openssl req -new -x509 -config /some/path/req.cnf \\ -\011 -keyout /some/path/key.pem -out /some/path/cert.pem </code> + openssl req -new -x509 -config /some/path/req.cnf \\ + -keyout /some/path/key.pem -out /some/path/cert.pem </code> <p>where the option <c>-new</c> indicates that we want to create a new certificate request and the option <c>-x509</c> implies that a self-signed certificate is created. - </p> + </p> </section> <section> @@ -111,12 +111,12 @@ <p>The OTP CA is created by first creating a certificate request with the command</p> <code type="none"> -\011openssl req -new -config /some/path/req.cnf \\ -\011 -keyout /some/path/key.pem -out /some/path/req.pem </code> + openssl req -new -config /some/path/req.cnf \\ + -keyout /some/path/key.pem -out /some/path/req.pem </code> <p>and the ask the Erlang CA to sign it:</p> <code type="none"> -\011openssl ca -batch -notext -config /some/path/req.cnf \\ -\011 -extensions ca_cert -in /some/path/req.pem -out /some/path/cert.pem </code> + openssl ca -batch -notext -config /some/path/req.cnf \\ + -extensions ca_cert -in /some/path/req.pem -out /some/path/cert.pem </code> <p>where the option <c>-extensions</c> refers to a section in the configuration file saying that it should create a CA certificate, and not a plain user certificate. diff --git a/lib/ssl/doc/src/new_ssl.xml b/lib/ssl/doc/src/new_ssl.xml index f50f714fe6..a11919eb51 100644 --- a/lib/ssl/doc/src/new_ssl.xml +++ b/lib/ssl/doc/src/new_ssl.xml @@ -437,30 +437,17 @@ end </func> <func> - <name>peercert(Socket) -> </name> - <name>peercert(Socket, Opts) -> {ok, Cert} | {error, Reason}</name> + <name>peercert(Socket) -> {ok, Cert} | {error, Reason}</name> <fsummary>Return the peer certificate.</fsummary> <type> <v>Socket = sslsocket()</v> - <v>Opts = [] | [otp] | [plain] </v> - <v>Cert = term()</v> + <v>Cert = binary()</v> <v>Subject = term()</v> </type> <desc> - <p><c>peercert(Cert)</c> is equivalent to <c>peercert(Cert, [])</c>. - </p> - <p>The form of the returned certificate depends on the - options. - </p> - <p>If the options list is empty the certificate is returned as - a DER encoded binary. - </p> - <p>The option <c>otp</c> or <c>plain</c> implies that the - certificate will be returned as a parsed ASN.1 structure in the - form of an Erlang term. For detail see the public_key application. - Currently only plain is officially supported see the public_key users - guide. - </p> + <p>The peer certificate is returned as a DER encoded binary. + The certificate can be decoded with <c>public_key:pkix_decode_cert/2</c>. + </p> </desc> </func> <func> diff --git a/lib/ssl/doc/src/pkix_certs.xml b/lib/ssl/doc/src/pkix_certs.xml index 47818c1b7d..1de807cadc 100644 --- a/lib/ssl/doc/src/pkix_certs.xml +++ b/lib/ssl/doc/src/pkix_certs.xml @@ -34,219 +34,24 @@ <p>Certificates were originally defined by ITU (CCITT) and the latest definitions are described in <cite id="X.509"></cite>, but those definitions are (as always) not working. - </p> + </p> <p>Working certificate definitions for the Internet Community are found - in the the PKIX RFCs <cite id="rfc3279"></cite>and <cite id="rfc3280"></cite>. + in the the PKIX RFCs <cite id="rfc3279"></cite> and <cite id="rfc3280"></cite>. The parsing of certificates in the Erlang/OTP SSL application is based on those RFCS. - </p> + </p> <p>Certificates are defined in terms of ASN.1 (<cite id="X.680"></cite>). For an introduction to ASN.1 see <url href="http://asn1.elibel.tm.fr/">ASN.1 Information Site</url>. - </p> + </p> </section> <section> <title>PKIX Certificates</title> - <p>Here we base the PKIX certificate definitions in RFCs <cite id="rfc3279"></cite>and <cite id="rfc3280"></cite>. We however present the - definitions according to <c>SSL-PKIX.asn1</c> module, - which is an amelioration of the <c>PKIX1Explicit88.asn1</c>, - <c>PKIX1Implicit88.asn1</c>, and <c>PKIX1Algorithms88.asn1</c> - modules. You find all these modules in the <c>pkix</c> subdirectory - of SSL. - </p> - <p>The Erlang terms that are returned by the functions - <c>ssl:peercert/1/2</c>, <c>ssl_pkix:decode_cert/1/2</c>, and - <c>ssl_pkix:decode_cert_file/1/2</c> when the option <c>ssl</c> - is used in those functions, correspond the ASN.1 structures - described in the sequel. - </p> - - <section> - <title>Certificate and TBSCertificate</title> - <code type="none"> -Certificate ::= SEQUENCE { - tbsCertificate TBSCertificate, - signatureAlgorithm SignatureAlgorithm, - signature BIT STRING } - -TBSCertificate ::= SEQUENCE { - version [0] Version DEFAULT v1, - serialNumber CertificateSerialNumber, - signature SignatureAlgorithm, - issuer Name, - validity Validity, - subject Name, - subjectPublicKeyInfo SubjectPublicKeyInfo, - issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, - -- If present, version MUST be v2 or v3 - subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, - -- If present, version MUST be v2 or v3 - extensions [3] Extensions OPTIONAL - -- If present, version MUST be v3 -- } - -Version ::= INTEGER { v1(0), v2(1), v3(2) } - -CertificateSerialNumber ::= INTEGER - -Validity ::= SEQUENCE { - notBefore Time, - notAfter Time } - -Time ::= CHOICE { - utcTime UTCTime, - generalTime GeneralizedTime } - </code> - <p>The meaning of the fields <c>version</c>, <c>serialNumber</c>, - and <c>validity</c> are quite obvious given the type definitions - above, so we do not go further into their details. - </p> - <p>The <c>signatureAlgorithm</c> field of <c>Certificate</c> and - the <c>signature</c> field of <c>TBSCertificate</c> contain - the name and parameters of the algorithm used for signing the - certificate. The values of these two fields must be equal. - </p> - <p>The <c>signature</c> field of <c>Certificate</c> contains the - value of the signature that the issuer computed by using the - prescribed algorithm. - </p> - <p>The <c><![CDATA[issuer<c> and <c>subject]]></c> fields can contain many - different types av data, and is therefore considered in a - separate section. The same holds for the <c>extensions</c> - field. - The <c>issuerUniqueID</c> and the <c>subjectUniqueID</c> fields - are not considered further.</p> - </section> - - <section> - <title>TBSCertificate issuer and subject</title> - <p></p> - <code type="none"><![CDATA[ -Name ::= CHOICE { -- only one possibility for now -- - rdnSequence RDNSequence } - -RDNSequence ::= SEQUENCE OF RelativeDistinguishedName - -DistinguishedName ::= RDNSequence - -RelativeDistinguishedName ::= - SET SIZE (1 .. MAX) OF AttributeTypeAndValue - -AttributeTypeAndValue ::= SEQUENCE { - type ATTRIBUTE-TYPE-AND-VALUE-CLASS.&id -\011\011({SupportedAttributeTypeAndValues}), - value ATTRIBUTE-TYPE-AND-VALUE-CLASS.&Type -\011\011({SupportedAttributeTypeAndValues}{@type}) } - -SupportedAttributeTypeAndValues ATTRIBUTE-TYPE-AND-VALUE-CLASS ::= -\011{ name | surname | givenName | initials | generationQualifier | -\011 commonName | localityName | stateOrProvinceName | organizationName | -\011 organizationalUnitName | title | dnQualifier | countryName | -\011 serialNumber | pseudonym | domainComponent | emailAddress } ]]></code> - </section> - - <section> - <title>TBSCertificate extensions</title> - <p>The <c>extensions</c> field of a <c>TBScertificate</c> is a - sequence of type <c>Extension</c>, defined as follows,</p> - <code type="none"> -Extension ::= SEQUENCE { - extnID OBJECT IDENTIFIER, - critical BOOLEAN DEFAULT FALSE, - extnValue ANY } </code> - <p>Each extension has a unique object identifier. An extension - with a <c>critical</c> value set to <c>TRUE</c><em>must</em> - be recognised by the reader of a certificate, or else the - certificate must be rejected. - </p> - <p>Extensions are divided into two groups: standard extensions - and internet certificate extensions. All extensions listed in - the table that follows are standard extensions, except for - <c>authorityInfoAccess</c> and <c>subjectInfoAccess</c>, which - are internet extensions. - </p> - <p>Depending on the object identifier the <c>extnValue</c> is - parsed into an appropriate welldefined structure. - </p> - <p>The following table shows the purpose of each extension, but - does not specify the structure. To see the structure consult - the <c>PKIX1Implicit88.asn1</c> module. - </p> - <table> - <row> - <cell align="left" valign="middle">authorityKeyIdentifier</cell> - <cell align="left" valign="middle">Used by to identify a certificate signed that has multiple signing keys. </cell> - </row> - <row> - <cell align="left" valign="middle">subjectKeyIdentifier</cell> - <cell align="left" valign="middle">Used to identify certificates that contain a public key. Must appear i CA certificates.</cell> - </row> - <row> - <cell align="left" valign="middle">keyUsage </cell> - <cell align="left" valign="middle">Defines the purpose of the certificate. Can be one or several of<c>digitalSignature</c>, <c>nonRepudiation</c>,<c>keyEncipherment</c>, <c>dataEncipherment</c>,<c>keyAgreement</c>, <c>keyCertSign</c>, <c>cRLSign</c>,<c>encipherOnly</c>, <c>decipherOnly</c>.</cell> - </row> - <row> - <cell align="left" valign="middle">privateKeyUsagePeriod </cell> - <cell align="left" valign="middle">Allows certificate issuer to provide a private key usage period to be short than the certificate usage period.</cell> - </row> - <row> - <cell align="left" valign="middle">certificatePolicies</cell> - <cell align="left" valign="middle">Contains one or more policy information terms indicating the policies under which the certificate has been issued.</cell> - </row> - <row> - <cell align="left" valign="middle">policyMappings</cell> - <cell align="left" valign="middle">Used i CA certificates. </cell> - </row> - <row> - <cell align="left" valign="middle">subjectAltName</cell> - <cell align="left" valign="middle">Allows additional identities to be bound the the subject. </cell> - </row> - <row> - <cell align="left" valign="middle">issuerAltName</cell> - <cell align="left" valign="middle">Allows additional identities to be bound the the issuer.</cell> - </row> - <row> - <cell align="left" valign="middle">subjectDirectoryAttributes</cell> - <cell align="left" valign="middle">Conveys identity attributes of the subject.</cell> - </row> - <row> - <cell align="left" valign="middle">basicConstraints</cell> - <cell align="left" valign="middle">Tells if the certificate holder is a CA or not.</cell> - </row> - <row> - <cell align="left" valign="middle">nameConstraints</cell> - <cell align="left" valign="middle">Used in CA certificates.</cell> - </row> - <row> - <cell align="left" valign="middle">policyConstraints</cell> - <cell align="left" valign="middle">Used in CA certificates.</cell> - </row> - <row> - <cell align="left" valign="middle">extKeyUsage</cell> - <cell align="left" valign="middle">Indicates for which purposed the public key may be used. </cell> - </row> - <row> - <cell align="left" valign="middle">cRLDistributionPoints</cell> - <cell align="left" valign="middle">Indicates how CRL (Certificate Revokation List) information is obtained.</cell> - </row> - <row> - <cell align="left" valign="middle">inhibitAnyPolicy</cell> - <cell align="left" valign="middle">Used i CA certificates.</cell> - </row> - <row> - <cell align="left" valign="middle">freshestCRL</cell> - <cell align="left" valign="middle">For CRLs.</cell> - </row> - <row> - <cell align="left" valign="middle">authorityInfoAccess</cell> - <cell align="left" valign="middle">How to access CA information of the issuer of the certificate.</cell> - </row> - <row> - <cell align="left" valign="middle">subjectInfoAccess</cell> - <cell align="left" valign="middle">How to access CA information of the subject of the certificate.</cell> - </row> - <tcaption>PKIX Extensions</tcaption> - </table> - </section> + <p>Certificate handling is now handled by the <c>public_key</c> application.</p> + <p> + DER encoded certificates returned by <c>ssl:peercert/1</c> can for example + be decoded by the <c>public_key:pkix_decode_cert/2</c> function. + </p> </section> </chapter> diff --git a/lib/ssl/doc/src/remember.xml b/lib/ssl/doc/src/remember.xml deleted file mode 100644 index 799627a33c..0000000000 --- a/lib/ssl/doc/src/remember.xml +++ /dev/null @@ -1,83 +0,0 @@ -<?xml version="1.0" encoding="latin1" ?> -<!DOCTYPE chapter SYSTEM "chapter.dtd"> - -<chapter> - <header> - <copyright> - <year>2003</year><year>2009</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - </legalnotice> - - <title>PKIX Certificates</title> - <prepared>UAB/F/P Peter Högfeldt</prepared> - <docno></docno> - <date>2003-06-09</date> - <rev>A</rev> - <file>pkix_certs.sgml</file> - </header> - - <section> - <title>Introduction to Certificates</title> - <p><em>Outline:</em></p> - <list type="bulleted"> - <item>SSL/TLS protocol - server must have certificate - -what - the the server sends to the client - client may verify the - server - server may ask client for certificate - what the - client sends to the server - server may then verify the client - - verification - certificate chains - root certificates - - public keys - key agreement - purpose of certificate - main - contents of certificate - contents have increased as time went - by - common file formats for certificates. - </item> - <item>private keys - password protection - key generation - file - formats. - </item> - <item>ssl_pkix and alternate decodings. - </item> - <item>Attribute Certificates (not used by SSL). - </item> - <item>Certificate requests - certificate authorities - signing of - certificates - certificate revocation lists. - </item> - <item>standards: ASN.1, X.509, X.520, PKIX, PKCS, PEM. - </item> - <item>incompatibilities between standards (X.509-1997 vs old) - the - ASN.1 problem of ANY, BIT STRING and OCTET STRING - the module - ssl_pkix. - </item> - <item>test suites: NIST - </item> - <item>Warnings: *creation* of trusted certificate (OpenSSL). - </item> - <item>Erlang SSL and certificates - </item> - <item>The need for seeding the random generator. See also John - S. Denker: High-Entropy Symbol Generator - (http://www.monmouth.com/~jsd). - </item> - <item>links to standards and documents. Books (Rescorla). - </item> - <item>ASN.1 crash course. - </item> - <item>Nagel algorithm. - </item> - </list> - <p>For an introduction to ASN.1 see <url href="http://asn1.elibel.tm.fr/">ASN.1 Information Site</url>. - </p> - </section> -</chapter> - - diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index 9b780b14ce..217eb791d0 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -347,39 +347,17 @@ </desc> </func> <func> - <name>peercert(Socket) -> </name> - <name>peercert(Socket, Opts) -> {ok, Cert} | {ok, Subject} | {error, Reason}</name> + <name>peercert(Socket) -> {ok, Cert} | {error, Reason}</name> <fsummary>Return the peer certificate.</fsummary> <type> <v>Socket = sslsocket()</v> - <v>Opts = [pkix | ssl | subject]()</v> - <v>Cert = term()()</v> + <v>Cert = binary()()</v> <v>Subject = term()()</v> </type> <desc> - <p><c>peercert(Cert)</c> is equivalent to <c>peercert(Cert, [])</c>. - </p> - <p>The form of the returned certificate depends on the - options. - </p> - <p>If the options list is empty the certificate is returned as - a DER encoded binary. - </p> - <p>The options <c>pkix</c> and <c>ssl</c> implies that the - certificate is returned as a parsed ASN.1 structure in the - form of an Erlang term. - </p> - <p>The <c>ssl</c> option gives a more elaborate return - structure, with more explicit information. In particular - object identifiers are replaced by atoms. - </p> - <p>The options <c>pkix</c>, and <c>ssl</c> are mutually - exclusive. - </p> - <p>The option <c>subject</c> implies that only the subject's - distinguished name part of the peer certificate is returned. - It can only be used together with the option <c>pkix</c> or - the option <c>ssl</c>.</p> + <p>Returns the DER encoded peer certificate, the certificate can be decoded with + <c>public_key:pkix_decode_cert/2</c>. + </p> </desc> </func> <func> @@ -719,8 +697,7 @@ <section> <title>SEE ALSO</title> - <p>gen_tcp(3), inet(3) - </p> + <p>gen_tcp(3), inet(3) public_key(3) </p> </section> </erlref> diff --git a/lib/stdlib/doc/src/gen_fsm.xml b/lib/stdlib/doc/src/gen_fsm.xml index f5d8b9bb48..739cd0bffd 100644 --- a/lib/stdlib/doc/src/gen_fsm.xml +++ b/lib/stdlib/doc/src/gen_fsm.xml @@ -729,6 +729,36 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 updated internal data.</p> </desc> </func> + <func> + <name>Module:format_status(normal, [PDict, StateData]) -> Status</name> + <fsummary>Optional function for providing a term describing the + current gen_fsm status.</fsummary> + <type> + <v>PDict = [{Key, Value}]</v> + <v>StateData = term()</v> + <v>Status = [term()]</v> + </type> + <desc> + <p><em>This callback is optional, so callback modules need not + export it. The gen_fsm module provides a default + implementation of this function that returns the callback + module state data.</em></p> + <p>This function is called by a gen_fsm process when one + of <seealso marker="sys#get_status/1">sys:get_status/1,2</seealso> + is invoked to get the gen_fsm status. A callback module + wishing to customise the <c>sys:get_status/1,2</c> return + value exports an instance of <c>format_status/2</c> that + returns a term describing the current status of the + gen_fsm.</p> + <p><c>PDict</c> is the current value of the gen_fsm's + process dictionary.</p> + <p><c>StateData</c> is the internal state data of the + gen_fsm.</p> + <p>The function should return <c>Status</c>, a list of one or + more terms that customise the details of the current state + and status of the gen_fsm.</p> + </desc> + </func> </funcs> <section> diff --git a/lib/stdlib/doc/src/gen_server.xml b/lib/stdlib/doc/src/gen_server.xml index 8496802259..30c04d1d52 100644 --- a/lib/stdlib/doc/src/gen_server.xml +++ b/lib/stdlib/doc/src/gen_server.xml @@ -598,6 +598,35 @@ gen_server:abcast -----> Module:handle_cast/2 <p>The function should return the updated internal state.</p> </desc> </func> + <func> + <name>Module:format_status(normal, [PDict, State]) -> Status</name> + <fsummary>Optional function for providing a term describing the + current gen_server status.</fsummary> + <type> + <v>PDict = [{Key, Value}]</v> + <v>State = term()</v> + <v>Status = [term()]</v> + </type> + <desc> + <p><em>This callback is optional, so callback modules need not + export it. The gen_server module provides a default + implementation of this function that returns the callback + module state.</em></p> + <p>This function is called by a gen_server process when one + of <seealso marker="sys#get_status/1">sys:get_status/1,2</seealso> + is invoked to get the gen_server status. A callback module + wishing to customise the <c>sys:get_status/1,2</c> return + value exports an instance of <c>format_status/2</c> that + returns a term describing the current status of the + gen_server.</p> + <p><c>PDict</c> is the current value of the gen_server's + process dictionary.</p> + <p><c>State</c> is the internal state of the gen_server.</p> + <p>The function should return <c>Status</c>, a list of one or + more terms that customise the details of the current state + and status of the gen_server.</p> + </desc> + </func> </funcs> <section> diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml index a395a8a415..10ead62073 100644 --- a/lib/stdlib/doc/src/sys.xml +++ b/lib/stdlib/doc/src/sys.xml @@ -4,23 +4,21 @@ <erlref> <header> <copyright> - <year>1996</year> - <year>2007</year> - <holder>Ericsson AB, All Rights Reserved</holder> + <year>1996</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - The Initial Developer of the Original Code is Ericsson AB. + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + </legalnotice> <title>sys</title> @@ -237,6 +235,17 @@ </type> <desc> <p>Gets the status of the process.</p> + <p>The value of <c>Misc</c> varies for different types of + processes. For example, a <c>gen_server</c> process returns + the callback module's state, and a <c>gen_fsm</c> process + returns information such as its current state name. Callback + modules for <c>gen_server</c> and <c>gen_fsm</c> can also + customise the value of <c>Misc</c> by exporting + a <c>format_status/2</c> function that contributes + module-specific information; + see <seealso marker="gen_server#format_status/2">gen_server:format_status/2</seealso> + and <seealso marker="gen_fsm#format_status/2">gen_fsm:format_status/2</seealso> + for more details.</p> </desc> </func> <func> diff --git a/lib/stdlib/src/c.erl b/lib/stdlib/src/c.erl index 9e4cec5db2..433833e233 100644 --- a/lib/stdlib/src/c.erl +++ b/lib/stdlib/src/c.erl @@ -197,7 +197,9 @@ nc(File, Opts0) when is_list(Opts0) -> Opts = Opts0 ++ [report_errors, report_warnings], case compile:file(File, Opts) of {ok,Mod} -> - Fname = concat([File, code:objfile_extension()]), + Dir = outdir(Opts), + Obj = filename:basename(File, ".erl") ++ code:objfile_extension(), + Fname = filename:join(Dir, Obj), case file:read_file(Fname) of {ok,Bin} -> rpc:eval_everywhere(code,load_binary,[Mod,Fname,Bin]), diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl index f3775f967a..ba0275ae2b 100644 --- a/lib/stdlib/src/gen_fsm.erl +++ b/lib/stdlib/src/gen_fsm.erl @@ -603,7 +603,12 @@ get_msg(Msg) -> Msg. format_status(Opt, StatusData) -> [PDict, SysState, Parent, Debug, [Name, StateName, StateData, Mod, _Time]] = StatusData, - Header = lists:concat(["Status for state machine ", Name]), + NameTag = if is_pid(Name) -> + pid_to_list(Name); + is_atom(Name) -> + Name + end, + Header = lists:concat(["Status for state machine ", NameTag]), Log = sys:get_debug(log, Debug, []), Specfic = case erlang:function_exported(Mod, format_status, 2) of diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 3df6f4bb90..7ea7de8d58 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -334,6 +334,10 @@ obsolete_1(ssl_pkix, decode_cert_file, A) when A =:= 1; A =:= 2 -> {deprecated,"deprecated (will be removed in R14B); use public_key:pem_to_der/1 and public_key:pkix_decode_cert/2 instead"}; obsolete_1(ssl_pkix, decode_cert, A) when A =:= 1; A =:= 2 -> {deprecated,{public_key,pkix_decode_cert,2},"R14B"}; + +%% Added in R13B04. +obsolete_1(erlang, concat_binary, 1) -> + {deprecated,{erlang,list_to_binary,1},"R14B"}; obsolete_1(_, _, _) -> no. diff --git a/lib/stdlib/src/sys.erl b/lib/stdlib/src/sys.erl index e0f2dbcd3c..12209c16d7 100644 --- a/lib/stdlib/src/sys.erl +++ b/lib/stdlib/src/sys.erl @@ -245,8 +245,17 @@ do_cmd(SysState, Other, _Parent, _Mod, Debug, Misc) -> {SysState, {error, {unknown_system_msg, Other}}, Debug, Misc}. get_status(SysState, Parent, Mod, Debug, Misc) -> + PDict = get(), + FmtMisc = + case erlang:function_exported(Mod, format_status, 2) of + true -> + FmtArgs = [PDict, SysState, Parent, Debug, Misc], + Mod:format_status(normal, FmtArgs); + _ -> + Misc + end, {status, self(), {module, Mod}, - [get(), SysState, Parent, Debug, Misc]}. + [PDict, SysState, Parent, Debug, FmtMisc]}. %%----------------------------------------------------------------- %% These are the system debug commands. diff --git a/lib/stdlib/test/c_SUITE.erl b/lib/stdlib/test/c_SUITE.erl index 5608d73d19..2edbc7ab4c 100644 --- a/lib/stdlib/test/c_SUITE.erl +++ b/lib/stdlib/test/c_SUITE.erl @@ -18,15 +18,16 @@ %% -module(c_SUITE). -export([all/1]). --export([c_1/1, c_2/1, c_3/1, c_4/1, memory/1]). +-export([c_1/1, c_2/1, c_3/1, c_4/1, nc_1/1, nc_2/1, nc_3/1, nc_4/1, + memory/1]). -include("test_server.hrl"). --import(c, [c/2]). +-import(c, [c/2, nc/2]). all(doc) -> ["Test cases for the 'c' module."]; all(suite) -> - [c_1, c_2, c_3, c_4, memory]. + [c_1, c_2, c_3, c_4, nc_1, nc_2, nc_3, nc_4, memory]. %%% Write output to a directory other than current directory: @@ -34,7 +35,7 @@ c_1(doc) -> ["Checks that c:c works also with option 'outdir' [ticket OTP-1209]."]; c_1(suite) -> []; -c_1(Config) when list(Config) -> +c_1(Config) when is_list(Config) -> ?line R = filename:join(?config(data_dir, Config), "m.erl"), ?line W = ?config(priv_dir, Config), ?line Result = c(R,[{outdir,W}]), @@ -44,7 +45,7 @@ c_2(doc) -> ["Checks that c:c works also with option 'outdir' [ticket OTP-1209]."]; c_2(suite) -> []; -c_2(Config) when list(Config) -> +c_2(Config) when is_list(Config) -> ?line R = filename:join(?config(data_dir, Config), "m"), ?line W = ?config(priv_dir, Config), ?line Result = c(R,[{outdir,W}]), @@ -59,7 +60,7 @@ c_3(doc) -> "directory). [ticket OTP-1209]."]; c_3(suite) -> []; -c_3(Config) when list(Config) -> +c_3(Config) when is_list(Config) -> ?line R = filename:join(?config(data_dir, Config), "m.erl"), ?line W = ?config(priv_dir, Config), ?line file:set_cwd(W), @@ -71,18 +72,68 @@ c_4(doc) -> "directory). [ticket OTP-1209]."]; c_4(suite) -> []; -c_4(Config) when list(Config) -> +c_4(Config) when is_list(Config) -> ?line R = filename:join(?config(data_dir, Config), "m"), ?line W = ?config(priv_dir, Config), ?line file:set_cwd(W), ?line Result = c(R,[{outdir,W}]), ?line {ok, m} = Result. +%%% Write output to a directory other than current directory: + +nc_1(doc) -> + ["Checks that c:nc works also with option 'outdir'."]; +nc_1(suite) -> + []; +nc_1(Config) when is_list(Config) -> + ?line R = filename:join(?config(data_dir, Config), "m.erl"), + ?line W = ?config(priv_dir, Config), + ?line Result = nc(R,[{outdir,W}]), + ?line {ok, m} = Result. + +nc_2(doc) -> + ["Checks that c:nc works also with option 'outdir'."]; +nc_2(suite) -> + []; +nc_2(Config) when is_list(Config) -> + ?line R = filename:join(?config(data_dir, Config), "m"), + ?line W = ?config(priv_dir, Config), + ?line Result = nc(R,[{outdir,W}]), + ?line {ok, m} = Result. + + +%%% Put results in current directory (or rather, change current dir +%%% to the output dir): + +nc_3(doc) -> + ["Checks that c:nc works also with option 'outdir' (same as current" + "directory)."]; +nc_3(suite) -> + []; +nc_3(Config) when is_list(Config) -> + ?line R = filename:join(?config(data_dir, Config), "m.erl"), + ?line W = ?config(priv_dir, Config), + ?line file:set_cwd(W), + ?line Result = nc(R,[{outdir,W}]), + ?line {ok, m} = Result. + +nc_4(doc) -> + ["Checks that c:nc works also with option 'outdir' (same as current" + "directory)."]; +nc_4(suite) -> + []; +nc_4(Config) when is_list(Config) -> + ?line R = filename:join(?config(data_dir, Config), "m"), + ?line W = ?config(priv_dir, Config), + ?line file:set_cwd(W), + ?line Result = nc(R,[{outdir,W}]), + ?line {ok, m} = Result. + memory(doc) -> ["Checks that c:memory/[0,1] returns consistent results."]; memory(suite) -> []; -memory(Config) when list(Config) -> +memory(Config) when is_list(Config) -> try ?line ML = c:memory(), ?line T = mget(total, ML), @@ -112,5 +163,5 @@ mget(K, L) -> ?line test_v(V). % Help function for c_SUITE:memory/1 -test_v(V) when integer(V) -> +test_v(V) when is_integer(V) -> ?line V. diff --git a/lib/stdlib/test/gen_fsm_SUITE.erl b/lib/stdlib/test/gen_fsm_SUITE.erl index 62f8b2f9dd..23c1d9a193 100644 --- a/lib/stdlib/test/gen_fsm_SUITE.erl +++ b/lib/stdlib/test/gen_fsm_SUITE.erl @@ -30,7 +30,7 @@ -export([shutdown/1]). --export([sys/1, sys1/1]). +-export([sys/1, sys1/1, call_format_status/1]). -export([hibernate/1,hiber_idle/3,hiber_wakeup/3,hiber_idle/2,hiber_wakeup/2]). @@ -42,7 +42,7 @@ % The gen_fsm behaviour -export([init/1, handle_event/3, handle_sync_event/4, terminate/3, - handle_info/3]). + handle_info/3, format_status/2]). -export([idle/2, idle/3, timeout/2, wfor_conf/2, wfor_conf/3, @@ -305,7 +305,7 @@ shutdown(Config) when is_list(Config) -> ok. -sys(suite) -> [sys1]. +sys(suite) -> [sys1, call_format_status]. sys1(Config) when is_list(Config) -> ?line {ok, Pid} = @@ -317,6 +317,13 @@ sys1(Config) when is_list(Config) -> ?line sys:resume(Pid), ?line stop_it(Pid). +call_format_status(Config) when is_list(Config) -> + ?line {ok, Pid} = gen_fsm:start(gen_fsm_SUITE, [], []), + ?line Status = sys:get_status(Pid), + ?line {status, Pid, _Mod, [_PDict, running, _Parent, _, Data]} = Status, + ?line [format_status_called | _] = lists:reverse(Data), + ?line stop_it(Pid). + %% Hibernation hibernate(suite) -> []; @@ -836,3 +843,6 @@ handle_sync_event(stop_shutdown_reason, _From, _State, Data) -> {stop, {shutdown,reason}, {shutdown,reason}, Data}; handle_sync_event({get, _Pid}, _From, State, Data) -> {reply, {state, State, Data}, State, Data}. + +format_status(_Opt, [_Pdict, _StateData]) -> + [format_status_called]. diff --git a/lib/stdlib/test/gen_server_SUITE.erl b/lib/stdlib/test/gen_server_SUITE.erl index 86a5a65ba3..6efdce78a1 100644 --- a/lib/stdlib/test/gen_server_SUITE.erl +++ b/lib/stdlib/test/gen_server_SUITE.erl @@ -30,7 +30,7 @@ call_remote_n1/1, call_remote_n2/1, call_remote_n3/1, spec_init/1, spec_init_local_registered_parent/1, spec_init_global_registered_parent/1, - otp_5854/1, hibernate/1, otp_7669/1 + otp_5854/1, hibernate/1, otp_7669/1, call_format_status/1 ]). % spawn export @@ -42,7 +42,7 @@ % The gen_server behaviour -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2]). + handle_info/2, terminate/2, format_status/2]). all(suite) -> [start, crash, call, cast, cast_fast, info, @@ -51,7 +51,7 @@ all(suite) -> call_remote_n2, call_remote_n3, spec_init, spec_init_local_registered_parent, spec_init_global_registered_parent, - otp_5854,hibernate,otp_7669]. + otp_5854, hibernate, otp_7669, call_format_status]. -define(default_timeout, ?t:minutes(1)). @@ -851,7 +851,7 @@ otp_5854(Config) when is_list(Config) -> ok. %% If initialization fails (with ignore or {stop,Reason}), -%% make sure that the process is not registered when gen_sever:start() +%% make sure that the process is not registered when gen_server:start() %% returns. otp_7669(Config) when is_list(Config) -> @@ -887,6 +887,24 @@ do_otp_7669_stop() -> ?MODULE, stop, []), ?line undefined = global:whereis_name(?MODULE). +%% Verify that sys:get_status correctly calls our format_status/2 fun +%% +call_format_status(suite) -> + []; +call_format_status(doc) -> + ["Test that sys:get_status/1,2 calls format_status/2"]; +call_format_status(Config) when is_list(Config) -> + ?line {ok, Pid} = gen_server:start_link({local, call_format_status}, + gen_server_SUITE, [], []), + ?line Status1 = sys:get_status(call_format_status), + ?line {status, Pid, _Mod, [_PDict, running, _Parent, _, Data1]} = Status1, + ?line [format_status_called | _] = lists:reverse(Data1), + ?line Status2 = sys:get_status(call_format_status, 5000), + ?line {status, Pid, _Mod, [_PDict, running, _Parent, _, Data2]} = Status2, + ?line [format_status_called | _] = lists:reverse(Data2), + ok. + + %%-------------------------------------------------------------- %% Help functions to spec_init_* start_link(Init, Options) -> @@ -1046,4 +1064,5 @@ terminate({From, stopped_info}, _State) -> terminate(_Reason, _State) -> ok. - +format_status(_Opt, [_PDict, _State]) -> + [format_status_called]. diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml index 59f600145e..e6c074cc7d 100644 --- a/lib/tools/doc/src/notes.xml +++ b/lib/tools/doc/src/notes.xml @@ -30,6 +30,21 @@ </header> <p>This document describes the changes made to the Tools application.</p> +<section><title>Tools 2.6.5.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>A bug concerning bit comprehensions has been fixed + in Cover. The bug was introduced in R13B03. + (Thanks to Matthew Sackman.)</p> + <p>Own Id: OTP-8340</p> + </item> + </list> + </section> + +</section> + <section><title>Tools 2.6.5</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el index f623e3a1ee..4fc4826238 100644 --- a/lib/tools/emacs/erlang.el +++ b/lib/tools/emacs/erlang.el @@ -72,7 +72,7 @@ ;; Variables: -(defconst erlang-version "2.6.1" +(defconst erlang-version "2.6.2" "The version number of Erlang mode.") (defvar erlang-root-dir nil @@ -3792,9 +3792,9 @@ Value is list (stack token-start token-type in-what)." ;; Clause end ((= (following-char) ?\;) - (if (and stack (and (eq (car (car stack)) 'when) - (eq (car (car (cdr (cdr stack)))) 'spec))) - (erlang-pop stack)) + (if (eq (car (car (last stack))) 'spec) + (while (memq (car (car stack)) '(when ::)) + (erlang-pop stack))) (if (and stack (eq (car (car stack)) '->)) (erlang-pop stack)) (forward-char 1)) @@ -3955,15 +3955,16 @@ Return nil if inside string, t if in a comment." (nth 2 stack-top)))) (t (goto-char (nth 1 stack-top)) - (cond ((looking-at "[({]\\s *\\($\\|%\\)") - ;; Line ends with parenthesis. - (erlang-indent-parenthesis (nth 2 stack-top))) - (t - ;; Indent to the same column as the first - ;; argument. - (goto-char (1+ (nth 1 stack-top))) - (skip-chars-forward " \t") - (current-column)))))) + (let ((base (cond ((looking-at "[({]\\s *\\($\\|%\\)") + ;; Line ends with parenthesis. + (erlang-indent-parenthesis (nth 2 stack-top))) + (t + ;; Indent to the same column as the first + ;; argument. + (goto-char (1+ (nth 1 stack-top))) + (skip-chars-forward " \t") + (current-column))))) + (erlang-indent-standard indent-point token base 't))))) ;; ((eq (car stack-top) '<<) ;; Element of binary (possible comprehension) expression, @@ -4047,33 +4048,8 @@ Return nil if inside string, t if in a comment." 0)) base)) ;; old catch (t - ;; Look at last thing to see how we are to move relative - ;; to the base. - (goto-char token) - (cond ((looking-at "||\\|,\\|->") - base) - ((erlang-at-keyword) - (+ (current-column) erlang-indent-level)) - ((or (= (char-syntax (following-char)) ?.) - (erlang-at-operator)) - (+ base erlang-indent-level)) - (t - (goto-char indent-point) - (cond ((memq (following-char) '(?\( ?{)) - ;; Function application or record. - (+ (erlang-indent-find-preceding-expr) - erlang-argument-indent)) - ;; Empty line, or end; treat it as the end of - ;; the block. (Here we have a choice: should - ;; the user be forced to reindent continued - ;; lines, or should the "end" be reindented?) - - ;; Avoid treating comments a continued line. - ((= (following-char) ?%) - base) - ;; Continued line (e.g. line beginning - ;; with an operator.) - (t (+ base erlang-indent-level))))))))) + (erlang-indent-standard indent-point token base 'nil) + )))) )) ((eq (car stack-top) 'when) (goto-char (nth 1 stack-top)) @@ -4105,21 +4081,55 @@ Return nil if inside string, t if in a comment." (+ 2 (nth 2 stack-top))) ((looking-at "::[^_a-zA-Z0-9]") (nth 2 stack-top)) - (t - (goto-char (nth 1 stack-top)) - (cond ((looking-at "::\\s *\\($\\|%\\)") - ;; Line ends with :: - (+ (erlang-indent-find-preceding-expr 2) - erlang-argument-indent)) - ;; (* 2 erlang-indent-level)) - (t - ;; Indent to the same column as the first - ;; argument. - (goto-char (+ 2 (nth 1 stack-top))) - (skip-chars-forward " \t") - (current-column)))))) + (t + (let ((start-alternativ (if (looking-at "|") 2 0))) + (goto-char (nth 1 stack-top)) + (- (cond ((looking-at "::\\s *\\($\\|%\\)") + ;; Line ends with :: + (if (eq (car (car (last stack))) 'spec) + (+ (erlang-indent-find-preceding-expr 1) + erlang-argument-indent) + (+ (erlang-indent-find-preceding-expr 2) + erlang-argument-indent))) + (t + ;; Indent to the same column as the first + ;; argument. + (goto-char (+ 2 (nth 1 stack-top))) + (skip-chars-forward " \t") + (current-column))) start-alternativ))))) ))) +(defun erlang-indent-standard (indent-point token base inside-parenthesis) + "Standard indent when in blocks or tuple or arguments. + Look at last thing to see in what state we are, move relative to the base." + (goto-char token) + (cond ((looking-at "||\\|,\\|->\\||") + base) + ((erlang-at-keyword) + (+ (current-column) erlang-indent-level)) + ((or (= (char-syntax (following-char)) ?.) + (erlang-at-operator)) + (+ base erlang-indent-level)) + (t + (goto-char indent-point) + (cond ((memq (following-char) '(?\( ?{)) + ;; Function application or record. + (+ (erlang-indent-find-preceding-expr) + erlang-argument-indent)) + ;; Empty line, or end; treat it as the end of + ;; the block. (Here we have a choice: should + ;; the user be forced to reindent continued + ;; lines, or should the "end" be reindented?) + + ;; Avoid treating comments a continued line. + ((= (following-char) ?%) + base) + ;; Continued line (e.g. line beginning + ;; with an operator.) + (t + (if (or (erlang-at-operator) (not inside-parenthesis)) + (+ base erlang-indent-level) + base)))))) (defun erlang-indent-find-base (stack indent-point &optional offset skip) "Find the base column for current stack." @@ -4946,6 +4956,7 @@ non-whitespace characters following the point on the current line." (setq erlang-electric-newline-inhibit nil) (setq erlang-electric-newline-inhibit t) (undo-boundary) + (erlang-indent-line) (end-of-line) (newline) (condition-case nil diff --git a/lib/tools/emacs/test.erl.indented b/lib/tools/emacs/test.erl.indented index b2cc23b92b..1ccced9177 100644 --- a/lib/tools/emacs/test.erl.indented +++ b/lib/tools/emacs/test.erl.indented @@ -44,6 +44,24 @@ b }). +-record(record3, {a = 8#42423 bor + 8#4234, + b = 8#5432 + bor 2#1010101 + c = 123 + + 234, + d}). + +-record(record4, { + a = 8#42423 bor + 8#4234, + b = 8#5432 + bor 2#1010101 + c = 123 + + 234, + d}). + + -define(MACRO_1, macro). -define(MACRO_2(_), macro). @@ -51,8 +69,10 @@ -type ann() :: Var :: integer(). -type ann2() :: Var :: - 'return' | 'return_white_spaces' | 'return_comments' - | 'text' | ann(). + 'return' + | 'return_white_spaces' + | 'return_comments' + | 'text' | ann(). -type paren() :: (ann2()). -type t1() :: atom(). @@ -89,7 +109,7 @@ fun((nonempty_maybe_improper_list('integer', any())| 1|2|3|a|b|<<_:3,_:_*14>>|integer()) -> nonempty_maybe_improper_list('integer', any())| - 1|2|3|a|b|<<_:3,_:_*14>>|integer()). + 1|2|3|a|b|<<_:3,_:_*14>>|integer()). -type t20() :: [t19(), ...]. -type t21() :: tuple(). -type t21(A) :: A. @@ -110,7 +130,28 @@ (t24()) -> t24() when is_subtype(t24(), atom()), is_subtype(t24(), t14()), is_subtype(t24(), t4()). + +-spec over(I :: integer()) -> R1 :: foo:typen(); + (A :: atom()) -> R2 :: foo:atomen(); + (T :: tuple()) -> R3 :: bar:typen(). + -spec mod:t2() -> any(). + +-spec handle_cast(Cast :: {'exchange', node(), [[name(),...]]} + | {'del_member', name(), pid()}, + #state{}) -> {'noreply', #state{}}. + +-spec handle_cast(Cast :: + {'exchange', node(), [[name(),...]]} + | {'del_member', name(), pid()}, + #state{}) -> {'noreply', #state{}}. + + +-spec get_closest_pid(term()) -> + Return :: pid() + | {'error', {'no_process', term()} + | {'no_such_group', term()}}. + -opaque attributes_data() :: [{'column', column()} | {'line', info_line()} | {'text', string()}] | {line(),column()}. @@ -277,7 +318,10 @@ indent_basics(X, Y, Z) c ), - + call(2#42423 bor + #4234, + 2#5432, + other_arg), ok; indent_basics(Xlongname, #struct{a=Foo, @@ -359,7 +403,7 @@ indent_icr(Z) -> % icr = if case receive X = 43 div 4, foo(X) end, - receive + receive {Z,_,_} -> X = 43 div 4, foo(X); @@ -491,7 +535,7 @@ indent_catch() -> B = catch oskar(X), A = catch (baz + - bax), + bax), catch foo(), C = catch B + diff --git a/lib/tools/emacs/test.erl.orig b/lib/tools/emacs/test.erl.orig index 773998a4c6..9b4203120b 100644 --- a/lib/tools/emacs/test.erl.orig +++ b/lib/tools/emacs/test.erl.orig @@ -44,6 +44,24 @@ b }). +-record(record3, {a = 8#42423 bor + 8#4234, + b = 8#5432 + bor 2#1010101 + c = 123 + +234, + d}). + +-record(record4, { + a = 8#42423 bor + 8#4234, + b = 8#5432 + bor 2#1010101 + c = 123 + + 234, + d}). + + -define(MACRO_1, macro). -define(MACRO_2(_), macro). @@ -51,8 +69,10 @@ -type ann() :: Var :: integer(). -type ann2() :: Var :: - 'return' | 'return_white_spaces' | 'return_comments' - | 'text' | ann(). + 'return' + | 'return_white_spaces' + | 'return_comments' + | 'text' | ann(). -type paren() :: (ann2()). -type t1() :: atom(). @@ -110,7 +130,28 @@ t15(),t20(),t21(), t22(),t25()}. (t24()) -> t24() when is_subtype(t24(), atom()), is_subtype(t24(), t14()), is_subtype(t24(), t4()). + +-spec over(I :: integer()) -> R1 :: foo:typen(); + (A :: atom()) -> R2 :: foo:atomen(); + (T :: tuple()) -> R3 :: bar:typen(). + -spec mod:t2() -> any(). + +-spec handle_cast(Cast :: {'exchange', node(), [[name(),...]]} + | {'del_member', name(), pid()}, + #state{}) -> {'noreply', #state{}}. + +-spec handle_cast(Cast :: + {'exchange', node(), [[name(),...]]} + | {'del_member', name(), pid()}, + #state{}) -> {'noreply', #state{}}. + + +-spec get_closest_pid(term()) -> + Return :: pid() + | {'error', {'no_process', term()} + | {'no_such_group', term()}}. + -opaque attributes_data() :: [{'column', column()} | {'line', info_line()} | {'text', string()}] | {line(),column()}. @@ -277,7 +318,10 @@ Y =:= 4711 -> c ), - + call(2#42423 bor + #4234, + 2#5432, + other_arg), ok; indent_basics(Xlongname, #struct{a=Foo, diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl index aff3927db3..1a7ebdc69a 100644 --- a/lib/tools/src/cover.erl +++ b/lib/tools/src/cover.erl @@ -1685,8 +1685,8 @@ munge_expr({lc,Line,Expr,Qs}, Vars) -> {MungedQs, Vars3} = munge_qualifiers(Qs, Vars2), {{lc,Line,MungedExpr,MungedQs}, Vars3}; munge_expr({bc,Line,Expr,Qs}, Vars) -> - {bin,BLine,[{bin_element,EL,Val,Sz,TSL}]} = Expr, - Expr2 = {bin,BLine,[{bin_element,EL,?BLOCK1(Val),Sz,TSL}]}, + {bin,BLine,[{bin_element,EL,Val,Sz,TSL}|Es]} = Expr, + Expr2 = {bin,BLine,[{bin_element,EL,?BLOCK1(Val),Sz,TSL}|Es]}, {MungedExpr,Vars2} = munge_expr(Expr2, Vars), {MungedQs, Vars3} = munge_qualifiers(Qs, Vars2), {{bc,Line,MungedExpr,MungedQs}, Vars3}; diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk index 644e8b719b..13cf5af9f5 100644 --- a/lib/tools/vsn.mk +++ b/lib/tools/vsn.mk @@ -16,4 +16,4 @@ # # %CopyrightEnd% -TOOLS_VSN = 2.6.5 +TOOLS_VSN = 2.6.5.1 diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf index df154f0125..4a646650ea 100644 --- a/lib/wx/api_gen/wxapi.conf +++ b/lib/wx/api_gen/wxapi.conf @@ -985,7 +985,9 @@ {class, wxFileDialog, wxDialog, [{skip, [{wxFileDialog,0}]}], ['wxFileDialog','~wxFileDialog','GetDirectory','GetFilename', {'GetFilenames',[{"files", out}]}, - 'GetFilterIndex','GetMessage','GetPath','GetPaths','GetWildcard', + 'GetFilterIndex','GetMessage','GetPath', + {'GetPaths', [{"paths", out}]}, + 'GetWildcard', 'SetDirectory','SetFilename','SetFilterIndex','SetMessage','SetPath', 'SetWildcard']}. diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp index cb662fc91b..ccbacce9b9 100644 --- a/lib/wx/c_src/gen/wxe_funcs.cpp +++ b/lib/wx/c_src/gen/wxe_funcs.cpp @@ -20582,19 +20582,11 @@ case wxFileDialog_GetPath: { // wxFileDialog::GetPath break; } case wxFileDialog_GetPaths: { // wxFileDialog::GetPaths - wxFileDialog *This = (wxFileDialog *) getPtr(bp,memenv); bp += 4; - int * pathsLen = (int *) bp; bp += 4; wxArrayString paths; - int pathsASz = 0, * pathsTemp; - for(int i=0; i < *pathsLen; i++) { - pathsTemp = (int *) bp; bp += 4; - paths.Add(wxString(bp, wxConvUTF8)); - bp += *pathsTemp; - pathsASz += *pathsTemp+4; - } - bp += (8-((0+ pathsASz) & 7 )) & 7; + wxFileDialog *This = (wxFileDialog *) getPtr(bp,memenv); bp += 4; if(!This) throw wxe_badarg(0); This->GetPaths(paths); + rt.add(paths); break; } case wxFileDialog_GetWildcard: { // wxFileDialog::GetWildcard diff --git a/lib/wx/configure.in b/lib/wx/configure.in index 7dc8d6e831..2b47f86baa 100755 --- a/lib/wx/configure.in +++ b/lib/wx/configure.in @@ -1,3 +1,21 @@ +dnl Process this file with autoconf to produce a configure script. -*-m4-*- + +dnl %CopyrightBegin% +dnl +dnl Copyright Ericsson AB 2008-2009. All Rights Reserved. +dnl +dnl The contents of this file are subject to the Erlang Public License, +dnl Version 1.1, (the "License"); you may not use this file except in +dnl compliance with the License. You should have received a copy of the +dnl Erlang Public License along with this software. If not, it can be +dnl retrieved online at http://www.erlang.org/. +dnl +dnl Software distributed under the License is distributed on an "AS IS" +dnl basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +dnl the License for the specific language governing rights and limitations +dnl under the License. +dnl +dnl %CopyrightEnd% AC_INIT() @@ -101,7 +119,7 @@ AC_SUBST(MIXED_CYGWIN) ## Check that we are in 32 bits mode on darwin ## (wxWidgets require that it currently uses 32-bits Carbon) ## Otherwise skip building wxErlang -AC_CHECK_SIZEOF(void *, 4) +AC_CHECK_SIZEOF(void *) case $ac_cv_sizeof_void_p-$host_os in 8-darwin*) diff --git a/lib/wx/doc/src/Makefile b/lib/wx/doc/src/Makefile index d18daa753a..fd9f7441a3 100644 --- a/lib/wx/doc/src/Makefile +++ b/lib/wx/doc/src/Makefile @@ -31,12 +31,6 @@ GenMods = $(shell ls ../../src/gen | grep 'wx[A-Z].*\.erl') \ glu.erl \ gl.erl -# GenMods = \ -# wx_misc.erl \ -# glu.erl \ -# gl.erl - - ModsNoExt = $(ErlMods:%.erl=%) $(GenMods:%.erl=%) ifneq ($(INSIDE_ERLSRC),true) @@ -126,9 +120,9 @@ gifs: $(GIF_FILES:%=$(HTMLDIR)/%) xml: $(XML_REF3_FILES) $(XML_CHAPTER_FILES) -ref_man.xml: ref_man.src.xml +ref_man.xml: ref_man.xml.src @echo Preparing ref_man.xml - @cat ref_man.src.xml > ref_man.xml + @cat ref_man.xml.src > ref_man.xml @for d in $(ModsNoExt); do \ echo " <xi:include href=\"$$d.xml\"/>" >> ref_man.xml ; \ done diff --git a/lib/wx/doc/src/ref_man.src.xml b/lib/wx/doc/src/ref_man.xml.src index 77fd16b050..77fd16b050 100644 --- a/lib/wx/doc/src/ref_man.src.xml +++ b/lib/wx/doc/src/ref_man.xml.src diff --git a/lib/wx/src/gen/wxFileDialog.erl b/lib/wx/src/gen/wxFileDialog.erl index 22b39aa150..efe1ff57f3 100644 --- a/lib/wx/src/gen/wxFileDialog.erl +++ b/lib/wx/src/gen/wxFileDialog.erl @@ -31,7 +31,7 @@ -module(wxFileDialog). -include("wxe.hrl"). -export([destroy/1,getDirectory/1,getFilename/1,getFilenames/1,getFilterIndex/1, - getMessage/1,getPath/1,getPaths/2,getWildcard/1,new/1,new/2,setDirectory/2, + getMessage/1,getPath/1,getPaths/1,getWildcard/1,new/1,new/2,setDirectory/2, setFilename/2,setFilterIndex/2,setMessage/2,setPath/2,setWildcard/2]). %% inherited exports @@ -152,15 +152,12 @@ getPath(#wx_ref{type=ThisT,ref=ThisRef}) -> wxe_util:call(?wxFileDialog_GetPath, <<ThisRef:32/?UI>>). -%% @spec (This::wxFileDialog(), Paths::[[string()]]) -> ok +%% @spec (This::wxFileDialog()) -> [[string()]] %% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialoggetpaths">external documentation</a>. -getPaths(#wx_ref{type=ThisT,ref=ThisRef},Paths) - when is_list(Paths) -> +getPaths(#wx_ref{type=ThisT,ref=ThisRef}) -> ?CLASS(ThisT,wxFileDialog), - Paths_UCA = [unicode:characters_to_binary([PathsTemp,0]) || - PathsTemp <- Paths], - wxe_util:cast(?wxFileDialog_GetPaths, - <<ThisRef:32/?UI,(length(Paths_UCA)):32/?UI, (<< <<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>|| UC_Str <- Paths_UCA>>)/binary, 0:(((8- ((0 + lists:sum([byte_size(S)+4||S<-Paths_UCA])) band 16#7)) band 16#7))/unit:8>>). + wxe_util:call(?wxFileDialog_GetPaths, + <<ThisRef:32/?UI>>). %% @spec (This::wxFileDialog()) -> string() %% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxfiledialog.html#wxfiledialoggetwildcard">external documentation</a>. |